Keras - "转换"经过训练的多对多模型到一对多模型(生成器)

时间:2017-10-27 17:01:58

标签: neural-network keras recurrent-neural-network

我尝试使用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个用于训练的编码字符串和256个用于测试的字符串。

所以我的输入张量是(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个时间步长就好了。也许我的模型错了:(

enter image description here

非常感谢您的支持,

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))

这个选择是随意的,我不知道它对你的数据是好还是好。