LSTM
1、简介
LSTM是一种RNN模型, 是对Simple RNN的改进, LSTM可以避免梯度消失的问题, 可以有更长的记忆。原论文 Long Short-term Memory (researchgate.net)](https://www.researchgate.net/publication/13853244_Long_Short-term_Memory))是1997年发表的。下图是LSTM原论文中的截取的图。
LSTM也是一种循环神经网络, 原理跟Simple RNN差不多。
每当读取一个新的输入x就会更新状态h, lstm的结构比simple RNN要复杂很多。Simple RNN只有一个参数矩阵, LSTM有4个参数矩阵, 下面看一下LSTM内部的具体结构。
2、LSTM结构
LSTM最重要的设计是这个传输带, 即为向量C。过去的信息通过传输带送到下一个时刻,不会发生太大的变化, LSTM就是通过传输传输带来避免梯度消失。
LSTM中有很多gate可以有选择的让信息通过, 先来看一下forget gate遗忘门。遗忘门由sigmoid function和Elementwise multiplication两部分组成。输入sigmoid是一个向量a, sigmoid作用到向量a的每个元素上, 把每个元素都压到0和1之间。sigmoid处理后的向量维度与输入sigmoid的向量维度相同。
计算出f之后需要计算传输带向量C和遗忘门向量f的elementwise multiplication。elementwise multiplication是这样计算的, 举个例子, c和f都是4维的向量, 把它们的每个元素分别乘起来就行, 所以elementwise multiplication的结果也是一个四维的向量。
遗忘门有选择的让传输带C的值通过, 假如f的一个元素都是零, 那么C对应的元素就不能通过, 对应的输出也是零。假如f的一个元素是1, 那么C对应的元素就全部通过, 对应的输出就是C本身。可以这里理解: f向量中元素的值可以看做向量C中对应元素的权重。
遗忘门f具体是怎么计算出来的, 看下面的结构图, ft是上一个状态ht-1和当前输入xt的函数。把状态ht-1与输入xt做concatination得到更高的向量, 然后计算矩阵wf与这个向量的乘积得到一个向量,再用sigmoid函数得到向量ft。向量ft的每一个元素都介于0到1之间, 遗忘门有个参数矩阵wf需要经过反向传播从训练数据中学习。
上面是遗忘门forget gate, 下面解释一下input gate输入门。输入门it依赖于旧的向量ht-1和新的输入xt。输入门it的计算与遗忘门很类似, 把旧的状态ht-1与输入xt做concatination, 得到更高维度的向量。然后计算矩阵Wi与这个向量的乘积得到一个向量, 最后再用sigmoid函数得到向量it。it的每一个元素都介于0到1之间, 输入门也有自己的参数矩阵wi, wi也需要通过反向传播从训练数据中学习得到。
还要计算new value C~t, C~t是个向量, 计算跟遗忘门和输入门都很像, 也是把旧的状态ht-1与新的状态xt做concatination, 再乘到参数矩阵Wc上, 区别在于激活函数不是sigmoid,而是tanh。所以计算得到的Ct向量都介于-1到1之间。计算new value C~t也需要一个单独的参数矩阵记作Wc。
上面已经计算出了遗忘门ft、new value C~t以及输入门it,我们还知道传输带旧的值Ct-1, 现在就可以更新传输带C了。用遗忘门ft和传输带旧的值Ct-1计算elementwise multiplication。 遗忘门ft和传输带旧的值Ct-1的维度是相同的向量,计算的乘积也是一个向量, 遗忘门ft可选择性的遗忘Ct-1中的一些元素。如果ft中的一个元素是0,那么Ct-1对应的元素也是0, 也就是Ct-1的元素选择性遗忘掉了。
上面选择性的遗忘掉Ct-1中的一些元素, 现在需要往传输带上添加新的信息, 计算输入门it和新的值C~t的elementwise multiplication。输入门it和新的值C~t都是维度相同的向量。它们的乘积也是维度相同的向量, 把乘积加到传输带上就行。 这样就完成了对传输带的一轮更新。用遗忘门删除了传输带上的一些信息, 然后加入新的信息, 得到传输到新的值Ct。
上面已经更新完传送带C了, 最后一步是计算LSTM的输出,也就是状态向量ht。ht是这么计算的, 首先计算output gate输出门Ot, 输出门Ot跟前面的遗忘门的计算基本一致。输入是旧的状态ht-1和当前输入xt, 通过concatination拼接得到更高维的向量。然后计算矩阵Wo与这个向量的乘积得到一个向量, 最后再利用sigmoid函数得到向量Ot。Ot的每个元素都介于0到1之间, 输出门也有自己的参数矩阵Wo, Wo也需要从训练数据中学习。
现在计算状态向量ht, 对传输带Ct的每个元素求tanh, 把元素压缩到-1和1之间, 然后求这两个元素的elementwise multiplication。红色向量是刚刚求解出来的输出门Ot, 将其与传输带输出的Ct做tanh后的结果相乘就得到了状态向量ht。
下面的结构图中显示,ht有两份copy, 一份copy传输到了下一步, 另外一份copy成了lstm的输出。到第t步位置,一共有7个向量输入到了LSTM, 可以认为所有这些x向量的信息都积累在状态ht里面。
3、LSTM的参数量
LSTM有遗忘门,输入门, new value以及输出门4个模块组成。这四个模块都有各自的参数矩阵W, 所以一共有4个参数矩阵。矩阵的行数是h的维度, 列数是h的维度加上x的维度。所以LSTM参数的数量是4乘以h的维度再乘以h的维度加上x的维度。
4、LSTM代码实现
LSTM的结构虽然复杂, 但是用keras实现起来非常简单, 跟simple RNN的实现几乎一样。用LSTM判断电影评论是正面还是负面, 跟simple RNN一样。让LSTM只输出最后一个状态向量ht, ht就是从一段500个词的电影评论中提取的特征向量, 然后输入线性分类器来判断评论是正面的还是负面的。
1 | from tensorflow.keras.layers import LSTM, Embedding, Dense |
打印的模型概要为:
参数量8320是这样计算的,每个参数矩阵h的维度是32, 乘以h的维度32 再 加上x的维度32。keras默认使用intercept, 所有参数里面还有32个维度的向量, 一个矩阵和一个向量加起来一共有2080个参数。LSTM一共有4个参数矩阵和4个intercept的向量, 所以参数的数量等于2080×4, 一共8320个参数。
8320 = 2080 × 4, 2080 = 32×(32 + 32)+ 32
dropout也可以用在LSTM层上,具体的方法比较复杂。
总结, LSTM与simple RNN的区别就是用了一条传输带让过去的信息很容易传输到下一个时刻, 这样就有了更长的记忆, LSTM的表现总是比simple RNN更好。