RNN与LSTM
前因后果
最近在搞论文,做的是基于rPPG的情感识别。
其中用到的网络中,出现了我之前经常听室友说过,但我从来没怎么去了解的Encoder与Decoder。
我的第一反应是:难道不是解析HTTP的编码器与解码器?
并且这个网络里面,使用到了Encoder-Decoder的思想, 我看不懂,但我大受震撼。
为了弄清楚网络,我就只能去网上冲浪,看看有没有相关的博客或者视频,讲这个结构的。
那么回到开始,什么是rPPG?
rPPG简介
rPPG,全称remote photoplethysmograph,即远程光电容积脉搏波。
PPG信号全名叫做光电容积脉搏波,也是一种信号,类似于ECG信号,一般通过手指进行测量,通过对该信号进行处理也可以提取出心率值;其原理如下图,由于人的心脏跳动,导致血管中血容量发生变化,其对于光的反射与透射情况会发生改变,这时通过一个设备来接受反射的光线,可以测量出光线强度的变化,一次推导出脉搏。
rPPG则是后来衍生出的名称,是通过远程测量的一种信号,即基于视频进行测量得到的信号,通过该信号可以计算出心率。由此可以看出,ECG,PPG,rPPG都是一种可以提取心率的信号,不同的是它们的测量方式不一样,需要的设备不一样。
所以简而言之,我的这个方向,仍然是通过计算机视觉来解决问题,这样可以实现非接触式的测量,还是很有发展前景的。
RNN
简介
提到Encoder与Decoder,就不得不先说说RNN。
RNN全称为Recurrent Neural Networks,翻译为循环神经网络。
人类在思考时,每一秒的思考,都不会是完全独立的。人每一时刻的思维与思考,或多或少都会和以前的信息相关联。
当你读一篇文章,或者一个句子的时候,对于当前词汇的理解,都是建立在对于之前词汇的理解之上的。
比如一个句子:我爱打篮球
当你读到 篮球 时,结合了上一个词 打,你会理解到这是一个组合词,表达的意思是 打篮球 这么一个动作。同时结合前面 我 以及 爱 ,你会解读出 我 喜欢 打篮球 这个状态。
所以你在理解句子时,不会把一切都扔掉,重新开始思考,你的思考是有持续性的。
而传统的神经网络做不到这些,这是神经网络的一个缺点。
例如,假设你想对电影中每一点发生的事件进行分类,传统的神经网络很难通过其对电影中先前事件的推理,来推理后续事件。
结构
所以就有人提出了RNN的概念。下面是RNN的基本网络结构:
可以很清楚的看到,RNN中包含了循环。每一个 t 时间输入的 Xt ,其送入了 A 中,同时其还包括了 t-1 时刻 A 的输出。
将这个图平坦铺开,可能会更好理解一些:
这种链状性质表明,循环神经网络与序列和列表密切相关,这种结构决定了循环神经网络在处理序列型数据时,有天然的优势。
但是读者看到这个结构,应该也能想到一个问题,那就是我从最开始时刻送入的 X1 数据,会一直延续到 Xt ,也就是 Long-Term。
Long-Term的缺点
RNN的一个优点是,它们可能能够将以前的信息连接到当前任务,例如,使用以前的视频帧可能有助于理解当前帧。如果RNN能够做到这一点,它们将非常有用。但RNN真的可以吗?不好说。
有的时候,我们在理解一个句子的时候,实际上只需要携带前面较少的信息,就可以很好地进行推理。
而上面RNN的结构,就会导致网络的记忆能力过于 强大 (虽然越早进入网络的输入 X ,在后续的 A 中占比可能会越来越小),我们在做推断的时候,可能根本不需要那么早的信息。甚至这些信息还会对网络的推理产生负面的影响。
但是也不能说,一定要把之前的信息全部丢掉。
理论上,RNN完全能够处理这种 Long-Term ,一个人可以仔细地为他们挑选参数来解决这种形式的玩具问题。遗憾的是,在实践中,RNN似乎无法学习它们。
既然都是人工智能深度学习了,那有没有一种网络,可以很 智能 地记忆呢?😏
LSTM
感谢先驱 Hochreiter & Schmidhuber 于1997(我还没出生)提出了LSTM,一个非常经典的、特殊的RNN,并在后续工作中得到了许多人的改进和推广。
经典LSTM
结构如下:
经典的LSTM有三个门(Gate),分别为遗忘门(Forget Gate)、输入门(Input Gate)以及输出门(Output Gate)
遗忘门(Forget Gate)
遗忘门的公式为:
这里将 h(t-1) 与 Xt 拼接后,与 Wf 矩阵相乘,并且加上了 bf 偏执矩阵,最后通过 Sigmoid 函数来激活,最后输出 0 或者 1 ,该输出与 C(t-1) 相乘,决定了 C(t-1) 是否保留。
f(t) 由 t-1 时刻的 h(t-1) 以及 t 时刻的 Xt 计算出来,并且只有 0 和 1,分别代表了保留与遗忘,就像一个门电路一样,所以将其称为了 Forget Gate
输入门
输入门的公式为:
这里的 it 就是 Input Gate,决定了网络是否保存当前的输入
最终的Ct公式为:
输出门
输出门也很好理解了,就是决定网络是否要将当前计算出来的结果(其实也就是Ct)输出。其公式为:
总结
其实花里胡哨的一堆门,其核心思想就是通过当前时刻的输入 Xt 以及上一时刻输入的 h(t-1) 来计算:
- 是否要把上一时刻的输出保留,通俗点说就是是否要保存记忆
- 是否要把当前时刻的输入,加入到网络中,通俗点说就是记忆里是否要加入新的数据
- 是否要把当前时刻的结果,输出,通俗点就是是否要把记忆力的数据,输出出去
说了这么多,那么和encoder与decoder啥关系呢?
encoder与decoder的概念
其实encoder与decoder这样一个结构,只是个概念,或者说思想。
E-D大多数时候还是用于NLP相关的场景中,尤其是sequence-to-sequence,也就是输入序列,输出序列。
并且sequence2sequence也可以解决输入序列与输出序列在形状与大小上不同的问题。
比如一句话:我是中国人
在分词的时候,会将其分为
- 我
- 是
- 中国
- 人
但是将其翻译后,应该为 I am chinese,其分词为:
- I
- am
- chinese
可以很明显的看出来,输入的序列长度为4,输出的序列为3。
所以就使用encoder将输入序列编码(encode)为固定长度的中间信息,最后使用decoder将中间信息解码(decode)为输出。
论文中的encoder与decoder
我在复现 PhysNet 论文时,使用作者提供的代码。在阅读其代码的时候,我一直很迷惑作者在论文中提出的E-D,到底在哪里呢?
而且在看了RNN以及encoder-decoder的文章以及视频后,更加困惑着,网络结构根本没有这么复杂啊!
直到昨天,在闲暇之余,突然想到encoder-decoder只是一种思想,没有规定说一定要使用RNN以及LSTM。
我重新看了看代码,以及作者的一部分注释,我才明白了E-D思想是怎么体现的。
1 |
|
这里用到了 nn.ConvTranspose3d 这个转置卷积函数,简要来说,是将卷积后大小缩小的矩阵,通过转置卷积,将其恢复到卷积前的大小(虽然数据已经变了)
1 |
|
在上述代码中,x的形状经过了多层的卷积操作,大小变为了 [64, T/4, 8, 8],而最开始输入的大小为 [3, T, 128, 128],我们想要将其第二个维度的大小,从T/4变回T,就可以使用 self.upsample 中的转置卷积操作。
其encode与decode分别是:
- encode:将原信号进行卷积以及时域最大池化,所以时间维度的大小从T不断地变为T/4
- decode:为了将时间维度大小恢复,使用了两次转置卷积,将时间维度大小恢复为T
虽然有点抽象,但是也大概理解了E-D的思路。
至于为啥这个操作有用,我目前还没领悟出来,还得多做实验。
参考与鸣谢
- 李宏毅老师的RNN讲解视频:李宏毅机器学习-RNN网络(中英文)_哔哩哔哩_bilibili
- 写的非常好的一个博客,但是是生肉:Understanding LSTM Networks – colah’s blog
- 转置矩阵讲解1:转置卷积(Transpose Convolution) - 知乎 (zhihu.com)
- 转置矩阵讲解2:转置卷积(反卷积) - 知乎 (zhihu.com)
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!