Keras在GitHub上的一句话简介是“Deep Learning for humans”(给人用的深度学习工具),确实,基于Tensorflow的Keras相对前者来说,能够更加方便快捷地构建神经网络,使非计算机专业的使用者能够将更多精力放在研究问题本身,而不是构建神经网络模型的过程。
在Keras的循环神经网络(RNN)中,有两个参数return_state,return_sequences
对于一般人来说容易混淆或者不清楚具体的用途用法,在经过一段时间的搜集与测试后,我把我的理解写在这篇博客上。
希望读者读完这篇博客后,可以知道:
要具体理解这两个参数的意思,我们首先需要了解一下RNN/LSTM的简单背景,这里只做简单介绍,具体细节还请参考具体的教科书或者论文。
最基本的循环神经网络RNN会遭遇“梯度消失”(vanishing gradients)的问题,因此很难捕捉长期的时间相关关系。
而Long Short-Term Memory(LSTM)能够解决这一问题,因为在每一个RNN单元中引入了“门”(gate)这个概念,使得模型能够通过反向传播(backpropagation)成功训练以表面梯度消失问题。
在上图中可以看到对每一个RNN单元,有对应的输入数据X
上面的c
Return sequences返回的是隐藏状态输出( the hidden state output)a
但是有的时候我们需要整个序列的输出,这时就需要把return_sequences设置为True。
下面用一个简单的例子来说明。
假设我们只有一个输入数据,这个数据有3个时间步长,最后的输出的也是一维数据,比如:
t1 = 0.1
t2 = 0.2
t3 = 0.3
所以我们的问题就可以简化成:输入3个连续的数字,得到一个数字。
完整的代码如下:
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
#shape=(3,1)代表输入数据的维度,问题是3个输入的数字,一个输出的数字,所以是(3,1)
inputs1 = Input(shape=(3, 1))
lstm1 = LSTM(1)(inputs1)
model = Model(inputs=inputs1, outputs=lstm1)
# define input data
#输入数据维度也是(3,1),因为只有一个,所以整体的data就是(1,3,1)
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))
最后结果
[[-0.0953151]]
以上是默认 return_sequences = False__的情况,如果设置__return_sequences = True,比较一下结果:
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1 = LSTM(1, return_sequences=True)(inputs1)
model = Model(inputs=inputs1, outputs=lstm1)
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))
得到的输出如下
[[[-0.02243521]
[-0.06210149]
[-0.11457888]]]
3个时间步长,因此得到的是3个隐藏状态输出。
需要注意的是,下面两种主要情况必须设置 return_sequences = True:
每一个LSTM单元或层的输出叫隐藏状态输出( the hidden state output),这个名字很容易因此歧义,因为每一个LSTM单元状态( cell state)反而是其内部的状态,不会被输出给下一个单元。一般来说,不需要去管这些单元状态,但是在一些复杂的模型中,后面LSTM层的单元状态初始化需要依赖于前面LSTM层中最后一个单元状态的值。如encoder-decoder模型。
还是举一个跟之前类似的例子:
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
#state_h, state_c分别代表隐藏层输出,单元状态输出
lstm1, state_h, state_c = LSTM(1, return_state=True)(inputs1)
model = Model(inputs=inputs1, outputs=[lstm1, state_h, state_c])
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))
运行上述程序会返回3个矩阵:
[array([[ 0.10951342]], dtype=float32),
array([[ 0.10951342]], dtype=float32),
array([[ 0.24143776]], dtype=float32)]
这两个参数可以同时应用:
from keras.models import Model
from keras.layers import Input
from keras.layers import LSTM
from numpy import array
# define model
inputs1 = Input(shape=(3, 1))
lstm1, state_h, state_c = LSTM(1, return_sequences=True, return_state=True)(inputs1)
model = Model(inputs=inputs1, outputs=[lstm1, state_h, state_c])
# define input data
data = array([0.1, 0.2, 0.3]).reshape((1,3,1))
# make and show prediction
print(model.predict(data))
运行上述代码后,打印的结果分为三部分:每一个时间步长的隐藏层状态输出,最后一个时间步长的隐藏层状态输出,最后一个时间步长的单元状态输出。
[array([[[-0.02145359],
[-0.0540871 ],
[-0.09228823]]], dtype=float32),
array([[-0.09228823]], dtype=float32),
array([[-0.19803026]], dtype=float32)]
可以发现,第一个向量的第三个数字-0.09228823,正式第二个向量的数字,因为他们都是最后一个时间步长的隐藏层状态输出。
这篇博客总结了Keras 中LSTM网络中return sequences 与 return states的区别与用法:
如果还有问题或者发现文中的错误,欢迎留言交流!
参考资料:
[1]: https://www.dlology.com/blog/how-to-use-return_state-or-return_sequences-in-keras/
[2]: https://machinelearningmastery.com/return-sequences-and-return-states-for-lstms-in-keras/
[3]: https://keras.io/layers/recurrent/#lstm