【问题标题】:Keras - "Convert" a trained many-to-many model to one-to-many model (generator)Keras - 将经过训练的多对多模型“转换”为一对多模型(生成器)
【发布时间】:2018-04-09 08:40:54
【问题描述】:

我正在尝试使用 Reber Grammar 输入(暂时未嵌入)来理解 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 个时间步长一样。所以也许我的模型是错误的:(

非常感谢您的支持,

【问题讨论】:

  • 你用什么作为Y?是不是X挪了一步?
  • 没错,我将它移动了 1 步并添加“E”作为最终输出(以保持相同的大小)
  • 关于模型的精度,可能对于理解这些序列来说太小了。添加更多层,例如,您可以有一个(或多个)具有更多单元的第一层,然后是具有 7 个单元的最后一层。
  • 我会尝试,但我对结果有疑问,因为 NN “创建”熵。我有一个二进制输入并得到一个“概率”作为输出。如果我将它提供给另一层,我猜它会从这种噪音中产生噪音,但我会尝试用于学习目的
  • 我的意思是具有两层或多层的单个模型。这使模型“更聪明”(学习时间更长,但学得更好)。拥有太多层或单元可能会使您的模型过于智能(它可以记住训练数据,但无法理解测试数据 - 这称为过度拟合)。

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


【解决方案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))

这个选择是任意的,我不知道它对您的数据来说是足够好还是太好了。

【讨论】:

  • 将模型的权重设置为另一个“不同”模型的可能性真棒!!!非常感谢:)
  • Yes :) -- 秘密在于 LSTM 根本不关心序列的长度。长度在“状态”中变得很重要,但在“权重”中并不重要。只要两个模型具有相同的层数、相同的单元数和输入特征,它们就是相同的模型。
  • 当我看到你的回复时我有点害怕,但它也适用于 GRU 和 SimpleRNN,所以现在我可以比较它们了
  • 顺便说一句....你知道在github上有什么页面教你制作像你这样的笔记本吗?我要开始使用了。
  • 你必须在你的电脑上做你的笔记本,并在需要的时候将它推送到 github(例如展示给某人或“存储”它)。完成后,我只需将其推送到我的 git(通过使用 git 命令或 git gui 之类的工具)。如果你想安装 jupyter notebook,你可以关注 (jupyter.readthedocs.io/en/latest/install.html),使用 git,有几个教程,但我使用了youtube.com/…
猜你喜欢
  • 1970-01-01
  • 2017-05-11
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 2020-05-21
  • 2022-01-22
相关资源
最近更新 更多