deep-learning - 理解有状态的 LSTM

标签 deep-learning keras lstm recurrent-neural-network stateful

关闭。这个问题需要更多 focused .它目前不接受答案。












想改进这个问题?更新问题,使其仅关注一个问题 editing this post .

1年前关闭。




Improve this question




我正在经历这个tutorial在 RNN/LSTM 上,我很难理解有状态的 LSTM。我的问题如下:

1.训练批量大小

RNNs 上的 Keras 文档中,我发现i中样本的隐藏状态批处理中的第 - 个位置将作为 i 中样本的输入隐藏状态提供- 下一批中的第一个位置。这是否意味着如果我们想将隐藏状态从一个样本传递到另一个样本,我们必须使用大小为 1 的批处理,从而执行在线梯度下降?有没有办法在大小>1的批处理中传递隐藏状态并对该批处理执行梯度下降?

2. 单字符映射问题

在教程的段落“单字符到单字符映射的有状态 LSTM”中,给出了一个使用 batch_size = 1 的代码。和 stateful = True学习根据字母表中的字母预测字母表的下一个字母。在代码的最后一部分(第 53 行到完整代码的末尾),模型从一个随机字母 ('K') 开始进行测试,并预测'B',然后给定'B',它预测'C',等等. 除了'K',它似乎运作良好。但是,我尝试对代码进行以下调整(最后一部分,我保留了第 52 行及以上):

    # demonstrate a random starting point
    letter1 = "M"
    seed1 = [char_to_int[letter1]]
    x = numpy.reshape(seed, (1, len(seed), 1))
    x = x / float(len(alphabet))
    prediction = model.predict(x, verbose=0)
    index = numpy.argmax(prediction)
    print(int_to_char[seed1[0]], "->", int_to_char[index])
    letter2 = "E"
    seed2 = [char_to_int[letter2]]
    seed = seed2
    print("New start: ", letter1, letter2)
    for i in range(0, 5):
        x = numpy.reshape(seed, (1, len(seed), 1))
        x = x / float(len(alphabet))
        prediction = model.predict(x, verbose=0)
        index = numpy.argmax(prediction)
        print(int_to_char[seed[0]], "->", int_to_char[index])
        seed = [index]
    model.reset_states()

and these outputs:

    M -> B
    New start: M E
    E -> C
    C -> D
    D -> E
    E -> F

It looks like the LSTM did not learn the alphabet but just the positions of the letters, and that regardless of the first letter we feed in, the LSTM will always predict B since it's the second letter, then C and so on.

因此,将先前的隐藏状态作为当前隐藏状态的初始隐藏状态如何帮助我们学习,因为在测试期间,如果我们以字母“K”开头,例如,字母 A 到 J 之前不会被输入并且初始隐藏状态不会与训练期间相同?

3. 在一本书上训练一个 LSTM 来生成句子

我想在一整本书上训练我的 LSTM 以学习如何生成句子,也许还学习作者的风格,我怎样才能自然地在该文本上训练我的 LSTM(输入整个文本并让 LSTM 找出单词之间的依赖关系) 而不是自己“人为地”从那本书中创建成批的句子来训练我的 LSTM?我相信我应该使用有状态的 LSTM 会有所帮助,但我不确定如何。

最佳答案

  • 在 Keras 中有一个有状态的 LSTM 意味着将使用一个 Keras 变量来存储和更新状态,实际上您可以随时检查状态向量的值(也就是说,直到您调用 reset_states() )。另一方面,无状态模型将在每次处理批处理时使用初始零状态,因此就好像您总是在 reset_states()train_on_batchtest_on_batch 之后调用 predict_on_batch 。关于状态被重用于下一批有状态模型的解释就是与无状态模型的区别。当然,状态将始终在批处理中的每个序列中流动,并且您不需要有大小为 1 的批处理来发生这种情况。我看到有状态模型有用的两种情况:
  • 你想训练分割的数据序列,因为这些序列很长,而且在整个长度上训练是不切实际的。
  • 在预测时间,您希望检索序列中每个时间点的输出,而不仅仅是在末尾(因为您想将其反馈回网络或因为您的应用程序需要它)。我个人在我导出以供以后集成的模型中这样做(它们是批量大小为 1 的训练模型的“副本”)。
  • 我同意字母表的 RNN 示例在实践中似乎并不是很有用;它仅在您以字母 A 开头时才有效。如果您想学习重现从任何字母开始的字母表,则需要使用此类示例(字母表的子序列或旋转)来训练网络。但我认为一个常规的前馈网络可以学习预测字母表的下一个字母,训练像 (A, B), (B, C) 等这样的对。我认为这个例子比其他任何东西都更适合演示目的.
  • 您可能已经阅读过它,但热门帖子 The Unreasonable Effectiveness of Recurrent Neural Networks 显示了一些有趣的结果,这些结果与您想要做的事情一致(尽管它并没有真正深入到实现细节)。我没有使用文本数据训练 RNN 的个人经验,但是您可以研究许多方法。您可以构建基于字符的模型(如帖子中的模型),您可以在其中一次输入并接收一个字符。更高级的方法是对文本进行一些预处理,并将它们转换为数字序列; Keras 包含一些 text preprocessing functions 来做到这一点。将单个数字作为特征空间可能效果不佳,因此您可以简单地将每个单词转换为具有 one-hot 编码的向量,或者更有趣的是,让网络为每个词学习最佳向量表示,这就是他们所说的 en embedding 。您可以进一步进行预处理并查看 NLTK 之类的内容,特别是如果您想删除停用词、标点符号等。最后,如果您有不同大小的序列(例如,您使用的是全文而不是固定大小的摘录,这对您可能重要也可能不重要),您需要更加小心并使用 masking 和/或 sample weighting .根据具体问题,您可以相应地设置培训。如果您想学习生成相似的文本,“Y”将类似于“X”(单热编码),仅移动一个(或多个)位置(在这种情况下,您可能需要使用 return_sequences=TrueTimeDistributed layers)。如果您想确定作者,您的输出可能是 softmax Dense layer

  • 希望有帮助。

    关于deep-learning - 理解有状态的 LSTM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41695117/

    相关文章:

    python - 如何重构 cnn 层的输出张量以供简单的 pytorch 模型中的线性层使用

    tensorflow - TensorFlow 中 logits 一词的含义是什么?

    tensorflow - 如何使用 TFRecordWriter 写入 tf.Data.dataset.take() 的结果?

    python - Keras model.predict() 在第一次迭代时变慢然后变快

    python - 在 tensorflow 中使用 LSTM RNN 进行分类,ValueError : Shape (1, 10, 5) 必须具有等级 2

    tensorflow - keras GRU 层中的返回状态和返回序列有什么区别?

    deep-learning - caffe 中的 L2 正则化,从 lasagne 转换

    python - 在tensorflow中将一个2d张量动态划分为多个张量

    python - 分配 Keras 张量的索引条目

    machine-learning - 如何限制 LSTM 模型中的序列预测以匹配特定模式?