我尝试使用Reber Grammar输入(目前尚未嵌入)了解RNN(非特定的RNN)。您可以在this link 上找到jupyter笔记本(请忽略降价,因为我在输出的第一个版本上失败并且它不是最新的:))。
对于每个时间步,我提供训练的输入和预期输出(因此它是多对多模型)。
输入/输出是" OneHotEncoded" (基于字符串" BTSXPVE")例如
- B是[1,0,0,0,0,0,0]
- V是[0,0,0,0,0,1,0]
对于时间步长,我有不知名长度的字符串(此处未编码以使其更清晰),例如:
- BPVVE
- BPVPXVPXVPXVVE
所以我决定将它们填充到20步。
所以我的输入张量是(2048,20,7)。我的输出张量也是(2048,20,7),因为对于每一个时间步,我都希望得到预测。
所以我训练了3个多对多模型(简单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](60%有T或40%有P)
根据图表生成单词
是正确的现在,我想使用此模型生成字符串(所以是一对多模型),但我不知道如何保留模型并将其用作生成器。
我想只输入B的输入(填充到20个步骤),得到结果,将B连接到输出的最佳索引,将其填充到20步,将需要输入提供给NN,依此类推。但我很确定这不是我们应该这样做的方式:s
此外,我试图输入' B'和' T'检查输出的概率是什么(应该是S或X),但我得到了:
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]
我所理解的是T(10%),S(60%),X(10%),V(18%),但在BT之后,我应该在X上获得更多的百分比,在V上几乎没有/ T(因为T之后的V和T只能在B / P之后)。如果我的模型没有考虑到n-1个时间步长就好了。也许我的模型错了:(
非常感谢您的支持,
答案 0 :(得分: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())
在预测中使用模型:
现在,使用此模型,您必须一次只输入一个步骤。每当你要输入一个新序列时,你必须小心reset_states()
:
所以,假设我们有一个起始字母B
。
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)
关于结果的质量....也许你的模型太小了。
你可以尝试更多图层,例如:
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))
这个选择是随意的,我不知道它对你的数据是好还是好。