[[189448]] 以下は、ニューラル ネットワーク モデルにおける 4 つのシーケンス デコード モデルについて、一般的な言葉を使って、主に全体的な概念やアイデアから一般的な説明を提供して理解を助けるための、カジュアルなトーク、つまりランダムなチャットです。注意:時間と労力を節約するために、以下の数式は掲載しない場合があります。また、一部の詳細は省略されています。ご興味があれば、原文[1][2][3]を直接お読みください。 [1] ニューラルネットワークによるシーケンスツーシーケンス学習 [2] 統計的機械翻訳のためのRNNエンコーダー・デコーダーを用いたフレーズ表現の学習 [3] アラインメントと翻訳を共同学習するニューラル機械翻訳 ニューラル ネットワークを使用したシーケンス エンコーディングの主なモデルは RNN です。現在、セル ユニットのみが異なる LSTM と GRU などのバリアント モデルが人気です。以下はすべて RNN で表されます。 エンコードモデルは比較的単純です。下図に示すように、入力テキスト{X1-X6}は反復的にエンコードされ、各瞬間の隠れ層の状態を取得します。最後に、シーケンスが完了した後、特徴融合を実行して文の表現を取得します。一般的なアプローチは、最後の瞬間のエンコーディング モデルの隠れた状態をシーケンス全体のエンコーディング表現として使用することですが、この効果は実際のアプリケーションではあまり良くありません。したがって、この図では、シーケンス全体の隠れたエンコーディングの合計と平均を直接使用して、シーケンスのエンコーディング ベクトルを取得します。 初期のタスクは主にトピック分類や感情検出などの分類タスクでした。この場合、エンコーディング ベクトルにソフトマックスを追加することで問題を解決できます。ただし、機械翻訳や音声認識などの問題では、シリアル化デコードが必要になります。 エンコード時には、RNN には前の瞬間の隠れ状態のエンコードだけでなく、各瞬間の現在の瞬間の入力文字も含まれることに注意してください。一方、デコード時にはそのような入力はありません。そして、より直接的な方法は、エンコード側で得られたエンコードベクトルを、各瞬間のデコードモデルの入力特徴として使用することです。次の図に示すように: シンプルで直感的であり、デコードモデルとエンコードモデルに違いはありません。ただし、学者たちはこのモデルがエレガントではないと感じているので、より洗練されたモデルをいくつか紹介しましょう。 このモデルを説明するために、試験での不正行為を一般的な例として使用します。 まず、入力テキストは学習中の教科書であり、エンコード先は教科書の理解に基づいてまとめられた授業ノートであると仮定します。デコード側の隠れ層ニューラルネットワークが私たちの脳であり、各瞬間の出力が試験中にテスト用紙に記入される答えとなります。上記の最も単純なデコード モデルでは、試験中に授業のノートを見ながら解答を書くようなものと考えることができます。これが普通のカンニングをする学生のやり方なら、成績優秀な学生は教科書をめくる必要はありません。彼らは授業のノートを記憶できる強力な脳神経ネットワークを持っています。デコードするときは、以前に書いた内容を復習し、解答用紙に答えを一つずつ丁寧に書いていくだけです。これは次のモデルです[1]。 また、弱い生徒の中には、カンニングをするだけでなく、ノートを見返す際に前回解答用紙に書いた答えを復習しなければならない生徒も多くいます(弱い生徒は前回解答用紙に書いた単語すら思い出せないほど弱いです)。これは次のような解答パターンです[2]。 しかし、成績の悪い生徒もいます。彼らはカンニングをするだけでなく、解答用紙に書いた答えを最後の瞬間に見直すだけでなく、教師が教科書の重要なポイントを強調して、自分でノートを整理できるようにする必要があります(これは一種の注意メカニズムです。ノートを取るときは、テストの問題に応じて重要なポイントを強調する必要があります!)。教師は成績の悪い生徒を本当によく世話します。彼らの解答モードは次のとおりです[3]。 成績優秀な学生を除いて、他の学生は質問に答えながら授業ノートに目を通すというカンニングをしていたことがわかります(多くの文献では、これをデコードモデル構造の覗き見と呼んでいますが、カンニングのように見えませんか?)。また、成績の悪い学生も、先生に要点を強調するように求めました。要点がわかったら、本に目を通す必要はなく、ちらっと見るだけで済みます。文献では、これを「ちらっと見る」と呼んでいますが、カンニングのように見えませんか? 生徒の脳ネットワークを同じ構造に設定すると(IQ を一定に保つように強制すると)、不正行為をする生徒が間違いなく最高得点を獲得します。トップ生徒モードは不利です。簡単なモデルテストをしてみましょう。 テストデータ: 入力シーケンステキスト = ['1 2 3 4 5' 、'6 7 8 9 10′ 、'11 12 13 14 15′ 、'16 17 18 19 20′ , '21 22 23 24 25'] ターゲットシーケンステキスト = ['1 2 3 4 5' 、「6、7、8、9、10」 、「11、12、13、14、15」 、「16、17、18、19、120」 , '21 22 23 24 25'] いくつかのパラメータを次のように設定します。 – (「語彙数:」、51、「固有語」) ('入力最大長:', 5, '単語') ('ターゲット最大長:', 5, '単語') (「隠れたベクトルの次元」、20) (「トレーニングストーリーの数:」、5) (「テストストーリーの数:」、5) – トレーニング プロセスを観察します。 そのうち、第 1 デコード モデルは一般的な不正行為、第 2 デコード モデルは学術マスター モード、第 3 デコード モデルは学術的弱者不正行為、第 4 デコード モデルは学術的弱者不正行為です。 IQ値(デコードモデルのニューラルネットワーク構造)が同じ場合、成績の悪い生徒のカンニングモードの方が質問に速く答える(トレーニング収束速度)のに対し、成績上位の生徒のモードは質問に最も遅く答えることがわかります。 論文[1]で述べたように、Xuebaモデルで良好なパフォーマンスを達成するには、モデルの隠れ層に4,000個のノードが必要です(XuebaのIQは確かに高く、強力な脳ネットワークを持っています)。 考えてみてください。教科書の内容が多ければ、成績優秀な生徒でも疲れてしまいます。成績の悪い生徒は、授業中に理解できると確信していますか?成績の悪い生徒は笑ってしまうので、先生は彼らのために要点を強調します!!! このブログ記事でテストされたサンプルコードは、[Github アドレス] にあります。 - # -*- エンコーディング:utf-8 -*-
- 「」
- テストエンコーダー-デコーダー 2016/03/22
- 「」
- keras.modelsからSequentialをインポートする
- keras.layers.recurrentからLSTM をインポートします
- keras.layers.embeddingsからEmbedding をインポートします
- keras.layers.coreからRepeatVector、TimeDistributedDense、Activation をインポートします。
- seq2seq.layers.decodersからLSTMDecoder、LSTMDecoder2、AttentionDecoder をインポートします
- インポート時間
- numpyをnpとしてインポートする
- 輸入再
-
- __author__ = 'http://jacoxu.com'
-
-
- def pad_sequences(シーケンス, maxlen=None, dtype='int32′,
- パディング='pre'、切り捨て='pre'、値=0。):
- ”'各シーケンスをパディング 同じ長さに:
- 最長シーケンスの長さ。
-
- maxlenが指定されている場合は、 シーケンスが長くなる
- maxlen より長い場合は maxlenに切り捨てられます。
- 切り捨ては先頭(デフォルト)または
- 終わり シーケンスの。
-
- ポストパディングとプレパディングをサポートします (デフォルト)。
-
- # 引数
- シーケンス:各要素がシーケンスであるリストのリスト
- maxlen: int 、最大長
- dtype: 入力する 結果のシーケンスをキャストします。
- パディング: 'pre'または'post'、前または後にパディング 各シーケンスの後に。
- 切り捨て: 'pre'または'post'、値を削除 より大きいシーケンスから
- 最初にmaxlenまたは 最後に シーケンスの
- value: float 、シーケンスを目的の値にパディングする値。
-
- #返品
- x:次元 (number_of_sequences, maxlen)を持つnumpy 配列
- ”'
- 長さ = [シーケンス内のsのlen(s)]
-
- nb_samples = len(シーケンス)
- maxlenがNoneの場合:
- maxlen = np.max (長さ)
-
- #最初の空でないシーケンスからサンプルシェイプを取得します
- #以下のメインループで一貫性をチェックします。
- sample_shape = タプル()
- シーケンス内のsの場合:
- len(s) > 0の場合:
- sample_shape = np.asarray(s).shape[1:]
- 壊す
-
- x = (np.ones((nb_samples, maxlen) sample_shape) * 値).astype(dtype)
- enumerate(シーケンス)のidx、sの場合:
- len(s) == 0の場合:
- 続行# 空のリストが見つかりました
- 切り捨て == 'pre' の場合:
- 切り捨て = s[-maxlen:]
- elif 切り捨て == 'post':
- 切り捨て = s[:maxlen]
- それ以外:
- ValueError が発生します ('切り捨て型 "%s" が認識されません' % 切り捨て)
-
- # `trunc` が期待通りの形状であるかどうかをチェックする
- trunc = np.asarray(trunc, dtype=dtype)
- trunc.shape[1:] != sample_shapeの場合:
- ValueErrorが発生します('サンプル%sの形状 順序 位置 %sは、予想される形状 %s' %と異なります
- (trunc.shape[1:], idx, sample_shape))
-
- パディング == 'post' の場合:
- x[idx, :len(trunc)] = 切り捨て
- elif パディング == 'pre':
- x[idx, -len(trunc):] = trunc
- それ以外:
- ValueError が発生します ('パディング タイプ "%s" が認識されません' % padding)
- xを返す
-
-
- def vectorize_stories(input_list、tar_list、word_idx、input_maxlen、tar_maxlen、vocab_size):
- x_set = []
- Y = np.zeros((len(tar_list), tar_maxlen, vocab_size), dtype=np.bool)
- input_listの_sentの場合:
- x = [word_idx[w] _sent内のwの場合]
- x_set.append(x)
- enumerate(tar_list)のs_index、tar_tmpの場合:
- t_indexの場合、 enumerate(tar_tmp)のトークン:
- Y[s_index, t_index, word_idx[トークン]] = 1
-
- pad_sequences(x_set, maxlen=input_maxlen)、Yを返す
-
-
- def tokenize(送信):
- 句読点を含む文のトークンを返します。
-
- >>> tokenize('ボブはリンゴを落としました。 リンゴは何ですか?
- [ 「ボブ」 、 「落とした」 、 「その」 、 「リンゴ」 、 「.」 、 「どこ」 、 「その」 、 「リンゴ」 、 「?」 ]
- ”'
- [x.strip()をre.split( '(\W )?' 、 sent)内のxに対して返す(x.strip() の場合)]
-
-
- main() を定義します:
- 入力テキスト = [ '1 2 3 4 5'
- 、 '6 7 8 9 10'
- 、 '11 12 13 14 15'
- 、 '16 17 18 19 20'
- , '21 22 23 24 25' ]
- tar_text = [ '1、2、3、4、5'
- 、 「6、7、8、9、10」
- 、 「11、12、13、14、15」
- 、 「16、17、18、19、120」
- , '21 22 23 24 25' ]
-
- 入力リスト = []
- tar_list = []
-
- input_textのtmp_inputの場合:
- input_list.append(トークン化(tmp_input))
- tar_text内のtmp_tarの場合:
- tar_list.append(トークン化(tmp_tar))
-
- vocab = sorted(reduce(lambda x, y: x | y, ( set (tmp_list) for tmp_list in input_list tar_list)))
- # pad_sequencesによるマスク用に0を予約する
- vocab_size = len(vocab) 1 # kerasは埋め込みを実行するときにlen(vocab) 1を実行する必要があります
- input_maxlen = max (map(len, ( input_list内のxに対するx )))
- tar_maxlen = max (map(len, ( tar_list内のxについてx )))
- 出力次元 = 語彙サイズ
- 隠し次元 = 20
-
- 印刷('-')
- print('語彙サイズ:', vocab_size, 'ユニーク単語')
- print('入力最大長:', input_maxlen, 'words')
- print('ターゲット最大長:', tar_maxlen, 'words')
- print('隠しベクトルの次元:', hidden_dim)
- print('トレーニングストーリーの数:', len(input_list))
- print('テストストーリーの数:', len(input_list))
- 印刷('-')
- print('単語シーケンスをベクトル化しています…')
- word_to_idx = dict((c, i 1) for i, c in enumerate(vocab)) # エンコードには文字をデジタルインデックスにマッピングする必要がある
- idx_to_word = dict((i 1, c) for i, c in enumerate(vocab)) # デコード時に、数値インデックスを文字にマッピングする必要があります
- inputs_train、tars_train = vectorize_stories(input_list、tar_list、word_to_idx、input_maxlen、tar_maxlen、vocab_size)
-
- デコーダーモード = 1 # 0 最もシンプルなモード、1 [1] 後方モード、2 [2] ピークモード、3 [3] 注意モード
- デコーダーモード == 3 の場合:
- エンコーダートップレイヤー = LSTM(hidden_dim, return_sequences= True )
- それ以外:
- エンコーダートップレイヤー = LSTM(hidden_dim)
-
- デコーダーモード == 0 の場合:
- デコーダートップレイヤー = LSTM(hidden_dim, return_sequences= True )
- デコーダートップレイヤー.get_weights()
- elif デコーダーモード == 1:
- デコーダートップレイヤー = LSTMDecoder(hidden_dim=hidden_dim、output_dim=hidden_dim
- 、output_length=tar_maxlen、state_input= False 、return_sequences= True )
- elif デコーダーモード == 2:
- デコーダートップレイヤー = LSTMDecoder2(hidden_dim=hidden_dim、output_dim=hidden_dim
- 、output_length=tar_maxlen、state_input= False 、return_sequences= True )
- elif デコーダーモード == 3:
- デコーダートップレイヤー = AttentionDecoder(hidden_dim=hidden_dim、output_dim=hidden_dim
- 、output_length=tar_maxlen、state_input= False 、return_sequences= True )
-
- en_de_model = シーケンシャル()
- en_de_model.add (埋め込み(input_dim=vocab_size,
- output_dim=hidden_dim、
- input_length=入力最大長))
- en_de_model.add (encoder_top_layer)を追加します。
- デコーダーモード == 0 の場合:
- en_de_model. add (RepeatVector(tar_maxlen))
- en_de_model.add (decoder_top_layer) (デコーダートップレイヤー)
-
- en_de_model.add (TimeDistributedDense(output_dim))
- en_de_model.add(アクティベーション('softmax'))
- print('コンパイル中…')
- time_start =時間.時間()
- en_de_model.compile(損失='categorical_crossentropy'、オプティマイザー='rmsprop')
- time_end =時間.時間()
- print('コンパイルされました。所要時間:%f秒!' % (time_end - time_start))
- iter_numが範囲(5000)の場合:
- en_de_model.fit(inputs_train、tars_train、batch_size=3、nb_epoch=1、show_accuracy= True )
- out_predicts = en_de_model.predict(inputs_train)
- i_idx 、out_predict をenumerate(out_predicts)で指定します:
- 予測シーケンス = []
- out_predictのpredict_vectorの場合:
- next_index = np.argmax(予測ベクトル)
- 次のトークン = idx_to_word[次のインデックス]
- 予測シーケンス.append(次のトークン)
- print('ターゲット出力:', tar_text[i_idx])
- print('予測出力:', predict_sequence)
-
- print('現在のiter_numは:%d' % iter_num)
-
- __name__ == '__main__' の場合:
- 主要()
|