mecab-koで簡易的な韓日機械翻訳を作る
本件は ひとり開発 Advent Calendar 2019 - Qiita 7日目にエントリーしています。
はじめに
私は海外野球のニュース記事を読みたいがために、自分用の機械翻訳を作ってます。
現在は韓国語のみで、あくまで野球ニュース用です。
まあ精度はよくないですが、野球用語や独特の表現を訳すところにフォーカスしており、
後述しますがmecab-koという韓国語用の形態素解析ツールを利用しています。
https://bitbucket.org/eunjeon/mecab-ko/
2月にとりあえず作って以降、定期的に辞書をいじっては訳を改善、、
また辞書をいじったり、追加したりして訳を改善している最中です。
正直言って、ルールベースはやるもんじゃないなと思いました
経緯
私は海外野球の情報(特に順位表や試合速報・結果)をよく見ていて、
主に以下のサイトをよく見ます。
サイト | 国/地域 | 言語 | URL |
---|---|---|---|
MLB | アメリカ | 英語 | https://www.mlb.com/ |
CPBL | 台湾 | 中国語(繁体字) | http://www.cpbl.com.tw/ |
KBO | 韓国 | 韓国語 | https://www.koreabaseball.com/ |
WBSC | 国際大会 | 英語など6ヶ国語 | https://www.wbsc.org/ |
ブログやtwitterなどで日本語で情報発信してくれている方もいて大変助かってますが、
なるべく一次情報を情報収集したい願望があります。
Google翻訳などのWEBサービスは野球に特化しているわけではないので、
ちょいちょい野球用語や独特の言い回しの訳が変なときがあって、
どうしても????ってなるときがあるんですよね。
たとえば以下、(自分で作った翻訳プログラムの運用中に書いたツイートしたものですが)
野球の試合中、しかも9回裏に試合の勝敗が決まる重要な場面でギターを出す人はいないです。「선발 박진우의 역투와 9회말 손시헌의 끝내기타를 앞세워」
— gayou (@gayou) 2019年6月10日
Google翻訳:”先発パク・ジヌの力投と9回裏孫時憲の素晴らしいギターを前面に出して”
野球の試合に唐突にギターが出てくるわけないだろ。https://t.co/AOyQmsBgzF
ここは「先発パク・ジヌの力投と9回裏ソン・シホンのサヨナラ打が出て~」と訳すのが的確です。
振り逃げホイル、、、なんて聞いたことないので、NAVERでダイジェスト映像を見たところ、” 7회초 선두타자 신본기가 스트라이크 낫아웃 포일로 출루했고,”
— gayou (@gayou) 2019年7月2日
→ 7回表先頭打者シン・ボンギがストライク振り逃げホイルで出塁して、
振り逃げホイル??https://t.co/RBIOJ4FqJv#baseball #kbo
”捕逸”(捕手がボールをキャッチし損ねて後ろに逸らすこと)でした。
※ダイジェスト映像はこちら(サムネに写っている選手は、元ソフトバンクのイ・デホ) sports.news.naver.com
とまあ他にもありますが、”捕逸”のように一般的でない用語や表現はどのジャンルにもあると思います。
そんなこんなで、海外野球のニュース記事を日本語で読みたいがために、
野球ニュース用の機械翻訳を作ろうと思いたったのでした。
目標
自分で作るにあたって、ゆるっとした目標を立てました。
- 野球独特の用語や表現はちゃんと訳したい
- てにをは が多少おかしいのは気にしない
- 野球ニュース以外の文章は正しく訳せなくていい
要はがんばりすぎないことです。はい。
こればっかりやってて家のこと何もしなかったら、うちの奥さんも黙ってはいないでしょう。
検討
韓国語を選択した理由
なんとなくですが一番難易度が低そうな予感がしたからです。
- 英語は、、、読めないこともない(すみません嘘です)
- 中国語は、、、漢字なので雰囲気で読んでる(読めてないです)
- ハングルは、、、さっぱりわからない(自分の語学レベルでは暗号にしか見えない)
- 英語と中国語の訳には言葉の並び替えが必要だ(どうしたらいいんだろう)
- そういえば韓国語と日本語は語順が同じなので、並び替え処理とか書かなくてもなんかできそう
- 形態素解析すれば、あとはそれを順に日本語に置換していくだけでできそう! *1
という風に考えてました。
で、どうやって作るのか
基本的には何の知識もないのでいろいろ調べたんですが、
以下の方法であれば自分でもできそうだと思いました。
近年の主流はニューラルネットワークのようですが、
まずは上に書いたような簡単なルールで作ることにしました。 *2
詳細
mecab-ko
mecab-koはmecabを韓国語用にカスタマイズが入ったものです。
(本家mecabだと意図した分割ができなかったです)
辞書はmecab-ko-dicを使っています。
https://bitbucket.org/eunjeon/mecab-ko/src/master/README.md
https://bitbucket.org/eunjeon/mecab-ko-dic/src/master/README.md
※mecab-koのインストール方法は、以前Qiitaに書いたことがあります。
qiita.com
事前準備
形態素解析の辞書(mecab-ko-dic)に各形態素の訳語を付加します。
辞書に訳語を持たせておくと、形態素解析と一緒に日本語訳の情報もくっついてきます。
訳語の収集にはGoogleスプレッドシートのgoogletranslate関数を使わせてもらいました。
元の辞書は品詞別の44ファイルに全部で81万word収録されているので、
スプレッドシートも1シートにおさまらないどころか、1ファイルに入りきれないので何ファイルかに分割する必要があるし、
あとgoogletranslate関数の戻りをひたすら待ちます(全word分実行し終わるのに待ち時間長め)。
※スプレッドシートでひたすら単語の訳を収集
ただしスクショにあるように収集した訳語はよく分からないのが多く、、
訳語を集めるのには向いてなかったかもです。
形態素解析〜訳文生成
コマンド実行でやるならmecabコマンドです。
$ cat [テキスト] | mecab
私の場合は、
なんてことをしてます。
たとえば以下の文章を形態素解析にかけると
두산 베어스가 1차전에서 짜릿한 끝내기 승리를 거뒀다.
以下のような結果が返ってきます。
두산 NNP,*,T,두산,*,*,*,*,斗山,トゥサン
베어스 NNP,인명,F,베어스,*,*,*,*,ベアーズ
가 JKS,*,F,가,*,*,*,*,が
1 SN,*,*,*,*,*,*,*
차 NNBC,*,F,차,*,*,*,*,次,回
전 NNG,*,T,전,*,*,*,*,戦,{multiple}
에서 JKB,*,F,에서,*,*,*,*,で,から,{multiple}
짜릿 XR,*,T,짜릿,*,*,*,*,ぴりっと,鮮やか
한 XSA+ETM,*,T,한,Inflect,XSA,ETM,하/XSA/*+ᆫ/ETM/*,した,な,{multiple}
끝내기 승리 NNG,*,T,끝내기 승리,*,*,*,*,サヨナラ勝利
를 JKO,*,T,를,*,*,*,*,を
거뒀 VV+EP,*,T,거뒀,Inflect,VV,EP,거두/VV/*+었/EP/*,おさめ
다 EF,*,F,다,*,*,*,*,た
. SF,*,*,*,*,*,*,*,.,1794,3560,3518,SF,*,*,*,*,*,*,*,。
EOS
辞書にあらかじめ日本語訳の列を追加していたので、
各形態素から日本語訳を取得することができます。
あとはこの日本語訳を順につなげていくだけです。
といっても↑の例は簡単なケースですが、動詞の変化系(〜した、〜できた、〜できなかった、〜して、〜しない、〜せずに などなど)の場合は愚直にロジックを書いて変形させてます(めんどくさいので他になんかいいやり方ないかなと、、)。
他にも同音異義語もあるので、これは今は前後の形態素の品詞などで判断して訳語を決めているものもあります。 *3
運用:訳文の調整
ルールのロジックはいろいろ書いてますが基本的には辞書が重要だと考えてます。
たとえば、最初に例としてあげた以下のような文章。
「선발 박진우의 역투와 9회말 손시헌의 끝내기타를 앞세워」
— gayou (@gayou) 2019年6月10日
Google翻訳:”先発パク・ジヌの力投と9回裏孫時憲の素晴らしいギターを前面に出して”
野球の試合に唐突にギターが出てくるわけないだろ。https://t.co/AOyQmsBgzF
形態素解析では「끝내」と「기타」の2つに分割されていますが、
ここでは「끝내기」(最後の、サヨナラ)と「타」(打)の2つに分割されて欲しいのです。
※いちおうmecab-ko-dicには「끝내기」「타」の2つの単語は定義されていますが
辞書で定義されているコスト値を調整することで意図したところで分割されるようにするのもよいのですが、 今回は「끝내기타(サヨナラ打)」を一語として新たに辞書に登録しました。
「끝내」という単語にはいろいろ意味を持っており、
※2020/10/22 サヨナラ犠打ではなかったので辞書を修正しました。
”ついに”、”最後”、”終わる”、”素晴らしい”、”最高”、”サヨナラ”などの意味があるようです。
また「기타」という単語は、一般的には”その他”、”ギター”の意味のようです。
どうやら”犠打”は一般的ではなさそうです。
で、このケースの場合はもちろん「素晴らしいギター」ではなく、
最後の犠打→(試合を終える犠打)→サヨナラ犠打 という表現が適切です。
ただし「끝내」「기타」の訳を変えるのではなく、
「끝내기타(サヨナラ犠打)」を一語として新たに辞書に登録することで野球らしい訳になるようにしました。
他にも野球用語や、外国人選手名なども新しく辞書登録しています。 ※一部辞書抜粋
블론세이브,,,,NNG,*,F,블론세이브,*,*,*,*,(ブラウンセーブ),セーブ失敗
끝내기타,,,,NNG,*,F,끝내기타,*,*,*,*,サヨナラ犠打
굿바이 안타,,,,NNG,*,F,굿바이 안타,*,*,*,*,サヨナラ安打
끝내기쇼,,,,NNG,*,F,끝내기쇼,*,*,*,*,サヨナラ勝利
現在は300語ほど辞書に追加したり、既存の訳を修正したりもします。
単語の意味を調べるときは以下の2サイトを便利に使わせてもらってます。 www.kpedia.jp https://ja.dict.naver.com/main.nhnja.dict.naver.com
やればやるほどだんだんとルールが増えていっているので、
そのうち整合性が取れなくなりそうです。
というわけで、ルールベースはやるもんじゃないなと思いました
システム構成
基本的に自分が使いたいもの、慣れているものを使っています。
サーバ環境
サーバはGCPを利用しています。
基本的に月額費用ゼロです。*4
メモリが少ない(630MB)ですがmecab-koや後述のwebサーバを動かすには十分です。
アプリケーション
- WEBサーバ: Nginx(443ポート)& Nginx Unit(8080ポート)
- サーバ証明書はLet's Encryptを使用
- 言語:PHP 7.3
- フレームワーク: 使ってない
- ライブラリ:mecab-ko(形態素解析)、mecab-ko-dic(辞書)
Nginx Unitは設定が簡単で素敵です。 www.nginx.com
今後
他言語への対応
韓国語のメンテはほどほどにして、中国語か英語に取り組みたいです。
ルールベースは正直しんどいので、統計的な手法を取り入れてみたいのですが、野球翻訳に向いてる?対訳データがない *5 ので、、、やっぱりルールベースなかあ、と。
また、ツールもいろいろあるのでどれを使うかは悩みます。
個人的には注目しているツールはJieba、Enju、StanfordCoreNLPです。
サーバはOracle Cloudへ移行したい
構文解析ツールを使おうとするとメモリが足りないので、
Oracle Cloudへの移行を検討中です。
Always Freeなインスタンス(メモリ1GB)は2つまで作れます。
www.oracle.com
それにしても無料枠があるなんていい時代になりました。
ケチなおっさんなんだと思われても仕方ないですが別にいいです。
きっちり使いこなしたいと思います。
開発言語はPythonかJava
ライブラリが比較的そろっているPythonかJavaで作れたらなと考えてます。
Goも気になります。
余談ですが、Nginx Unitはパスごとにどの言語で動かすかの設定が割と楽です。
今は試しにですが、
って設定をしています。以下がunit.jsonの設定内容。
{
"listeners": {
"*:8000": {
"pass": "routes"
}
},
"routes": [
{
"match": {
"uri": "/api/ko/*"
},
"action": {
"pass": "applications/translate-ko"
}
},
{
"match": {
"uri": "/api/zh/*"
},
"action": {
"pass": "applications/translate-zh"
}
}
],
"applications": {
"translate-ko": {
"type": "php",
"processes": 1,
"root": "[path]",
"index": "index.php"
},
"translate-zh": {
"type": "python 3.6",
"processes": 1,
"path": "[path]",
"module": "wsgi"
}
}
}
まだまだ雑な設定ですが、別途php-fpmとかuwsgiを準備、設定する必要がなくて便利です。
最後に
私がやっている個人開発は、
自分の困っていることを解決するための手段だったり、
新しいソフトウェア・ライブラリを試すためだったりします。
今回アドベントカレンダーにエントリしている都合、
他の方の個人開発の記事を見ていますが、
みんなそれぞれやっていることが違って楽しいですね。
Qiita ひとり開発 Advent Calendar 2019は7日目はこれで終わりです。
明日8日目は u1and0さんの「開発環境の紹介 (VM->Docker with tmux, vim)」です。