Pythonによる機械翻訳モデルの構築 Vol.2

概要

  • 今回は前回実行した予測プログラムPredict_on_GPU.ipynbの詳細について解説します。

ライブラリ読み込み

単語分割にMeCabを使用するので、インストールします。
また、予測結果出力に日本語を表示するためにjapanese_matplotlibもインストールしています。

また、下記のプログラムの詳細は以下の通りです。

  • preprocess_utils:前処理用のプログラム
  • model:Transformer
  • weight_utils:学習済みモデルの読み書き用のプログラム

日英翻訳データダウンロード

日英翻訳データをここからダウンロードし、展開しています。
jpn.txtが対象のデータになります。

データ読み込み

ここでは、jpn.txtからデータを読み込んで、学習データとテストデータに分割しています。
preprocess_utils.CreateDataのパラメータは以下の通りです。

  • corpus_path:読み込むファイルのパス
  • do_shuffle:データをシャッフルするか
  • seed_value:シャッフルに使用するシード値
  • split_percent:学習に使うデータのパーセンテージ
  • 実行すると、学習データ、テストデータのデータ数とデータのサンプルを出力します。

前処理

ここでは、学習データ、テストデータの前処理を行っています。
前処理の内容は以下の通りです。

ここでは、原文がを単語分割し、文章の開始と終了を表すstartとendトークンを付与します。
次に、単語をIDに置き換えます。各単語に一つずつユニークなIDが割り当てられ、この例ではAIなら503といったIDが割り当てられています。
最後に0埋めを行うことで、文章の長さを揃えます。文によって単語の数がバラバラだとモデルで処理することが難しいため、あらかじめ最大長を定めておきます。
以上のような前処理を経て、モデルに入力するシーケンスが作成されます。

preprocess_utils.PreprocessDataのパラメータは以下の通りです。

  • mecab:使用するトーカナイザーを設定
  • source_data:翻訳元データ
  • target_data:翻訳後データ
  • max_length:シーケンスの最大長
  • batch_size:バッチサイズ
  • test_flag:テストデータを作成する場合はTrue
  • train_dataset:test_flag=Trueの場合は、学習データを入力する

バッチ作成

ここでは、学習に使うバッチデータを作成しています。
バッチサイズが64なので、64のデータを一つのまとまりとしてバッチを作成します。
予測ではTPUを使用しないので、実行されるコードは以下の2行となります。

モデル定義

使用するハイパラメータは以下の通りです。

  • num_layers:レイヤー数
  • d_model:中間層の次元数
  • num_heads:Multi Head Attentionのヘッド数
  • dff:Feed Forward Networkの次元数
  • dropout_rate:ドロップアウト率

また、今回はモデルの読み書きにpklファイルを用いているので、初期化関数を定義しています。
モデルの読み書きはGCPで行うのが一般的ですが、今回はGCPを使用しないので、このやり方を採用しました。
この関数はTransformerや最適化関数、損失関数などを定義した後に実行することで、学習済みの重みを初期の重みとして利用することができます。

次に、モデル定義についてみていきましょう。

Transformer

  • Transormerクラスを作成しています。クラスの中身については次回以降、解説予定です。
  • 先ほど定義したハイパーパラメータが入力されているのがわかります。

Learning Rate

  • ここでは学習率を設定しています。
  • 学習が進むごとに学習率が小さくなるように設定されています。

Optimizer

  • optimizerにはAdamを使用し、先ほど設定したlearning_rateに従います。

Loss Function

  • 損失関数にはSparseCategoricalCrossentropyを使用します。
  • 予測した単語確率と正解単語間の損失を求めます。
  • また、損失を計算する際はPADの0を無視するためにマスクします。

metrics

  • metricsを下記のように設定します。

予測

予測はnに任意の数値を入れるとその番号のデータを予測用のデータセットから取り出して予測するようになっています。
predict関数に予測したい文章のベクトルを入力することで、翻訳後の文章とattention_weightsを出力します。

predict関数の内部では、入力文のシーケンスと仮のターゲット文のシーケンスをtransfomerの実行関数に入力し、ターゲット文の次に次に来る単語を予測します。
ちなみに仮のターゲット文のシーケンスの初期状態はトークンが存在するだけです。
transformerが予測結果を出力したら、その単語を仮のターゲット文の最後尾に追加し、再びtransformerに入力します。
これをトークンを予測するか、ターゲット文の最大シーケンス長になるまで繰り返しますことでターゲット文を生成します。

また、plot_attention_weights関数は、予測結果をもとにattention_weightsの図を作成する関数です。

予測結果

次に予測結果を見てましょう。

この例では、「 You should tell your mother as soon as possible .」という入力文に対して「できるだけ早く母に話してください。」という文章を出力しました。
それらしい文章に翻訳できていることがわかります。
また、その下のattention_weightsの図を見てみましょう。
attention_weightsの図を見ると入力文と出力文における単語間の関連性を見ることができます。
これは各headのattention_weightsの図を示したものになりますが、色が明るいほど単語間の関連性が強く出ているのがわかります。
例えば、head_1では「mother」という単語と「母」という単語間の関連性が強く出ており、翻訳前の単語と翻訳後の単語とでちゃんと結びつきができていると思われます。
また、他のheadも見てみると「tell」と「話し」の関係性が出ていたり、「possible」と「できるだけ」も対応付けられていることがわかります。

以上、Predict_on_GPU.ipynbの解説でした。
次回はTransformerがどのように学習をして、このような機械翻訳を実現しているのかを解説します。

(K.K)

タイトルとURLをコピーしました