我正在努力调和我对LSTM的理解,并在Keras实施的this post by Christopher Olah中指出。我正在关注Keras教程的blog written by Jason Brownlee。我最担心的是,
[samples, time steps, features]
和让我们参考下面粘贴的代码集中讨论上述两个问题:
# reshape into X=t and Y=t+1
look_back = 3
trainX, trainY = create_dataset(train, look_back)
testX, testY = create_dataset(test, look_back)
# reshape input to be [samples, time steps, features]
trainX = numpy.reshape(trainX, (trainX.shape[0], look_back, 1))
testX = numpy.reshape(testX, (testX.shape[0], look_back, 1))
########################
# The IMPORTANT BIT
##########################
# create and fit the LSTM network
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
for i in range(100):
model.fit(trainX, trainY, nb_epoch=1, batch_size=batch_size, verbose=2, shuffle=False)
model.reset_states()
注意:create_dataset采用长度为N的序列并返回N-look_back
数组,其中每个元素都是look_back
长度序列。
可以看出,TrainX是一个三维数组,其中Time_steps和Feature分别是最后两个维度(在此特定代码中为3和1)。关于下面的图像,这是否意味着我们正在考虑many to one
情况,其中粉红色方框的数量为3?或者字面意思是链长是3(即只考虑3个绿色方框)。
当我们考虑多元系列时,功能参数是否相关?例如同时模拟两个金融股?
有状态LSTM是否意味着我们在批次运行之间保存单元格内存值?如果是这种情况,batch_size
就是一个,并且在训练运行之间重置内存,所以说它是有状态的。我猜这与训练数据没有改组的事实有关,但我不确定如何。
有什么想法? 图片参考:http://karpathy.github.io/2015/05/21/rnn-effectiveness/
对于@ van关于红色和绿色方框相同的评论有点困惑。所以,为了确认,以下API调用是否与展开的图表相对应?特别注意第二个图(batch_size
被任意选择。):
对于那些已完成Udacity深度学习课程且仍然对time_step参数感到困惑的人,请查看以下讨论:https://discussions.udacity.com/t/rnn-lstm-use-implementation/163169
事实证明model.add(TimeDistributed(Dense(vocab_len)))
正是我所寻找的。以下是一个示例:https://github.com/sachinruk/ShakespeareBot
我总结了我对LSTM的大部分理解:https://www.youtube.com/watch?v=ywinX5wgdEU
答案 0 :(得分:119)
时间步骤意味着什么:X.shape中的Time-steps==3
(描述数据形状)意味着有三个粉红色框。由于在Keras中每个步骤都需要输入,因此绿色框的数量通常应该等于红色框的数量。除非你破解结构。
多对多对多对多:在keras中,初始化return_sequences
或LSTM
或{{1}时会有GRU
个参数}。如果SimpleRNN
为return_sequences
(默认情况下),那么多对一,如图所示。它的返回形状为False
,代表最后一个状态。当(batch_size, hidden_unit_length)
为return_sequences
时,则多对多。它的返回形状为True
功能参数是否相关:功能参数表示“红框有多大”或每步的输入维度是多少。如果您想从8种市场信息中预测,那么您可以使用(batch_size, time_step, hidden_unit_length)
生成数据。
有状态:您可以查找the source code。初始化状态时,如果feature==8
,则上次训练的状态将用作初始状态,否则将生成新状态。我还没有打开stateful==True
。但是,我不同意stateful
时batch_size
只能为1 stateful==True
。
目前,您使用收集的数据生成数据。图像您的股票信息将作为流而来,而不是等待一天收集所有顺序,您希望在使用网络进行培训/预测时生成输入数据在线。如果您有400只股票共享同一个网络,那么您可以设置batch_size==400
。
答案 1 :(得分:96)
作为已接受答案的补充,这个答案显示了keras行为以及如何实现每张图片。
标准keras内部处理总是多对多,如下图所示(我使用features=2
,压力和温度,仅作为示例):
在此图像中,我将步数增加到5,以避免与其他维度混淆。
对于这个例子:
我们的输入数组应该是(N,5,2)
的形状:
[ Step1 Step2 Step3 Step4 Step5
Tank A: [[Pa1,Ta1], [Pa2,Ta2], [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B: [[Pb1,Tb1], [Pb2,Tb2], [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
....
Tank N: [[Pn1,Tn1], [Pn2,Tn2], [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
]
通常,LSTM层应该处理整个序列。划分窗户可能不是最好的主意。该层具有关于序列在向前发展时如何演变的内部状态。 Windows消除了学习长序列的可能性,将所有序列限制为窗口大小。
在Windows中,每个窗口都是长原始序列的一部分,但是通过Keras,它们将被视为一个独立的序列:
[ Step1 Step2 Step3 Step4 Step5
Window A: [[P1,T1], [P2,T2], [P3,T3], [P4,T4], [P5,T5]],
Window B: [[P2,T2], [P3,T3], [P4,T4], [P5,T5], [P6,T6]],
Window C: [[P3,T3], [P4,T4], [P5,T5], [P6,T6], [P7,T7]],
....
]
请注意,在这种情况下,您最初只有一个序列,但是您要在许多序列中将其划分以创建窗口。
"什么是序列"是抽象的。重要的部分是:
使用return_sequences=True
:
outputs = LSTM(units, return_sequences=True)(inputs)
#output_shape -> (batch_size, steps, units)
使用完全相同的图层,keras将执行完全相同的内部预处理,但是当您使用return_sequences=False
(或者只是忽略此参数)时,keras将自动丢弃上一个之前的步骤:
outputs = LSTM(units)(inputs)
#output_shape -> (batch_size, units) --> steps were discarded, only the last was returned
现在,keras LSTM图层不支持此功能。您必须创建自己的策略来增加步骤。有两种好的方法:
stateful=True
循环获取一步的输出并将其作为下一步的输入(需要output_features == input_features
)为了适应keras标准行为,我们需要逐步输入,因此,我们只需重复输入我们想要的长度:
outputs = RepeatVector(steps)(inputs) #where inputs is (batch,features)
outputs = LSTM(units,return_sequences=True)(outputs)
#output_shape -> (batch_size, steps, units)
现在出现了stateful=True
的一种可能用法(除了避免加载无法同时适合您计算机内存的数据)
有状态允许我们输入"部分"分阶段的序列。区别在于:
stateful=False
中,第二批包含全新序列,独立于第一批stateful=True
中,第二批继续第一批,扩展相同的序列。 这就像在窗口中划分序列一样,有两个主要区别:
stateful=True
会将这些窗口视为一个长序列在stateful=True
中,每个新批次都将被解释为继续上一批(直到您致电model.reset_states()
)。
输入示例,批处理1包含步骤1和2,批处理2包含步骤3到5:
BATCH 1 BATCH 2
[ Step1 Step2 | [ Step3 Step4 Step5
Tank A: [[Pa1,Ta1], [Pa2,Ta2], | [Pa3,Ta3], [Pa4,Ta4], [Pa5,Ta5]],
Tank B: [[Pb1,Tb1], [Pb2,Tb2], | [Pb3,Tb3], [Pb4,Tb4], [Pb5,Tb5]],
.... |
Tank N: [[Pn1,Tn1], [Pn2,Tn2], | [Pn3,Tn3], [Pn4,Tn4], [Pn5,Tn5]],
] ]
注意批次1和批次2中的储罐对齐!这就是我们需要shuffle=False
的原因(当然,除非我们只使用一个序列)。
您可以无限期地拥有任意数量的批次。 (要在每批中使用可变长度,请使用input_shape=(None,features)
。
对于我们这里的情况,我们每批只使用一步,因为我们希望得到一个输出步骤并使其成为输入。
请注意,图片中的行为不是由" stateful=True
。我们将在下面的手动循环中强制执行该行为。在此示例中,stateful=True
是"允许"我们停止序列,操纵我们想要的东西,并从我们停止的地方继续。
老实说,对于这种情况,重复方法可能是更好的选择。但是,由于我们正在研究stateful=True
,这是一个很好的例子。使用它的最好方法是下一个"多对多"情况下。
层:
outputs = LSTM(units=features,
stateful=True,
return_sequences=True, #just to keep a nice output shape even with length 1
input_shape=(None,features))(inputs)
#units = features because we want to use the outputs as inputs
#None because we want variable length
#output_shape -> (batch_size, steps, units)
现在,我们需要手动循环进行预测:
input_data = someDataWithShape((batch, 1, features))
#important, we're starting new sequences, not continuing old ones:
model.reset_states()
output_sequence = []
last_step = input_data
for i in steps_to_predict:
new_step = model.predict(last_step)
output_sequence.append(new_step)
last_step = new_step
#end of the sequences
model.reset_states()
现在,在这里,我们得到一个非常好的应用程序:给定输入序列,尝试预测其未来的未知步骤。
我们使用与"一对多"相同的方法。以上,区别在于:
图层(与上面相同):
outputs = LSTM(units=features,
stateful=True,
return_sequences=True,
input_shape=(None,features))(inputs)
#units = features because we want to use the outputs as inputs
#None because we want variable length
#output_shape -> (batch_size, steps, units)
培训强>
我们将训练我们的模型来预测序列的下一步:
totalSequences = someSequencesShaped((batch, steps, features))
#batch size is usually 1 in these cases (often you have only one Tank in the example)
X = totalSequences[:,:-1] #the entire known sequence, except the last step
Y = totalSequences[:,1:] #one step ahead of X
#loop for resetting states at the start/end of the sequences:
for epoch in range(epochs):
model.reset_states()
model.train_on_batch(X,Y)
<强>测算:强>
我们预测的第一阶段涉及&#34;调整州和#34;。这就是我们为什么要再次预测整个序列的原因,即使我们已经知道它的这一部分:
model.reset_states() #starting a new sequence
predicted = model.predict(totalSequences)
firstNewStep = predicted[:,-1:] #the last step of the predictions is the first future step
现在我们按照一对多的情况进入循环。但是不要在这里重置状态!。我们希望模型知道序列的哪一步(并且由于我们上面做出的预测,它在第一个新步骤知道它)
output_sequence = [firstNewStep]
last_step = firstNewStep
for i in steps_to_predict:
new_step = model.predict(last_step)
output_sequence.append(new_step)
last_step = new_step
#end of the sequences
model.reset_states()
这些方法用于这些答案和文件:
在上面的所有例子中,我展示了&#34;一层&#34;的行为。
当然,您可以将多个图层堆叠在一起,而不必按照相同的模式进行堆叠,并创建自己的模型。
出现的一个有趣的例子是&#34; autoencoder&#34;有一个&#34;多对一编码器&#34;然后是一对多的&#34;一对多&#34;解码器:
<强>编码器:强>
inputs = Input((steps,features))
#a few many to many layers:
outputs = LSTM(hidden1,return_sequences=True)(inputs)
outputs = LSTM(hidden2,return_sequences=True)(outputs)
#many to one layer:
outputs = LSTM(hidden3)(outputs)
encoder = Model(inputs,outputs)
<强>解码器:强>
使用&#34;重复&#34;方法;
inputs = Input((hidden3,))
#repeat to make one to many:
outputs = RepeatVector(steps)(inputs)
#a few many to many layers:
outputs = LSTM(hidden4,return_sequences=True)(outputs)
#last layer
outputs = LSTM(features,return_sequences=True)(outputs)
decoder = Model(inputs,outputs)
<强>自动编码器:强>
inputs = Input((steps,features))
outputs = encoder(inputs)
outputs = decoder(outputs)
autoencoder = Model(inputs,outputs)
使用fit(X,X)
如果您想了解有关如何在LSTM中计算步骤的详细信息,或有关上述stateful=True
个案的详细信息,请参阅此答案中的更多内容:Doubts regarding `Understanding Keras LSTMs`
答案 2 :(得分:0)
如果在最后一层RNN中有return_sequences,则不能使用简单的Dense层而是使用TimeDistributed。
以下是一段可能对其他人有帮助的示例代码。
words = keras.layers.Input(batch_shape =(None,self.maxSequenceLength),name =“input”)
# Build a matrix of size vocabularySize x EmbeddingDimension
# where each row corresponds to a "word embedding" vector.
# This layer will convert replace each word-id with a word-vector of size Embedding Dimension.
embeddings = keras.layers.embeddings.Embedding(self.vocabularySize, self.EmbeddingDimension,
name = "embeddings")(words)
# Pass the word-vectors to the LSTM layer.
# We are setting the hidden-state size to 512.
# The output will be batchSize x maxSequenceLength x hiddenStateSize
hiddenStates = keras.layers.GRU(512, return_sequences = True,
input_shape=(self.maxSequenceLength,
self.EmbeddingDimension),
name = "rnn")(embeddings)
hiddenStates2 = keras.layers.GRU(128, return_sequences = True,
input_shape=(self.maxSequenceLength, self.EmbeddingDimension),
name = "rnn2")(hiddenStates)
denseOutput = TimeDistributed(keras.layers.Dense(self.vocabularySize),
name = "linear")(hiddenStates2)
predictions = TimeDistributed(keras.layers.Activation("softmax"),
name = "softmax")(denseOutput)
# Build the computational graph by specifying the input, and output of the network.
model = keras.models.Model(input = words, output = predictions)
# model.compile(loss='kullback_leibler_divergence', \
model.compile(loss='sparse_categorical_crossentropy', \
optimizer = keras.optimizers.Adam(lr=0.009, \
beta_1=0.9,\
beta_2=0.999, \
epsilon=None, \
decay=0.01, \
amsgrad=False))
答案 3 :(得分:0)
检查一下,我已经在github https://github.com/MohammadFneish7/Keras_LSTM_Diagram上的一个简单易用的图中创建了完整的Keras LSTM解释