Keras中RNN LSTM循环神经网络中 Return Sequences 与 Return States 的区别

内容概览

  • RNN/LSTM 简介
  • Return sequences
  • Return States
  • Return States + Sequences
  • 总结

Keras在GitHub上的一句话简介是“Deep Learning for humans”(给人用的深度学习工具),确实,基于Tensorflow的Keras相对前者来说,能够更加方便快捷地构建神经网络,使非计算机专业的使用者能够将更多精力放在研究问题本身,而不是构建神经网络模型的过程。

在Keras的循环神经网络(RNN)中,有两个参数return_state,return_sequences

对于一般人来说容易混淆或者不清楚具体的用途用法,在经过一段时间的搜集与测试后,我把我的理解写在这篇博客上。

希望读者读完这篇博客后,可以知道:

  1. return_sequences 返回的是每一个输入时间步长(each input time step)的隐藏状态输出( the hidden state output);
  2. return_state 返回的是最后一个时间步长(the last input time step)的隐藏状态输出( the hidden state output)以及单元状态( cell state);
  3. return_sequences, return_state 两者可以同时使用。

要具体理解这两个参数的意思,我们首先需要了解一下RNN/LSTM的简单背景,这里只做简单介绍,具体细节还请参考具体的教科书或者论文。

RNN/LSTM 简介

最基本的循环神经网络RNN会遭遇“梯度消失”(vanishing gradients)的问题,因此很难捕捉长期的时间相关关系。
而Long Short-Term Memory(LSTM)能够解决这一问题,因为在每一个RNN单元中引入了“门”(gate)这个概念,使得模型能够通过反向传播(backpropagation)成功训练以表面梯度消失问题。
Keras中RNN LSTM循环神经网络中 Return Sequences 与 Return States 的区别_第1张图片
在上图中可以看到对每一个RNN单元,有对应的输入数据X (t = 1,2,3…),以及上一个单元的输出a ,对每个单元,有隐藏状态输出( the hidden state output)以及单元状态( cell state)两个参数,之前提到的a 就是隐藏状态输出,前一个单元的隐藏状态输出又会作为后一个单元的输入。对于每一个单元本身的单元状态( cell state),不同的RNN算法也有对应的计算方法。比如下图的GRU与LSTM,对于GRU, a = c ,而LSTM算法中,两者是不同的。
Keras中RNN LSTM循环神经网络中 Return Sequences 与 Return States 的区别_第2张图片
上面的c 的结果就是所谓的单元状态( cell state)。不用担心有点晕,其实只需要记住两点:

  1. a 对应隐藏状态输出( the hidden state output)
  2. c 对应单元状态( cell state)
    上面俩对应的就是之前提到的return_sequences, return_state这两个参数的设置。

Return sequences

Return sequences返回的是隐藏状态输出( the hidden state output)a,默认设置为False,这意味着Keras只会输出最后一个隐藏层的结果,这个结果可以认为是整段输入序列的简单代表,有时候这正是我们想要的结果,比如一些特定的分类任务(如文本情感分析)或者回归任务(预测明天的股价)。
但是有的时候我们需要整个序列的输出,这时就需要把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

  1. 如果在模型中堆叠了多个LSTM层,那么前面的LSTM必须设置 return_sequences = True,这样才能使后面的LSTM的输入数据与最原始的输入数据有一样的维度(比如这个例子中是3)。
  2. 想得到每一个时间步长的识别结果,比如识别一个视频内每一帧图片的结果。

Return States

每一个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个矩阵:

  1. 最后一个时间步长的LSTM隐藏层状态输出( the hidden state output);
  2. 最后一个时间步长的LSTM隐藏层状态输出( the hidden state output)(同上);
  3. 最后一个时间步长的LSTM单元状态( cell state)
[array([[ 0.10951342]], dtype=float32),
 array([[ 0.10951342]], dtype=float32),
 array([[ 0.24143776]], dtype=float32)]

Return States + Sequences

这两个参数可以同时应用:

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. return_sequences 返回每一个时间步长(each input time step)的隐藏层状态(the hidden state);
  2. return_state 返回最后一个时间步长(the last input time step)的隐藏状态(the hidden state)以及单元状态( cell state);
  3. 上述两者可以同时使用。

如果还有问题或者发现文中的错误,欢迎留言交流!


参考资料
[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

你可能感兴趣的:(深度学习,Keras,LSTM)