2017-10-27 40 views
0

Reber Grammarの入力(現在は埋め込まれていません)のRNN(特定ではない)を理解しようとしています。あなたはthis linkでジュピターノートを見つけることができます(最初のバージョンで出力に失敗したため、マークダウンを無視してください。最新ではありません:))Keras - 訓練された多対多モデルを1対多のモデル(ジェネレータ)に変換します。

すべてのタイムステップについて、トレーニングの入力と予想される出力を提供します(多対多モデルなので)。

  • 入力/出力は、例えば

    • B [1、0、0、0、0、0、0になるように(文字列 "BTSXPVE" に基づいて) "OneHotEncoded" され]タイムステップのために
    • V [0、0、0、0、0、1、0]
  • を、私は(不明な長さの文字列を持って、ここでエンコードされません例えば)それをより明確にするために:

    • BPVVE
    • BPVPXVPXVPXVVE

をので、私は20のタイムステップにパッドにそれらを決めました。

  • バッチについては、私は無料です。私はトレーニングのために2048の符号化された文字列を生成し、テストのために256を生成しました

私の入力テンソルは(2048,20,7)です。私の出力テンソルも(2048、20、7)です。タイムステップごとに予測をしたいからです。

私は次のコードのように3つの多対多モデル(Simple RNN、GRU、LSTM)を訓練しました。

model = Sequential() 

model.add(LSTM(units=7, input_shape=(maxlen, 7), return_sequences=True)) 
model.compile(loss='mse', 
       optimizer='Nadam', 
       metrics=['mean_squared_error']) 

history = model.fit(X_train, y_train, validation_data=(X_test, y_test), 
        epochs=1500, batch_size=1024) 

予想されたように、すべての時間ステップのために、私は(クリーンアップのビットの後)は、例えば、特定の値を取得する可能性を有する:

B [0、0.622、0、0を予測します、0.401、0、0](Tを有する60%Pを有する40%)

これはワード


を生成するために、グラフに基づいて正しいです

ここでは、このモデルを使用して文字列を生成したいと思います(1対多のモデル)ので、モデルを保持してジェネレータとして使用する方法はわかりません。

私は、Bの入力(20のタイムステップまで)を入力し、結果を得て、Bを出力の最良のインデックスと連結し、20のタイムステップにパッドし、NNに必要な入力を供給すると考えましたに。しかし、私はこれが私たちがやるべき方法ではないことを確信しています:s

さらに、出力の確率(SまたはXでなければならない)を確認するために 'B'と 'T'を入力しようとしました。私が得た:

X = np.array([[[1,0,0,0,0,0,0], [0,1,0,0,0,0,0]]]) # [[[B, P]]] 
X = sequence.pad_sequences(X, maxlen=20) 
print(model.predict(X)[0]) 

[0、0.106、0.587、0.1、0、0.171、0.007]

私は理解することがpreditであることT(10%)、S(60 BT後には、VとTの間でVとTはB/Pの後でのみ可能であるため、Xには%以上、V/Tではほとんどないはずです。私のモデルがn-1タイムステップを考慮していなかったようなものです。だから、多分私のモデルが間違っている:(

enter image description here

ご支援に感謝、

+0

「Y」として何を使用しましたか?それは 'X'が一歩進んだのでしょうか? –

+0

正確には、1ステップ移動して最終出力として "E"を追加します(同じサイズを維持する) –

+0

モデルの精度については、それらのシーケンスを理解するには小さすぎるかもしれません。より多くのレイヤーを追加するには、例えば、1つ(またはそれ以上)の最初のレイヤーをさらに多く、次に最後のレイヤーを7つのユニットにすることができます。 –

答えて

1

あなたはstateful=Trueモデルとしてこのモデルを作り直すことができます。それはtimesteps=1(または可変長のためNone)で作業してください。

newModel = Sequential() 

newModel.add(LSTM(units=7, stateful=True,batch_input_shape=(1,1,7), return_sequences=True)) 

モデルをリメイク予測でモデル使用

newModel.set_weights(model.get_weights()) 

::他のモデルから重みを取得0

このモデルで、今

を入力する必要がありますだけで一歩一度に。だから

我々が始まる手紙Bを持っていると仮定します。そして、あなたは、あなたが入力する新しいシーケンスを行っているたびにreset_states()に注意する必要があります。結果の品質について

startingLetter = oneHotForBWithShape((1,1,7)) 


#we are starting a new "sentence", so, let's reset states: 
newModel.reset_states() 

#now the prediction loop: 
nextLetter = startingLetter 
while nextLetter != endLetter: 
    nextLetter = newModel.predict(nextLetter) 
    nextLetter = chooseOneFromTheProbabilities(nextLetter) 

....多分あなたのモデルは、そのためにあまりにも小さなあります。あなたがCAY

は、例えば、複数の層を試してみてください。

model = Sequential() 

model.add(LSTM(units=50, input_shape=(maxlen, 7), return_sequences=True)) 
model.add(LSTM(units=30, return_sequences=True)) 
model.add(LSTM(units=7, return_sequences=True)) 

この選択は任意だった、それは十分に良いか、あなたのデータのためにあまりにも良いことだと、私は知りません。

+0

モデルから別の「異なる」ものに重さを設定する可能性があります!ありがとうたくさん:) –

+0

はい:) - 秘密はLSTMsが単にシーケンスの長さを気にしないということです。長さは "状態"の中で重要になるが、 "体重"では重要ではない。 2つのモデルが同じ数のレイヤーを持ち、ユニットと入力フィーチャーの数が同じである限り、それらは同じモデルです。 –

+0

私はあなたの返事を見て少し怖かったですが、それもGRUとSimpleRNNと一緒に働くので、今すぐ私はそれらを比較することができます –

関連する問題