Python 获取LSTMs中的预测状态

Python 获取LSTMs中的预测状态,python,keras,lstm,Python,Keras,Lstm,我正在尝试使用以下模型生成莎士比亚文本: model = Sequential() model.add(Embedding(len_vocab, 64)) model.add(LSTM(256, return_sequences=True)) model.add(TimeDistributed(Dense(len_vocab, activation='softmax'))) model.compile(loss='sparse_categorical_crossentropy', optimi

我正在尝试使用以下模型生成莎士比亚文本:

model = Sequential()
model.add(Embedding(len_vocab, 64))
model.add(LSTM(256, return_sequences=True))
model.add(TimeDistributed(Dense(len_vocab, activation='softmax')))

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.summary()
训练集由转换为数字的字符组成。其中
x
的形状为
(句子数,句子长度)
,而
y
的形状相同,其中
y
仅为
x
偏移一个字符。在这种情况下,
句子长度=40

然而,当我预测时,我一次预测一个字符。关于我如何使用模型进行拟合和预测,请参见下文:

for i in range(2):
    model.fit(x,y, batch_size=128, epochs=1)

    sentence = []
    letter = np.random.choice(len_vocab,1).reshape((1,1)) #choose a random letter
    for i in range(100):
        sentence.append(val2chr(letter))
        # Predict ONE letter at a time
        p = model.predict(letter)
        letter = np.random.choice(27,1,p=p[0][0])
    print(''.join(sentence))
然而,不管我训练了多少个阶段,我得到的都是jibberish的输出其中一个可能的原因是我没有从之前的预测中获得单元内存

所以问题是,在我预测之前,如何确保状态被发送到下一个单元格

完整的jupyter笔记本示例如下

编辑1: 我刚刚意识到我需要以先前的LSTMs隐藏状态发送,而不仅仅是单元内存。 此后,我尝试将模型重做为:

batch_size = 64

model = Sequential()
model.add(Embedding(len_vocab, 64, batch_size=batch_size))
model.add(LSTM(256, return_sequences=True, stateful=True))
model.add(TimeDistributed(Dense(len_vocab, activation='softmax')))

model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.summary()

但是,现在我无法一次预测一个字母,因为它需要
批量大小的输入。

使用Keras训练字符rnn的标准方法可以在官方示例中找到:

该模型基于maxlen字符序列进行训练。 训练此网络时,LSTM状态在每个序列后重置(默认情况下,stateful=False)

一旦训练了这样的网络,您可能希望一次输入和预测一个角色。最简单的方法(据我所知)是构建另一个具有相同结构的Keras模型,使用第一个模型的权重对其进行初始化,但使用Keras“有状态”模式下的RNN层:

在这种模式下,Keras必须知道批次的完整形状(参见文档)。
由于您只想向网络提供一步字符的一个样本,因此批处理的形状为(1,1,len(chars))。

正如@j-c-doe所指出的,您可以对一个批处理使用有状态选项并传递权重。我发现的另一种方法是继续展开LSTM并预测如下:

for i in range(150):
    sentence.append(int2char[letter[-1]])
    p = model.predict(np.array(letter)[None,:])
    letter.append(np.random.choice(len(char2int),1,p=p[0][-1])[0])
注意:预测的维度非常重要<代码>np。数组(字母)[None,:]
给出一个
(1,i+1)
形状。这样就不需要对模型进行修改


最重要的是,它不断地传递细胞状态记忆和隐藏状态。我不能完全确定它是否也通过了隐藏状态,或者它是否只是细胞状态。

也许可以看看?@Yu-Yang我恐怕这不是我想要的。这是一个多对一的预测(即在我的场景中,40个字母用于预测一个字母)。我的重点是如何将状态传递到下一个元素问题上。
model = Sequential()
model.add(LSTM(128, stateful=True, batch_input_shape=(1, 1, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
for i in range(150):
    sentence.append(int2char[letter[-1]])
    p = model.predict(np.array(letter)[None,:])
    letter.append(np.random.choice(len(char2int),1,p=p[0][-1])[0])