Cookpadのレシピを機械翻訳する

前回のつくれぽ数の予測に引き続き、今回もCookpadネタです。

皆さんご存知の通り、英語版Cookpad(https://en.cookpad.com)が8月5日にリリースされました。

今のところ、英語圏のユーザがレシピを投稿するのではなく、どうやら日本語版サイトのレシピを翻訳しているみたいです:

日本食の家庭料理のレシピ数では世界一を誇るクックパッドのレシピのなかから、海外の家庭でも手軽に作りやすい人気レシピを英語に翻訳していきます。(中略)オープン当初は約1,500品の掲載レシピ数からスタートし、早期に数万品まで増やしていく予定です (クックパッド英語版『COOKPAD』をリリース)

そのため、Cookpadの日本語のレシピと英語のレシピは1対1の関係にあります。例えば「たまにはね♪塩鯖のトマト煮(^m^*)」を英語に翻訳したものは「Salted Mackerel, Simmered With Tomatoes For a Change (^m^*)」で見ることができます。

機械翻訳の研究をしており、なおかつ料理をするのも大好きな友人のVictorがこの日英レシピデータに興味を持ったらしく、こんなやりとりをTwitterでしました(なお、Victorが言及しているリンクはCookpadが求人をかけていたRecipe Translatorの募集要項ページです。現在は募集終了したらしく、リンク切れになっています):

それではCookpadのデータを使って機械翻訳システムを作り、日本語のレシピを英語に翻訳してみましょう1

データ

2013年8月14日に英語版Cookpadから1,952件のレシピをクロールしました。同日に日本語版Cookpadから、それらに対応する1,952件の日本語レシピをクロールしています。レシピの80%を訓練データ、10%を開発データ、10%を評価データに分けました。

なお、今回翻訳するのはCookpadのレシピに含まれる以下の要素です:

  • タイトル
  • 紹介文
  • 材料(材料名と量)
  • 手順
  • コツ・ポイント
  • レシピの生い立ち

手法

機械翻訳と一口に言っても、いくつかのアプローチがあります。1990年台から主流なのは統計的機械翻訳で、これはGoogle翻訳やMicrosoftのBing Translatorでも使われています。統計的機械翻訳では対訳コーパスとよばれる、例えば日本語と英語など異なる言語の文と文が対訳の形でまとめられたデータからモデルを学習します。

下の図に、統計的機械翻訳の仕組みをおおまかに示します:

一般的に、統計的機械翻訳システムは翻訳モデル、言語モデル、デコーダの3つから成り立ちます。 今回の場合、翻訳モデルを学習するには日本語のレシピとそれに対応する英語のレシピの集まり(対訳コーパス)を使います。言語モデルを学習するには英語レシピの集まりのみを使います(i.e. 日本語レシピは必要ありません)。

翻訳モデルは、大雑把に言えば日本語と英語の対応関係を規定します。例えば、日本語レシピデータのうち500行に「ゴボウ」という言葉が含まれており、対応する英語レシピの500行のうち498行に”burdock”と書かれていたら、英語を全く知らなくても『「ゴボウ」は”burdock”に対応するんだな』と予想がつきます。このように、翻訳モデルの学習では対応する文から対応する単語/句の組を計算します。

言語モデルは「英文がどれだけ流暢か」を計算するために使われます。例えば、”heat the oil in a frying pan”は自然な英文ですが、”heat an oil in a frying pan”はあまり流暢ではなく、”heat an oils in a frying pan”はかなりひどい英文と言えます。「ある文がどれくらい流暢か」というのを具体的な数値として求めるには、その文(に含まれる単語の組み合わせ)が訓練データにどれくらいの頻度で含まれているかを数えることによって計算することが出来ます。具体例を挙げるとすれば、Googleが有するweb文書の集まりを訓練データに見立てれば、“heat the oil in a frying pan”と検索すると約1,090,000件、“heat an oil in a frying pan”で3件、“heat an oils in a frying pan”で0件ヒットするのでそれらの数値を「流暢さ」として使えそうなことが分かります。

翻訳したい日本語文を入力すると、機械翻訳システムは翻訳モデルと言語モデルを使って膨大な数の訳文を生成し、デコーダがその中からもっとも良さそうな英文を選び、それを出力します。

実装

今回はオープンソースの統計的機械翻訳システムを使いました。有名どころは以下の3つです:

  • Moses (http://www.statmt.org/moses/) University of EdinburghのPhilipp Koehn主体のプロジェクト。3つの中では最も歴史が古く、成熟している。機能が豊富。ユーザマニュアル(pdf)も300ページを超える大作。C++で書かれている。
  • Joshua (http://joshua-decoder.org/) JHU/UPennのChris Callison-Burch主体のプロジェクト。Javaで書かれている。
  • cdec (http://cdec-decoder.org/, http://www.cdec-decoder.org/) CMUのChris Dyer主体のプロジェクト。この3つのプロジェクトのうち最も後発で、最新の手法が含まれているが必要最小限の機能のみ実装されている印象。他の2つに比べると高速・メモリ使用量が低いらしい。C++で書かれている。

前述したVictorはcdecの主要contributorの1人なので、よしみで今回はcdecを使いました。

上の図では対訳コーパスがレシピ単位で対応付けられているように見えますが、実際には文レベルで対応付けをするのが一般的です。日英版Cookpadにおいて、レシピのタイトルや材料はすでに文レベルで対応付けされているのですが、レシピの紹介文、手順、コツ・ポイント、生い立ちは自由形式で入力するので段落単位で対応付けされています。これらを文レベルで対応付けするために、hunalignというsentence alignerを用いてます。

デコーダについて

ちょっと脱線します。機械翻訳システムではデコーダが最も良い英文を選ぶと書きましたが、もともとdecodeという単語には「解読、復号をする」という意味があります。翻訳と暗号解読がなぜ関係あるのかという疑問が当然湧きますが、機械翻訳の先駆者であるWarren Weaverは次のような文を書いています:

One naturally wonders if the problem of translation could conceivably be treated as a problem in cryptography. When I look at an article in Russian, I say: ‘This is really written in English, but it has been coded in some strange symbols. I will now proceed to decode.’

また、自然言語処理の大御所であるKevin Knightが機械翻訳の手法を用いて秘密結社の暗号文を解読した、というダ・ヴィンチ・コードもびっくりの逸話もあります(cf. http://ameblo.jp/malikun01/entry-11060614160.html http://www.wired.com/dangerroom/2012/11/ff-the-manuscript/)

結果

一般的に、対訳コーパスの量が多ければ多いほど翻訳システムの性能が上がります。実用的な統計的機械翻訳システムを作るには100万文程度の対訳コーパスが必要らしいのですが、今回は(訓練データの約1,600件のレシピに含まれる)5.4万文と非常に少量です。そのため、全く使えない代物になることを危惧していたのですが、意外とまとも(?)な翻訳結果が得られました。翻訳システムを評価するために一般的によく使われる指標であるBLEU値は0.196と、日本語→英語翻訳としては可もなく不可もなくといったところです。

具体的な翻訳結果を見ていきましょう。調理手順が比較的簡単な✿さつま揚げの磯辺焼き✿(英語版はIsobe-yaki Fried Satuma-age Fish Cakes with Nori Seaweed)の原文と翻訳した結果を次に示します:

#--------------------------
# 原文
#--------------------------

# タイトル
✿さつま揚げの磯辺焼き✿

# 紹介文
甘辛く味付けしたさつま揚げを海苔で巻きました。
お弁当のおかずやおつまみにもピッタリな簡単な一品です♪

# 材料
さつま揚げ 2枚
☆醤油 小さじ1
☆みりん 小さじ1
海苔 1/3枚

# 手順
さつま揚げは食べやすい大きさに切り、フライパンで(油なしで)両面を焼く。
火を弱めて☆を加え、さつま揚げの両面に調味料を絡ませながら焼く。
粗熱が取れたら適当な大きさに切った海苔で巻く。
お弁当に入れるとこんな感じです。

# コツ・ポイント
特にありません。

# このレシピの生い立ち
お弁当のおかずにぴったりな簡単な一品を考えました。
さつま揚げはお弁当箱に詰めやすく、冷めても美味しいのでよく使っています。

#--------------------------
# 翻訳結果
#--------------------------

# タイトル
✿ Fish cake - coated with ✿

# 紹介文
Sweet-salty cakes to the rolls with nori seaweed.
Perfect side dish for lunch box or appetizer an easy dish.

# 材料
fish cake      2
☆ soy sauce    1 teaspoon
☆ mirin        1 teaspoon
nori seaweed   1 / 3

# 手順
Cut the fish cake into easy to eat pieces, in a frying pan (without oil). Fry both sides.
Turn down the heat.
Add the cakes on both sides of the flavoring ingredients to the pan.
It has cooled down a bit up into bite size pieces. Wrap with nori seaweed.
In a bento it looks like this.

# コツ・ポイント
None in particular.

# このレシピの生い立ち
It's great for bentos, easy and came up with this dish.
Stuff the cakes in a bento box easy and delicious even when cold, so use well.

稚拙な部分も少々ありますが、英文のみから要点をなんとなく把握することができます。材料の翻訳はほぼ完璧で、手順は少し手を加えれば意味が通じるでしょう。

比較のために、Google翻訳とBing Translatorの出力も見てみます:

#--------------------------
# Google翻訳 (2013/08/26時点)
#--------------------------

# タイトル
✿ ✿ Isobe grilled fish cake of

# 紹介文
It was wound with glue a fish cake that was seasoned Amakaraku.
Simple ♪ is one article which is good to snack or side dish of the lunch

# 材料
Fish cake      Two
☆ soy sauce    1 tsp
☆ Mirin        1 tsp
Laver          1/3 sheet

# 手順
Cut into bite-size, fish cake and bake both sides (without oil) in a frying pan.
In addition to the ☆ weaken the fire, and bake while entangle the seasoning on both sides of the fish cake. Add the cakes on both sides of the flavoring ingredients to the pan.
Is wound with glue that was cut to a suitable size When you take the rough heat
It is such a feeling when I put a lunch

# コツ・ポイント
It is not especially.

# このレシピの生い立ち
I thought a good simple dish side dish of the lunch.
I often use fish cake is delicious and easy packed in lunch boxes, even if cold.

#--------------------------
# Bing Translator (2013/08/26時点)
#--------------------------

# タイトル
✿ grilling of the deep-fried ✿

# 紹介文
Earthdom deep-fried fish cake rolled with Nori seaweed.
Is a simple dish perfect for the lunch box side dishes or appetizers.

# 材料
Fried fish cake    2 Piece
☆ soy sauce        1 Teaspoon
☆ Mirin            1 Teaspoon
Nori seaweed       1 / 3

# 手順
In a frying pan (oil at no), cut into bite-sized fried fish cake Cook on both sides.
Slowly ☆ addition, entwined seasoning on both sides of fried fish cake bake.
Roll seaweed paper cut to size refrigerate.
This is put in the Bento.

# コツ・ポイント
Not particularly.

# このレシピの生い立ち
I thought simple dish a perfect side dish for lunch.
So delicious deep-fried easy packed lunch, cold, it also often use.

贔屓目に見ているかもしれませんが、Google翻訳やBing Translatorよりも今回作った翻訳システムのほうがほんのちょっとだけ、より自然な翻訳のような気がします。 レシピのタイトルの「さつま揚げの磯辺焼き」が”coated with”、”fish cake of”、”of the deep-fried”のように全ての翻訳システムでincomplete sentenceに翻訳される理由がよく分かりませんが興味深い現象です。

次に、翻訳が特にうまくいった例も紹介します:

#--------------------------
# 日本語原文
#--------------------------

2010/10/20話題入り感謝♫
ナスを斜め7mm幅に切る 。    
ボールに入れ塩を振りかけて軽く揉みこみ暫く置く 。
その間にタレを作ります 。
〇を全て混ぜ合わせておく 。
フライパンを熱しごま油を入れる 。
ナスの水気を軽くふき取り並べて両面を中火で焼く。
両面に焼き色がついたら、タレを加え煮詰める。
タレが少し残るくらいで火を止める。
丼ぶりに、白ご飯を入れ、ナスを並べて盛り付け、小ネギとのりを散らして出来上がり~♪

#--------------------------
# 翻訳結果
#--------------------------

Thank you for making this a top recipe on 2010/10/20.
Slice the eggplant 7mm thick pieces.
Massage lightly in a bowl and sprinkle with salt and leave.
In the meantime, make the sauce.
Mix the 〇 ingredients together.
Heat the sesame oil in a frying pan.
Lightly drain the eggplant, and cook on both sides over medium heat.
When browned on both sides, add the sauce.
Turn off the heat a little with the sauce.
In a bowl, add the white rice and arrange the eggplant and plate, scatter with chopped green onion and nori seaweed and it's done.

“Slice the eggplant 7mm thick pieces”は”Slice the eggplant diagonally into 7mm thick pieces”のほうがより自然です。また、「ナスの水気を軽く拭き取り…」は”lightly drain the eggplant”と翻訳されましたが、”lightly dry off the eggplant (with a napkin/towel)“のほうが個人的にはしっくりします2。最後に、「タレが少し残るくらいで火を止める」は”turn off the heat a little with the sauce”と翻訳されてますが、これは”turn off the heat so that a little amount of sauce remains”が妥当でしょう。しかし、これら以外の文はほぼ完璧といっていいほどの翻訳です。

また参考までに、Google翻訳とBing Translatorの出力も見てみましょう:

#--------------------------
# Google翻訳 (2013/08/26時点)
#--------------------------

October 20, 2010 topic enters thank ♫
I cut to 7 mm width diagonally eggplant.    
Put for a while crowded rub lightly sprinkled with salt and put in a bowl.
I make a sauce in the meantime.
I keep mixing all Yes.
Add the sesame oil Heat the frying pan.
Bake over medium heat on both sides side by side lightly wipe off the moisture of the eggplant.
When browned on both sides with, boil down was added to the sauce.
I stop the fire in about a little sauce remains.
To bowl the first time, it ~ ♪ Put the white rice, Ready to Eat side-by-side eggplant, and voila Sprinkle the glue and small green onion

#--------------------------
# Bing Translator (2013/08/26時点)
#--------------------------

2010 / 10 / 20 Buzz with gratitude ♫
Eggplant cut width 7 mm diagonal.
Bowl sprinkle salt lightly 揉みこみ and put for a while.
In the meantime make sauce.
○ all mix.
Heat the skillet add sesame oil.
Sprinkle Eggplant drain side Cook on both sides over medium heat.
Pour in on both sides and sauce in addition boil down.
Sauce will long remain a little to stop the fire.
Put the rice in a bowl, serve Eggplant side by side, sprinkle the onions with paste and voila ~!

日本語はpro-drop languageなので、日本語→英語のように日本語をsource languageとした機械翻訳ではその取り扱いが難しそうなイメージがあります。現に、今回のケースでは”I cut to 7 mm”, “I make a sauce”, “I keep mixing”, “I stop the fire”などGoogle翻訳では”I”を挿入していますが、レシピの手順としてこれは不自然です。一方、Bing Translatorは”I”を挿入していません。

原文の「のりを散らして」がGoogle翻訳では”sprinkle the glue”、Bing Translatorでは”sprinkle … with paste”と翻訳されていますが、これは恐らく”sprinkle the glue powder”や”sprinkle … with paste”というフレーズがGoogleとBingが使っているコーパスに数多く含まれていたためだと考えられます。

Google翻訳とBing Translatorは汎用な翻訳システムであるのに対し、今回作成したシステムでは訓練データと評価データを同一のドメインから取得しているため、翻訳の質がより高いように感じます。

まとめ

対訳コーパスが少量であったにも関わらず、レシピの材料と調理手順に関しては言い回しが限られているため、それなりの質の翻訳が得られました。それに対し、レシピのタイトル、紹介文、コツ・ポイント、生い立ちに関してはより自由な書き方ができるため、あまり芳しくない結果となりました。

今回得られた翻訳システムは実用レベルとまではいきませんが、翻訳家を支援するツールだと割り切って使う分には問題ないと思います。「『ゴボウ』は英語で何て言うんだっけ」「この言い回しは英語で何て言うんだっけ」など、翻訳家でも訳が思い浮かばないケースが多々あると思います。辞書を引く代わりに、あらかじめ機械翻訳で得られた訳文を表示しておけば翻訳にかかる時間やコストを削減できるのではないでしょうか。

また、今回はcdecの初心者向けチュートリアルを忠実に実行しただけにも関わらずこのように悪くはない結果になったので、もう少しカスタマイズを頑張ればもっとまともな翻訳が得られると思います。

なお、今回のソースコードはhttps://github.com/mrorii/gastroglotに置いておきました。

統計的機械翻訳に興味を持たれた方は、日本語で読める資料として

を推薦します。また、(英語ですが)教科書はPhilipp Koehnの本が定番です:

(機械翻訳というよりは暗号学の内容ですが)一般大衆向けの読み物としてはサイモン・シン(著)、青木薫 (翻訳)の「暗号解読」が大変面白いです:

暗号が解読されたために処刑されたスコットランド女王、第二次世界大戦中のナチス・ドイツが用いた暗号機のエニグマを解読した連合軍の研究者達、またアメリカ原住民のナヴァホ族のコードトーカーによってたちまち苦戦を強いられた日本軍など、暗号解読にまつわる様々な歴史上の人間ドラマが詰まっていて、科学技術系のノンフィクションの珠玉の作品の1つです。

この記事をきっかけに、日本でも機械翻訳を採用するWeb企業が増えたらなと思います3。Cookpadとか。


  1. なお、上のtweetでは「2人でタッグを組んでやろうぜ!」と書かれていますが、結局(機械翻訳が初心者の)自分1人でほとんどやったので誤りなどありましたら教えて下さい。 [return]
  2. “drain”は布巾ではなくザルを使うイメージがあります。 [return]
  3. (外資系企業ですが)Microsoftではオンラインマニュアルをi18n対応するための前処理段階として機械翻訳を使っているみたいです(http://d.hatena.ne.jp/mamoruk/20100112/p2のコメント欄を参照) [return]