深入理解LSTM,全网最详细讲解
深入理解LSTM,全网最详细讲解
LSTM(长短期记忆网络)是深度学习中处理序列数据的重要模型,相比传统的RNN(循环神经网络),LSTM通过引入遗忘门、输入门和输出门等结构,有效解决了长期依赖问题。本文将深入解析LSTM的工作原理,帮助读者全面理解这一重要模型。
1. LSTM与RNN的区别
1.1 RNN 网络结构
图 1(上)为逻辑结构图,(下)为实际细节图
可以看到,RNN的结构比较简单,值得关注的点就是相邻两个时刻的神经细胞单元会相互共享隐藏层的信息。但是RNN很容易在时间序列过长的时候产生梯度爆炸和梯度消失的问题。
大家如果想详细了解RNN的相关结构解释和计算,可以参考我的上一篇文章RNN网络详解,在【RNN网络详解】一文中,我详细分析了RNN分享权重的部分和理解方式,希望能够对您有所帮助。
1.2 LSTM网络的结构
LSTM网络的结构相比普通的RNN结构来说较为复杂,尤其是针对于记忆的长短、以及应该遗忘何种信息?记住何种信息?的问题通过:遗忘门、输入门、输出门等结构来较为完美地解决。
图 2 LSTM 神经单元内部的三个“门”结构整体图
首先做一个形象化的理解,每个LSTM神经单元都会经过一个C t − 1 C_{t-1}Ct−1 →C t C_tCt 的过程,而我们可以形象地把C t C_tCt 理解成当前神经单元的【记忆内容】,把C t − 1 C_{t-1}Ct−1 认为是前一个时刻神经单元的【记忆内容】,上一个时刻的【记忆内容】会在这一个时刻进行更新和删除,而更新和删除的过程就是 LSTM 比 RNN 先进的地方。
【遗忘门】
图 3 LSTM 神经单元“遗忘门” 部分
首先将上一时刻(t − 1 t-1t−1时刻)的**隐藏状态的信息S t − 1 S_{t-1}St−1 **与本时刻(t tt时刻)的数据共同输入Sigmoid 函数,输出的值介于0 ~ 1之间,代表该不该忘记,越接近 0 表示越应该忘记,越接近1 表示越应该记住。最后得到的这个值会与前一时刻的记忆C t − 1 C_{t-1}Ct−1 做乘积运算来限制前面的记忆对后面的影响。
所以,我们可以形象地将f t f_tft 称为:【过去记忆重要程度的衡量因子】例如:如果sigmoid 函数输出的结果是:0,就代表当前的上一时刻的隐藏层和这一时刻的输入组成的综合结果是没有任何价值的,那么这个 0 与C t − 1 C_{t-1}Ct−1 相乘,就会导致前面的信息被遗忘。
【可能遇到的问题】
//为什么要把本时刻(t时刻)的数据也经过遗忘门呢?为什么不仅仅把上一时刻的信息做“重要性”判断即可呢?//
答:因为本时刻输入的信息可能也并没有记住的必要,可能是一些无关紧要的信息,所以要把本时刻的信息x t x_txt 和上一时刻的隐藏层信息h t − 1 h_{t-1}ht−1 整合之后再判断,这两个信息整合起来再经过遗忘门来判断一下是否有长期记忆的必要。当然,本时刻的信息不会就这么简单地就消失,它也会输入到 “输入门” 进行判断,也就是说,本时刻的信息x t x_txt 依然有进入下一个时刻细胞单元的机会,并且被作为后面的细胞单元的判断和估计“材料”。
遗忘门的运算公式:
f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t = \sigma (W_f · [h_{t-1, x_t}]+b_f)ft =σ(Wf ⋅[ht−1,xt ]+bf )
公式的意思就是上面文字表述的部分:
先将t tt时刻的输入X = [ x 1 , . . . , x t ] X = [x_1,...,x_t]X=[x1 ,...,xt ]与上一个隐藏层的数据h t − 1 h_{t-1}ht−1 进行结合(也就是**<图1>**中的S SS),然后再用W f W_fWf 矩阵将其调整成与t tt时刻隐藏层相同的维度,然后加一个b f b_fbf 偏置之后经过s i g m o i d sigmoidsigmoid函数进行0~1之间的分类。
【输入门】
图 4 LSTM 神经单元“输入门” 部分
小伙伴们有没有发现,咱们这个“输入门”有两条线路组成:
左边的那条经过sigmoid(σ \sigmaσ)函数,美其名曰叫做i t i_tit ,但是不知道细心的你是否发现了他与 “遗忘门” 的结构几乎是一样的,那么你想这是为什么呢? 因为它同样只需要产生一个 0~1 的结果就好了,因为后面要与C t ~ \tilde{C_t}Ct ~ 作乘积,做个假设,假如sigmoid结果出来是0, 那无论C t ~ \tilde{C_t}Ct ~ 是什么,都没有输进C t {C_t}Ct 的必要了,所以用乘积的方式来代表输入当前数据的重要程度是很聪明的一种做法。所以我们把左边这条线称作为【输入的重要性因子】
右边那条线和左边那条线输入的数据都是一样的,包括“遗忘门”输入的数据都是一样的,都是[ h t − 1 ] + x t [h_{t-1}] + x_t[ht−1 ]+xt 。不同的是,右边这条线经过的激活函数不是 sigmoid 而是tanh,让我们先来看一下 sigmoid 函数和 tanh 的不同:
① sigmoid:
图 5 sigmoid 函数可视化图
② tanh:
图 6 tanh 函数可视化图
很清楚的发现,sigmoid函数的分布范围在 0 ~ 1,而 tanh 的分布范围是沿着 y 轴对称,所以 tanh 起的作用是压缩输入tanh函数的数值,使其分布在 -1 ~ +1 以调节网络,有类似于数据中心化的效果,使得其收敛速度要比sigmoid快;所以一般再隐藏层使用 tanh 而在输出层使用 sigmoid ;最后与左边处于 0~1 的重要性衡量因子相乘,结果存入C t C_tCt 。
输入门的运算公式:
i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) i_t = \sigma(W_i·[h_{t-1},x_t] + b_i)it =σ(Wi ⋅[ht−1 ,xt ]+bi )
C t ~ = t a n h ( W C ⋅ [ h t − 1 , x t ] + b C ) \tilde{C_t}=tanh(W_C·[h_{t-1},x_t]+b_C)Ct ~ =tanh(WC ⋅[ht−1 ,xt ]+bC )
C t = f t ∗ C t − 1 + i t ∗ C t ~ C_t=f_tC_{t-1}+i_t\tilde{C_t}Ct =ft ∗Ct−1 +it ∗Ct ~
图 7 经过遗忘门和输入门的数据如何删减和更新 “记忆 ”
“遗忘门”通过【过去记忆重要程度的衡量因子】与过去的记忆C t − 1 C_{t-1}Ct−1 做运算,起到“截断和筛选过去记忆”的作用,而【输入的重要性因子】与 “经过tanh函数调整过后的综合输入”做运算然后添加到C t − 1 C_{t-1}Ct−1 中来“扩展记忆的总容量”,使得记忆可以不断的被更新,虽然因为输入来源是(前面的隐藏内容h t − 1 h_{t-1}ht−1 和当前输入x t x_txt )综合的,可能导致一些原来已经有的记忆又被增加和更新了一遍,但是这个不会影响最后的结果,也是合理的。
【输出门】
图 8 输出门结构
如**<图 8>**所示,图中红色的圆圈部分其实已经形成了“新的记忆”C t C_tCt ,C t C_tCt 不做任何处理,直接输出到下一个单元作为下一个单元的“记忆”。但是,可以很明显的看到,h t h_tht 与C t C_tCt 不同,其要输出到下一个LSTM神经细胞单元需要再进行两个步骤:
① 经过t a n h tanhtanh函数进行调整
② 与上一个时刻的隐藏状态与本时刻输入的综合数据做乘积运算
图中所示的O t O_tOt 还是一个介于0~1的值,由h t − 1 h_{t-1}ht−1 和x t x_txt 经过sigmoid 函数算出来的、用来衡量即将要输出的C t C_tCt 有多少输出的价值,因为毕竟这个C t C_tCt 说是根据h t − 1 h_{t-1}ht−1 和x t x_txt 算出来的,所以同样由这两个因素来决定到底输出多少信息到本神经单元之外。
1.3 总结
图 9 “遗忘门 ”,“输入门 ”,“输出门 ”的共同特点
无论是“ 遗忘门 ”,“ 输入门 ”,“ 输出门 ”,我发现(细心的你可能也发现了),他们都被一个0~1之间的值所决定,这个值与一组数据做乘积,来显示这个数据的重要性。而这个值都是由h t − 1 h_{t-1}ht−1 和x t x_txt 经过 sigmoid 函数而得出来的,他们在不同的位置,衡量的却都是 “重要性”,更好理解的说法是:他们都衡量当前这个数据往后传递的必要性(重要性):
在遗忘门中,它决定了,C t − 1 C_{t-1}Ct−1 要不要被忘掉
在输入门中,它决定了,要不要把C ~ i \tilde C_{i}C~i 加入到记忆中来更新记忆
在输出门中,它决定了,这个更新的记忆要不要或者有多重要来输入到下一个隐藏层。
以上分析都是个人的想法和理解,如果发现有逻辑上的错误和问题,非常开心能和您一起讨论,谢谢!!