我正在阅读有关RNN/LSTM的本教程,我很难理解有状态的LSTM.我的问题如下:
1.培训批量大小在关于RNN的Keras文档中,我发现i
批次中位于样本中的样本的隐藏状态将作为输入隐藏状态提供i
给下一批中的样本.这是否意味着如果我们想要将隐藏状态从样本传递到样本,我们必须使用大小为1的批次,因此执行在线梯度下降?有没有办法在批量> 1的批次中传递隐藏状态并在该批次上执行梯度下降?
在教程的段落中,"一个字符到一个字符映射的状态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_batch
,test_on_batch
和predict_on_batch
.有关状态被重用于有状态模型的下一批次的解释与非有状态有关; 当然,国家将始终在该批次中流动,你就没有需要有大小为1批次为实现这一目标.我看到有状态模型有用的两种情况:
你想训练分裂的数据序列,因为这些数据非常长,并且在整个长度上进行训练是不切实际的.
在预测时间,您希望检索序列中每个时间点的输出,而不仅仅是最后(因为您要将其反馈回网络或因为您的应用程序需要它).我个人在我导出的模型中这样做以便以后集成(这是训练模型的"副本",批量大小为1).
我同意字母表的RNN例子在实践中看起来并不是很有用; 只有当你从字母A开始时它才会起作用.如果你想学习从任何字母开始重现字母表,你需要用这种例子(字母表的子序列或旋转)训练网络.但我认为一个常规的前馈网络可以学习预测下一个字母表培训的字母,如(A,B),(B,C)等.我认为这个例子仅用于说明目的而不是其他任何目的.
您可能已经阅读过它,但是流行的帖子"回归神经网络的不合理有效性"显示了一些有趣的结果(尽管它并没有真正涉及实现细节).我没有使用文本数据培训RNN的个人经验,但您可以研究多种方法.您可以构建基于字符的模型(如帖子中的模型),您可以一次输入和接收一个字符.更高级的方法是对文本进行一些预处理,并将它们转换为数字序列; Keras包含一些文本预处理功能.将一个数字作为特征空间可能无法正常工作,因此您可以简单地将每个单词转换为具有单热编码的向量,或者更有趣的是,让网络为每个单词学习最佳向量表示,其中他们称之为en embedding.您可以进一步使用预处理并查看类似NLTK的内容,特别是如果您想删除停用词,标点符号等内容.最后,如果你有不同大小的序列(例如你使用的是全文而不是固定大小的摘录,这对你来说可能重要或不重要),你需要更加小心并使用掩蔽和/或样本加权.根据确切的问题,您可以相应地设置培训.如果你想学习生成类似的文本,"Y"将类似于"X"(单热编码),只移位一个(或更多)位置(在这种情况下你可能需要使用return_sequences=True
和TimeDistributed层).如果要确定autor,则输出可以是softmax Dense图层.
希望有所帮助.