cedro-blog

keras seq2seq でサクッと英日翻訳をやってみる

今回は、keras のサンプルプログラムを使って、英語を日本語に翻訳してみたいと思います。

こんにちは cedro です。

最近、自然言語処理にはまってます。ところで、Seq2Seq(Sequece to Sequence)というモデルをご存知でしょうか。seq2seq は、系列を入力として系列を出力するモデルです。

例えば、英語の単語の系列を受け取り、それと同じ意味のフランス語の単語の系列を出力すれば、英仏の翻訳が出来ます。また、日本語の単語の系列を受け取り、それに応答する日本語の単語の系列を出力すれば、チャットボットの様な事が出来ます。

ということで、今回は、keras のサンプルプログラムを使って、英語を日本語に翻訳してみたいと思います。

 

データセットを準備します

今回使うサンプルプログラムは、lstm_seq2seq.py でオリジナルは英語をフランス語に翻訳する仕様になっています。ただ、私にとっては、英語の理解でさえ怪しいのにフランス語に翻訳されても適切かどうかは判断しようがない、正に猫に小判状態。なので、英語を日本語に翻訳する仕様に変更してやってみたい。

英日翻訳の仕様に変更するには、学習のためのデータセットを英仏から英日に変更すれば良いわけですが、そんな都合の良いものがあるのかというと、ちゃんとあるんです!

実は、英仏のデータセットが置いてある、Tab-delimited Bilingual Sentence Pairs というホームページに、英日のデータセット( jpn-eng.zip も置いてあるので、それをダウンロードしてサンプルプログラムと同じフォルダーに置けば、英日翻訳の仕様に変更できます。。

サンプルプログラムは、1文字単位の処理をしていますので、日本語を使っていても形態素解析などをする必要などなく、英日のデータセットそのまま使えるわけです。便利ですね。

 

プログラムを見てみます

プログラムの冒頭の部分です。11行目は、データセットを何行分読み込むのか指定しています。今回は、オリジナル通り10000行分読み込む設定です。13行目は、読み込むデータセットを英仏から英日に変更しています。

16行目からデータセットをベクトル化する準備です。input_texts には英文が順次格納され、target_textsにはそれを翻訳した日本文が順次格納されます。input_characters には英文に使われている文字の種類が格納され、target_characters には日本文に使われている文字の種類が格納されます。

input_texts = [  … ‘ Tom caught a big fish. ‘,  … ]

target_texts = [ … ‘ \tトムは大きな魚を捕まえた。\n ‘,  … ]

input_characters = [ … ‘ A ‘, ‘ B ‘, ‘ C ‘, ‘ D ‘, … ]

target_characters = [ … ‘ あ ‘, ‘ い ‘, ‘ う ‘, ‘ え ‘, … ]

 

辞書を作成し、データをベクトル化する部分です。2−5行目で、input_characters から辞書 input_token_index を作成し、target_characters から辞書 target_token_index を作成します。

input_token_index = { …  ‘ A ‘: 20,  ‘ B ‘: 21,  ‘ C ‘: 22,  ‘ D ‘: 23,  … }

target_token_index = {  …  ‘ あ ‘: 45,  ‘ い ‘: 46,  ‘ う ‘: 47,  ‘ え ‘: 48, …  }

7行目からがデータをベクトル化する部分です。encoder_input_data は英文のベクトルデータ、decoder_input_data は日本文のベクトルデータ、decoder_target_data は日本文を1文字づつ予測するベクトルデータが格納されます。

 

モデル構築学習をする部分です。26行目はターミナルにモデル表示する命令を追加。27–28行目で、モデル可視化モジュールをインポートし、モデルを’  lstm_seq2seq.png ‘ で保存するために追加してます(但し、pydot graphviz を事前にインストールしておく必要があります)。

 

 lstm_seq2seq.png を表示させたものです。モデルLSTMモジュール2つ使っています。lstm_1 input_1 から英文文字単位の系列で受け取り学習します。lstm_2 lstm_1 の結果(学習した重み)を受け取ると共に、input_2 からその英文を翻訳した日本語文文字単位の系列で受け取り学習します。

29行目から学習の開始です。

 

英文に対応した日本文を生成する部分です。3–14行目サンプリングモデルの構築(学習の時と同様です)、18–21行目逆引き辞書の作成。

reverse_input_char_index = {  …  20: ‘ A ‘,  21: ‘ B ‘,  22: ‘ C ‘,  23: ‘ D ‘,  …  }

reverse_target_char_index = {  …  45: ‘ あ ‘,  46: ‘ い ‘,  47: ‘ う ‘,  48: ‘ え ‘,  …  }

23–58行目は、英文の入力から日本文を予測する関数の定義です。

61行目でデータセットの最初から何番目までの英文を翻訳するかを設定しています。オリジナルは100ですが、これでは極めて初歩的な文なので、2000に設定しています。

 

プログラムを動かしてみます

プログラムは、私の MacbookAir で動かすと、175sec / epoch100 epoch 動かすのに約5時間弱といったところ。少し時間は掛かりますが、ノートパソコンでも、やれるレベルだと思います。

 

プログラムを起動させた時の初期画面です。Number of unique input tokens英文なので 72 種類と少ないですが、Number of unique output tokens日本文なので1483 種類とかなり多いです。

model.summary() の表示は、単純なSequential モデルとは違って、Connected to という項目が追加され、各モジュールの接続状況を表示しています。

10000個のデータセットの内、8000個学習に、2000個評価に使う設定です。

 

英文を日本語に翻訳した出力の一部です。実は、サンプルプログラムの設定は、データセットで学習した英文をそのまま日本語訳させているので、上手くいって当たり前という気もします。しかし、10000個の英文と和訳のデータセットをLSTM256個の隠れ層の重みだけで学習しているわけですから、これは凄いことです。

ディープラーニングを使って機械翻訳というのは、こういうイメージなのかなと少し分かった気がします。

では、また。