【问题标题】:Keras, stateless LSTMKeras,无状态 LSTM
【发布时间】:2018-03-30 11:34:33
【问题描述】:

这是一个非常简单的 LSTM 在无状态模式下的示例,我们在一个非常简单的序列 [0–>1][0–>2] 上对其进行训练

知道为什么它不会在无状态模式下收敛吗?

我们有一个大小为 2 的批次,包含 2 个样本,它应该保持批次内的状态。在预测时,我们希望连续收到 1 和 2。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM 
import numpy
# define sequences
seq = [0, 1, 0, 2]
# convert sequence into required data format. 
#We are going to extract 2 samples [0–>1] and [0–>2] and convert them into one hot vectors
seqX=numpy.array([[( 1. , 0. , 0.)], [( 1. , 0. , 0.)]])
seqY=numpy.array([( 0. , 1. , 0.) , ( 0. , 0. , 1.)])

# define LSTM configuration
n_unique = len(set(seq)) 
n_neurons = 20
n_batch = 2
n_features = n_unique #which is =3
# create LSTM
model = Sequential()
model.add(LSTM(n_neurons, input_shape=( 1, n_features)  ))
model.add(Dense(n_unique, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='Adam')
# train LSTM
model.fit(seqX, seqY, epochs=300, batch_size=n_batch, verbose=2, shuffle=False)
# evaluate LSTM 
print('Sequence')
result = model.predict_classes(seqX, batch_size=n_batch, verbose=0)
for i in range(2):
    print('X=%.1f y=%.1f, yhat=%.1f' % (0, i+1, result[i]))

示例 2 在这里我想澄清一下我想要什么结果。

相同的代码示例,但处于有状态模式 (stateful=True)。它完美地工作。我们用零向网络输入 2 次,得到 1,然后是 2。但我想在无状态模式下得到相同的结果,因为它应该将状态保持在批处理中。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM 
import numpy
# define sequences
seq = [0, 1, 0, 2]
# convert sequences into required data format
seqX=numpy.array([[( 1. , 0. , 0.)], [( 1. , 0. , 0.)]])
seqY=numpy.array([( 0. , 1. , 0.) , ( 0. , 0. , 1.)])

# define LSTM configuration
n_unique = len(set(seq))
n_neurons = 20
n_batch = 1
n_features = n_unique
# create LSTM
model = Sequential()
model.add(LSTM(n_neurons, batch_input_shape=(n_batch, 1, n_features), stateful=True  ))
model.add(Dense(n_unique, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='Adam')
# train LSTM
for epoch in range(300):
    model.fit(seqX, seqY, epochs=1, batch_size=n_batch, verbose=2, shuffle=False)
    model.reset_states()
# evaluate LSTM 
print('Sequence')
result = model.predict_classes(seqX, batch_size=1, verbose=0)
for i in range(2):
    print('X=%.1f y=%.1f, yhat=%.1f' % (0, i+1, result[i]))

作为正确的结果,我们应该得到:

顺序

X=0.0 y=1.0, yhat=1.0

X=0.0 y=2.0, yhat=2.0

【问题讨论】:

  • 您有两个相等的序列并期望每个序列有一个不同的输出?
  • seqX.shape = (2,1,3) --> 我们有两个序列,每个序列只有一个时间步长(因此,没有序列),每个步长三个特征。
  • 我们用零(2 个向量 1,0,0)向网络馈送 2 次,并期望先预测 1(向量 0,1,0)然后预测 2(向量 0,0,2 ) .即 [0–>1] 和 [0–>2]。应该记住这个顺序。
  • 您必须用两步输入一个序列,而不是一步输入两个序列。 seqX.shape = (1,2,3).

标签: keras sequence lstm stateless


【解决方案1】:

您必须用两个步骤输入一个序列,而不是用一个步骤输入两个序列:

  • 一个序列,两个步骤:seqX.shape = (1,2,3)
  • 两个序列,一步:seqX.shape = (2,1,3)

输入形状为(numberOfSequences, stepsPerSequence, featuresPerStep)

seqX = [[[1,0,0],[1,0,0]]]

如果你想得到 y 的两个步骤作为输出,你必须使用return_sequences=True

LSTM(n_neurons, input_shape=( 1, n_features), return_sequences=True)

整个工作代码:

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM 
import numpy

# define sequences
seq = [0, 1, 0, 2]

# convert sequence into required data format. 
#We are going to extract 2 samples [0–>1] and [0–>2] and convert them into one hot vectors
seqX=numpy.array([[[ 1. , 0. , 0.], [ 1. , 0. , 0.]]])
seqY=numpy.array([[[0. , 1. , 0.] , [ 0. , 0. , 1.]]])
    #shapes are (1,2,3) - 1 sequence, 2 steps, 3 features 

# define LSTM configuration
n_unique = len(set(seq)) 
n_neurons = 20
n_features = n_unique #which is =3
#no need for batch size

# create LSTM
model = Sequential()

model.add(LSTM(n_neurons, input_shape=( 2, n_features),return_sequences=True))
    #the input shape must have two steps    

model.add(Dense(n_unique, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='Adam')

# train LSTM
model.fit(seqX, seqY, epochs=300, verbose=2) 
   #no shuffling and no batch size needed. 

# evaluate LSTM 
print('Sequence')
result = model.predict_classes(seqX, verbose=0)
print(seqX)
print(result) #all steps are predicted in a single array (with return_sequences=True)

【讨论】:

  • 那么第二个例子呢?尽管输入和输出具有与第一个示例相同的形状并且不需要 "return_sequences" ,但它工作正常,我们只是在每次更新后显式重置状态。为什么我们不能在无状态模式下做同样的事情?
  • 第二个例子不起作用。它正在打印X=0.0 y=1.0, yhat=1.0X=0.0 y=2.0, yhat=1.0。您的结果在 yhat 中(始终为 1)。在y 中,您正在打印(i+1)
  • 如果您在不同批次中预测每个步骤,则不需要在有状态层中返回序列,因为每个预测都会返回一个值。 --- 在非状态层中,您必须一次预测所有步骤。
  • 第二个例子工作正常。只是不要忘记设置 n_batch = 1,model.reset_states()。结果为:序列 X=0.0 y=1.0, yhat=1.0 X=0.0 y=2.0, yhat=2.0
  • 在 model.reset_states() 之前按 4 次空格键。它没有复制正确。它应该与model.fit处于同一级别
猜你喜欢
  • 1970-01-01
  • 2017-08-31
  • 2018-04-04
  • 2017-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
相关资源
最近更新 更多