入門Python神経機械翻訳、これは非常に簡素な実戦ガイドです
18729 ワード
Medium、著者:Susan Li、機械の心コンパイルから選択します.
マシン翻訳(MT)は、コンピュータを使用してテキストまたは音声を1つの言語から別の言語に翻訳する方法を研究する非常に挑戦的なタスクです.本論文では,Kerasを用いて最も基本的なテキストロードとデータプリプロセッシングから開始し,このチュートリアルのすべてのコードがGitHubでオープンソースされた,ループニューラルネットワークとエンコーダデコーダの枠組みの下でどのように許容可能なニューラル翻訳システムを構築できるかを議論した.
従来の意味では、機械翻訳は一般的に高度に複雑な言語知識を用いて開発された大型統計モデルを用いているが、最近では深さモデルを用いて翻訳プロセスを直接モデリングし、原語データと訳文データのみを提供する場合に必要な言語知識を自動的に学習する研究が多い.この深さニューラルネットワークに基づく翻訳モデルは現在最適な効果を得ている.
プロジェクトアドレス:github.com/susanli2016…
次に,深さニューラルネットワークを用いて機械翻訳問題を解決する.英語をフランス語に翻訳するニューラルネットワーク機械翻訳モデルをどのように開発するかを示す.このモデルは、英語のテキスト入力を受信し、フランス語の訳文を返します.より正確には、次の4つのモデルを構築します.簡単なRNN; 語埋め込みRNN; 双方向RNN; エンコーダ-デコーダモデル.
深さニューラルネットワークの訓練と評価は計算密集型の任務である.著者らは、AWS EC 2インスタンスを使用して、すべてのコードを実行する.本明細書で行う場合は、GPUインスタンスにアクセスする必要があります.
ライブラリのロード
作者はhelp.pyデータをロードし、project_を使用test.pyテスト関数.
データ#データ#
このデータセットには、small_という比較的小さな用語集が含まれています.vocab_Enファイルには英語の文が含まれています.small_vocab_frには対応するフランス語翻訳が含まれています.
データセットダウンロードアドレス:github.com/susanli2016…
データのロード文サンプル small_vocab_enの各行には英語の文が含まれており、フランス語の翻訳はsmall_にあります.vocab_frに対応する各行.用語集 問題の複雑さは語彙の複雑さに依存する.より複雑な語彙は、より複雑な問題を意味します.処理するデータセットについて、その複雑さを見てみましょう.
プリプロセッシング
次の前処理方法を使用して、テキストを整数シーケンスに変換します.
1.語をid表現に変換する.
2.各シーケンスが同じ長さになるようにpaddingを追加します.
Tokensize(タグ文字列)
KerasのTokenizer関数を使用して、各文を単語idのシーケンスに変換します.この関数を使用して、英語文とフランス語文をマークします.
関数tokenizeは、タグ化された入力とクラスを返します.
Padding
Kerasのpad_を使うことでsequences関数は、すべての英語シーケンスが同じ長さを有し、すべてのフランス語シーケンスが同じ長さを有するように、各シーケンスに最後にゼロを追加します.
前処理フロー
前処理関数の実装:
モデル#モデル#
本節では,種々のニューラルネットワーク構造を試みる.私たちは4つの比較的簡単な構造を訓練し始めます.モデル1は単純なRNNである. モデル2は、用語埋め込みRNNである. モデル3は双方向RNNである. モデル4は、2つのRNNからなるエンコーダ−デコーダアーキテクチャである.
4つの単純な構造を試みた後,以上の4つのモデルよりも性能が優れたより深いモデルを構築する.
idをテキストに再変換
ニューラルネットワークは入力を単語idに変換しますが、これは私たちが最終的に望んでいる形式ではありません.私たちが望んでいるのはフランス語翻訳です.logits_to_text関数はニューラルネットワークから出力されるlogitsからフランス語翻訳へのギャップを補い,この関数を用いてニューラルネットワークの出力をよりよく理解する.
モデル1:RNN
英語をフランス語シーケンスに翻訳するための良好な基準である基礎RNNモデルを構築した.
基礎RNNモデルの検証セット精度は0.6039であった.
モデル2:ワード埋め込み
語埋め込みは、n次元空間における類義語距離に近いベクトル表現であり、nは埋め込みベクトルの大きさを表す.用語埋め込みを用いてRNNモデルを構築する.
埋め込みモデルの検証セット精度は0.8401であった.
モデル3:双方向RNN
双方向RNNモデルの検証セット精度は0.5992であった.
モデル4:エンコーダ-デコーダフレームワーク
エンコーダは文のマトリクス表現を構築し、デコーダはそのマトリクスを入力として予測の翻訳を出力する.
エンコーダ-デコーダモデルの検証セットの精度は0.6406です.
モデル5:カスタム深度モデル
単語埋め込みと双方向RNNをモデルに統合するmodel_を構築します.final.
そこで,GPUパラメータを256に変更したり,学習率を0.005に変更したり,モデルに対して20 epochsより多く(または少ない)訓練したりするなど,いくつかの実験を行う必要がある.
予測
文の完璧な翻訳を得たと同時に、セットの精度が0.9776であることを検証しました.
原文链接:medium.com/@actsusanli…
マシン翻訳(MT)は、コンピュータを使用してテキストまたは音声を1つの言語から別の言語に翻訳する方法を研究する非常に挑戦的なタスクです.本論文では,Kerasを用いて最も基本的なテキストロードとデータプリプロセッシングから開始し,このチュートリアルのすべてのコードがGitHubでオープンソースされた,ループニューラルネットワークとエンコーダデコーダの枠組みの下でどのように許容可能なニューラル翻訳システムを構築できるかを議論した.
従来の意味では、機械翻訳は一般的に高度に複雑な言語知識を用いて開発された大型統計モデルを用いているが、最近では深さモデルを用いて翻訳プロセスを直接モデリングし、原語データと訳文データのみを提供する場合に必要な言語知識を自動的に学習する研究が多い.この深さニューラルネットワークに基づく翻訳モデルは現在最適な効果を得ている.
プロジェクトアドレス:github.com/susanli2016…
次に,深さニューラルネットワークを用いて機械翻訳問題を解決する.英語をフランス語に翻訳するニューラルネットワーク機械翻訳モデルをどのように開発するかを示す.このモデルは、英語のテキスト入力を受信し、フランス語の訳文を返します.より正確には、次の4つのモデルを構築します.
深さニューラルネットワークの訓練と評価は計算密集型の任務である.著者らは、AWS EC 2インスタンスを使用して、すべてのコードを実行する.本明細書で行う場合は、GPUインスタンスにアクセスする必要があります.
ライブラリのロード
import collections
import helper
import numpy as np
import project_tests as tests
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.models import Model
from keras.layers import GRU, Input, Dense, TimeDistributed, Activation, RepeatVector, Bidirectional
from keras.layers.embeddings import Embedding
from keras.optimizers import Adam
from keras.losses import sparse_categorical_crossentropy
作者はhelp.pyデータをロードし、project_を使用test.pyテスト関数.
データ#データ#
このデータセットには、small_という比較的小さな用語集が含まれています.vocab_Enファイルには英語の文が含まれています.small_vocab_frには対応するフランス語翻訳が含まれています.
データセットダウンロードアドレス:github.com/susanli2016…
データのロード
english_sentences = helper.load_data('data/small_vocab_en')
french_sentences = helper.load_data('data/small_vocab_fr')
print('Dataset Loaded')
for sample_i in range(2):
print('small_vocab_en Line {}: {}'.format(sample_i + 1, english_sentences[sample_i]))
print('small_vocab_fr Line {}: {}'.format(sample_i + 1, french_sentences[sample_i]))
english_words_counter = collections.Counter([word for sentence in english_sentences for word in sentence.split()])
french_words_counter = collections.Counter([word for sentence in french_sentences for word in sentence.split()])
print('{} English words.'.format(len([word for sentence in english_sentences for word in sentence.split()])))
print('{} unique English words.'.format(len(english_words_counter)))
print('10 Most common words in the English dataset:')
print('"' + '" "'.join(list(zip(*english_words_counter.most_common(10)))[0]) + '"')
print()
print('{} French words.'.format(len([word for sentence in french_sentences for word in sentence.split()])))
print('{} unique French words.'.format(len(french_words_counter)))
print('10 Most common words in the French dataset:')
print('"' + '" "'.join(list(zip(*french_words_counter.most_common(10)))[0]) + '"')
プリプロセッシング
次の前処理方法を使用して、テキストを整数シーケンスに変換します.
1.語をid表現に変換する.
2.各シーケンスが同じ長さになるようにpaddingを追加します.
Tokensize(タグ文字列)
KerasのTokenizer関数を使用して、各文を単語idのシーケンスに変換します.この関数を使用して、英語文とフランス語文をマークします.
関数tokenizeは、タグ化された入力とクラスを返します.
def tokenize(x):
x_tk = Tokenizer(char_level = False)
x_tk.fit_on_texts(x)
return x_tk.texts_to_sequences(x), x_tk
text_sentences = [
'The quick brown fox jumps over the lazy dog .',
'By Jove , my quick study of lexicography won a prize .',
'This is a short sentence .']
text_tokenized, text_tokenizer = tokenize(text_sentences)
print(text_tokenizer.word_index)
print()
for sample_i, (sent, token_sent) in enumerate(zip(text_sentences, text_tokenized)):
print('Sequence {} in x'.format(sample_i + 1))
print(' Input: {}'.format(sent))
print(' Output: {}'.format(token_sent))
Padding
Kerasのpad_を使うことでsequences関数は、すべての英語シーケンスが同じ長さを有し、すべてのフランス語シーケンスが同じ長さを有するように、各シーケンスに最後にゼロを追加します.
def pad(x, length=None):
if length is None:
length = max([len(sentence) for sentence in x])
return pad_sequences(x, maxlen = length, padding = 'post')
tests.test_pad(pad)
# Pad Tokenized output
test_pad = pad(text_tokenized)
for sample_i, (token_sent, pad_sent) in enumerate(zip(text_tokenized, test_pad)):
print('Sequence {} in x'.format(sample_i + 1))
print(' Input: {}'.format(np.array(token_sent)))
print(' Output: {}'.format(pad_sent))
前処理フロー
前処理関数の実装:
def preprocess(x, y):
preprocess_x, x_tk = tokenize(x)
preprocess_y, y_tk = tokenize(y)
preprocess_x = pad(preprocess_x)
preprocess_y = pad(preprocess_y)
# Keras's sparse_categorical_crossentropy function requires the labels to be in 3 dimensions
preprocess_y = preprocess_y.reshape(*preprocess_y.shape, 1)
return preprocess_x, preprocess_y, x_tk, y_tk
preproc_english_sentences, preproc_french_sentences, english_tokenizer, french_tokenizer =\
preprocess(english_sentences, french_sentences)
max_english_sequence_length = preproc_english_sentences.shape[1]
max_french_sequence_length = preproc_french_sentences.shape[1]
english_vocab_size = len(english_tokenizer.word_index)
french_vocab_size = len(french_tokenizer.word_index)
print('Data Preprocessed')
print("Max English sentence length:", max_english_sequence_length)
print("Max French sentence length:", max_french_sequence_length)
print("English vocabulary size:", english_vocab_size)
print("French vocabulary size:", french_vocab_size)
モデル#モデル#
本節では,種々のニューラルネットワーク構造を試みる.私たちは4つの比較的簡単な構造を訓練し始めます.
4つの単純な構造を試みた後,以上の4つのモデルよりも性能が優れたより深いモデルを構築する.
idをテキストに再変換
ニューラルネットワークは入力を単語idに変換しますが、これは私たちが最終的に望んでいる形式ではありません.私たちが望んでいるのはフランス語翻訳です.logits_to_text関数はニューラルネットワークから出力されるlogitsからフランス語翻訳へのギャップを補い,この関数を用いてニューラルネットワークの出力をよりよく理解する.
def logits_to_text(logits, tokenizer):
index_to_words = {id: word for word, id in tokenizer.word_index.items()}
index_to_words[0] = ''
return ' '.join([index_to_words[prediction] for prediction in np.argmax(logits, 1)])
print('`logits_to_text` function loaded.')
モデル1:RNN
英語をフランス語シーケンスに翻訳するための良好な基準である基礎RNNモデルを構築した.
def simple_model(input_shape, output_sequence_length, english_vocab_size, french_vocab_size):
learning_rate = 1e-3
input_seq = Input(input_shape[1:])
rnn = GRU(64, return_sequences = True)(input_seq)
logits = TimeDistributed(Dense(french_vocab_size))(rnn)
model = Model(input_seq, Activation('softmax')(logits))
model.compile(loss = sparse_categorical_crossentropy,
optimizer = Adam(learning_rate),
metrics = ['accuracy'])
return model
tests.test_simple_model(simple_model)
tmp_x = pad(preproc_english_sentences, max_french_sequence_length)
tmp_x = tmp_x.reshape((-1, preproc_french_sentences.shape[-2], 1))
# Train the neural network
simple_rnn_model = simple_model(
tmp_x.shape,
max_french_sequence_length,
english_vocab_size,
french_vocab_size)
simple_rnn_model.fit(tmp_x, preproc_french_sentences, batch_size=1024, epochs=10, validation_split=0.2)
# Print prediction(s)
print(logits_to_text(simple_rnn_model.predict(tmp_x[:1])[0], french_tokenizer))
基礎RNNモデルの検証セット精度は0.6039であった.
モデル2:ワード埋め込み
語埋め込みは、n次元空間における類義語距離に近いベクトル表現であり、nは埋め込みベクトルの大きさを表す.用語埋め込みを用いてRNNモデルを構築する.
from keras.models import Sequential
def embed_model(input_shape, output_sequence_length, english_vocab_size, french_vocab_size):
learning_rate = 1e-3
rnn = GRU(64, return_sequences=True, activation="tanh")
embedding = Embedding(french_vocab_size, 64, input_length=input_shape[1])
logits = TimeDistributed(Dense(french_vocab_size, activation="softmax"))
model = Sequential()
#em can only be used in first layer --> Keras Documentation
model.add(embedding)
model.add(rnn)
model.add(logits)
model.compile(loss=sparse_categorical_crossentropy,
optimizer=Adam(learning_rate),
metrics=['accuracy'])
return model
tests.test_embed_model(embed_model)
tmp_x = pad(preproc_english_sentences, max_french_sequence_length)
tmp_x = tmp_x.reshape((-1, preproc_french_sentences.shape[-2]))
embeded_model = embed_model(
tmp_x.shape,
max_french_sequence_length,
english_vocab_size,
french_vocab_size)
embeded_model.fit(tmp_x, preproc_french_sentences, batch_size=1024, epochs=10, validation_split=0.2)
print(logits_to_text(embeded_model.predict(tmp_x[:1])[0], french_tokenizer))
埋め込みモデルの検証セット精度は0.8401であった.
モデル3:双方向RNN
def bd_model(input_shape, output_sequence_length, english_vocab_size, french_vocab_size):
learning_rate = 1e-3
model = Sequential()
model.add(Bidirectional(GRU(128, return_sequences = True, dropout = 0.1),
input_shape = input_shape[1:]))
model.add(TimeDistributed(Dense(french_vocab_size, activation = 'softmax')))
model.compile(loss = sparse_categorical_crossentropy,
optimizer = Adam(learning_rate),
metrics = ['accuracy'])
return model
tests.test_bd_model(bd_model)
tmp_x = pad(preproc_english_sentences, preproc_french_sentences.shape[1])
tmp_x = tmp_x.reshape((-1, preproc_french_sentences.shape[-2], 1))
bidi_model = bd_model(
tmp_x.shape,
preproc_french_sentences.shape[1],
len(english_tokenizer.word_index)+1,
len(french_tokenizer.word_index)+1)
bidi_model.fit(tmp_x, preproc_french_sentences, batch_size=1024, epochs=20, validation_split=0.2)
# Print prediction(s)
print(logits_to_text(bidi_model.predict(tmp_x[:1])[0], french_tokenizer))
双方向RNNモデルの検証セット精度は0.5992であった.
モデル4:エンコーダ-デコーダフレームワーク
エンコーダは文のマトリクス表現を構築し、デコーダはそのマトリクスを入力として予測の翻訳を出力する.
def encdec_model(input_shape, output_sequence_length, english_vocab_size, french_vocab_size):
learning_rate = 1e-3
model = Sequential()
model.add(GRU(128, input_shape = input_shape[1:], return_sequences = False))
model.add(RepeatVector(output_sequence_length))
model.add(GRU(128, return_sequences = True))
model.add(TimeDistributed(Dense(french_vocab_size, activation = 'softmax')))
model.compile(loss = sparse_categorical_crossentropy,
optimizer = Adam(learning_rate),
metrics = ['accuracy'])
return model
tests.test_encdec_model(encdec_model)
tmp_x = pad(preproc_english_sentences)
tmp_x = tmp_x.reshape((-1, preproc_english_sentences.shape[1], 1))
encodeco_model = encdec_model(
tmp_x.shape,
preproc_french_sentences.shape[1],
len(english_tokenizer.word_index)+1,
len(french_tokenizer.word_index)+1)
encodeco_model.fit(tmp_x, preproc_french_sentences, batch_size=1024, epochs=20, validation_split=0.2)
print(logits_to_text(encodeco_model.predict(tmp_x[:1])[0], french_tokenizer))
エンコーダ-デコーダモデルの検証セットの精度は0.6406です.
モデル5:カスタム深度モデル
単語埋め込みと双方向RNNをモデルに統合するmodel_を構築します.final.
そこで,GPUパラメータを256に変更したり,学習率を0.005に変更したり,モデルに対して20 epochsより多く(または少ない)訓練したりするなど,いくつかの実験を行う必要がある.
def model_final(input_shape, output_sequence_length, english_vocab_size, french_vocab_size):
model = Sequential()
model.add(Embedding(input_dim=english_vocab_size,output_dim=128,input_length=input_shape[1]))
model.add(Bidirectional(GRU(256,return_sequences=False)))
model.add(RepeatVector(output_sequence_length))
model.add(Bidirectional(GRU(256,return_sequences=True)))
model.add(TimeDistributed(Dense(french_vocab_size,activation='softmax')))
learning_rate = 0.005
model.compile(loss = sparse_categorical_crossentropy,
optimizer = Adam(learning_rate),
metrics = ['accuracy'])
return model
tests.test_model_final(model_final)
print('Final Model Loaded')
予測
def final_predictions(x, y, x_tk, y_tk):
tmp_X = pad(preproc_english_sentences)
model = model_final(tmp_X.shape,
preproc_french_sentences.shape[1],
len(english_tokenizer.word_index)+1,
len(french_tokenizer.word_index)+1)
model.fit(tmp_X, preproc_french_sentences, batch_size = 1024, epochs = 17, validation_split = 0.2)
y_id_to_word = {value: key for key, value in y_tk.word_index.items()}
y_id_to_word[0] = ''
sentence = 'he saw a old yellow truck'
sentence = [x_tk.word_index[word] for word in sentence.split()]
sentence = pad_sequences([sentence], maxlen=x.shape[-1], padding='post')
sentences = np.array([sentence[0], x[0]])
predictions = model.predict(sentences, len(sentences))
print('Sample 1:')
print(' '.join([y_id_to_word[np.argmax(x)] for x in predictions[0]]))
print('Il a vu un vieux camion jaune')
print('Sample 2:')
print(' '.join([y_id_to_word[np.argmax(x)] for x in predictions[1]]))
print(' '.join([y_id_to_word[np.max(x)] for x in y[0]]))
final_predictions(preproc_english_sentences, preproc_french_sentences, english_tokenizer, french_tokenizer)
文の完璧な翻訳を得たと同時に、セットの精度が0.9776であることを検証しました.
原文链接:medium.com/@actsusanli…