• RNN/LSTM学习记录


    一.RNN

    什么是循环神经网络:

    循环神经网络,从名字上理解“循环”,即为构成一个往复的结构,它有着这样的特点,对时序特征的数据十分敏感,能够挖掘出数据中的书序信息以及语义信息

    什么是序列特性呢,就是符合时间顺序,或者其他顺序就叫做序列特性。举个例子就是

    • 拿人类的某句话来说,也就是人类的自然语言,是不是符合某个逻辑或规则的字词拼凑排列起来的,这就是符合序列特性。
    • 语音,我们发出的声音,每一帧每一帧的衔接起来,才凑成了我们听到的话,这也具有序列特性、
    • 股票,随着时间的推移,会产生具有顺序的一系列数字,这些数字也是具有序列特性。

    为什么要发明循环神经网络:

    我们先来看一个NLP很常见的问题,命名实体识别,举个例子,现在有两句话:

    第一句话:I like eating apple!(我喜欢吃苹果!)

    第二句话:The Apple is a great company!(苹果真是一家很棒的公司!)

    现在的任务是要给apple打Label,我们都知道第一个apple是一种水果,第二个apple是苹果公司,假设我们现在有大量的已经标记好的数据以供训练模型,当我们使用全连接的神经网络时,我们做法是把apple这个单词的特征向量输入到我们的模型中(如下图),在输出结果时,让我们的label里,正确的label概率最大,来训练模型,但我们的语料库中,有的apple的label是水果,有的label是公司,这将导致,模型在训练的过程中,预测的准确程度,取决于训练集中哪个label多一些,这样的模型对于我们来说完全没有作用。问题就出在了我们没有结合上下文去训练模型,而是单独的在训练apple这个单词的label,这也是全连接神经网络模型所不能做到的,于是就有了我们的循环神经网络。

    循环神经网络的结构及原理:

    上图就是RNN的结构,我第一次看到这图的第一反应是,不是说好的循环神经网络么,起码得是神经网络啊,神经网络不是有很多球球么,也就是神经元,这RNN咋就这几个球球,不科学啊,看不懂啊!!!!随着慢慢的了解RNN,才发现这图看着是真的清楚,因为RNN的特殊性,如果展开画成那种很多神经元的神经网络,会很麻烦。

    首先不要管右边的W,只看X,U,S,V,O,这幅图就变成了,如下

     

    等等,这图看着有点眼熟啊,这不就是全连接神经网络结构吗?对,没错,不看W的话,上面那幅图展开就是全连接神经网络,其中X是一个向量,也就是某个字或词的特征向量,作为输入层,如上图也就是3维向量,U是输入层到隐藏层的参数矩阵,在上图中其维度就是3X4,S是隐藏层的向量,如上图维度就是4,V是隐藏层到输出层的参数矩阵,在上图中就是4X2,O是输出层的向量,在上图中维度为2。有没有一种顿时豁然开朗的感觉,正是因为我当初在学习的时候,可能大家都觉得这个问题比较小,所以没人讲,我一直搞不清楚那些神经元去哪了。。所以我觉得讲出来,让一些跟我一样的小白可以更好的理解。

    弄懂了RNN结构的左边,那么右边这个W到底是什么啊?把上面那幅图打开之后,是这样的:

     等等,这又是什么??别慌,很容易看,举个例子,有一句话是,I love you,那么在利用RNN做一些事情时,比如命名实体识别,上图中的 Xt−1 代表的就是I这个单词的向量,X代表的是love这个单词的向量, Xt+1 代表的是you这个单词的向量,以此类推,我们注意到,上图展开后,W一直没有变,W其实是每个时间点之间的权重矩阵,我们注意到,RNN之所以可以解决序列问题,是因为它可以记住每一时刻的信息,每一时刻的隐藏层不仅由该时刻的输入层决定,还由上一时刻的隐藏层决定,公式如下,其中Qt 代表t时刻的输出, St 代表t时刻的隐藏层的值:

     值得注意的一点是,在整个训练过程中,每一时刻所用的都是同样的W。

     举个例子,方便理解

    假设现在我们已经训练好了一个RNN,如图,我们假设每个单词的特征向量是二维的,也就是输入层的维度是二维,且隐藏层也假设是二维,输出也假设是二维,所有权重的值都为1且没有偏差且所有激活函数都是线性函数,现在输入一个序列,到该模型中,我们来一步步求解出输出序列:

     

    你可能会好奇W去哪了?W在实际的计算中,在图像中表示非常困难 ,所以我们可以想象上一时刻的隐藏层的值是被存起来,等下一时刻的隐藏层进来时,上一时刻的隐藏层的值通过与权重相乘,两者相加便得到了下一时刻真正的隐藏层,如图 a1 , a2 可以看做每一时刻存下来的值,当然初始时a1 , a2是没有存值的,因此初始值为0:

     

     

    当我们输入第一个序列,【1,1】,如下图,其中隐藏层的值,也就是绿色神经元,是通过公式St = f(U * Xt + W * St-1) 计算得到的,因为所有权重都是1,所以也就是 1∗1+1∗1+1∗0+1∗0=2 (我把向量X拆开计算的,由于篇幅关系,我只详细列了其中一个神经元的计算过程,希望大家可以看懂,看不懂的请留言),输出层的值4是通过公式 Qt=g(V⋅St) 计算得到的,也就是 2∗1+2∗1=4 (同上,也是只举例其中一个神经元),得到输出向量【4,4】:

     当【1,1】输入过后,我们的记忆里的 a1,a2 已经不是0了,而是把这一时刻的隐藏状态放在里面,即变成了2,如图,输入下一个向量【1,1】,隐藏层的值通过公式St=f(U * Xt + W * St−1) 得到, 1∗1+1∗1+1∗2+1∗2=6 ,输出层的值通过公式Qt=g(V * St),得到 6∗1+6∗1=12 ,最终得到输出向量【12,12】:

     

    同理,该时刻过后 a1,a2 的值变成了6,也就是输入第二个【1,1】过后所存下来的值,同理,输入第三个向量【2,2】,如图,细节过程不再描述,得到输出向量【32,32】:

    由此,我们得到了最终的输出序列为

    至此,一个完整的RNN结构我们已经经历了一遍,我们注意到,每一时刻的输出结果都与上一时刻的输入有着非常大的关系,如果我们将输入序列换个顺序,那么我们得到的结果也将是截然不同,这就是RNN的特性,可以处理序列数据,同时对序列也很敏感。

    二.LSTM

    如果你经过上面的文章看懂了RNN的内部原理,那么LSTM对你来说就很简单了,首先大概介绍一下LSTM,是四个单词的缩写,Long short-term memory,翻译过来就是长短期记忆,是RNN的一种,比普通RNN高级(上面讲的那种),基本一般情况下说使用RNN都是使用LSTM,现在很少有人使用上面讲的那个最基础版的RNN,因为那个存在一些问题,LSTM效果好,当然会选择它了!

    长短时记忆网络(Long Short Term Memory Network, LSTM),是一种改进之后的循环神经网络,可以解决RNN无法处理长距离的依赖的问题,目前比较流行。

    长短时记忆网络的思路:

    原始 RNN 的隐藏层只有一个状态,即h,它对于短期的输入非常敏感。
    再增加一个状态,即c,让它来保存长期的状态,称为单元状态(cell state)。

    把上图按照时间维度展开

     

    在 t 时刻,LSTM 的输入有三个:当前时刻网络的输入值 、上一时刻 LSTM 的输出值 、以及上一时刻的单元状态 
    LSTM 的输出有两个:当前时刻 LSTM 输出值 、和当前时刻的单元状态.

    关键问题是:怎样控制长期状态 c ?

    方法是:使用三个控制开关

    第一个开关,负责控制继续保存长期状态c;
    第二个开关,负责控制把即时状态输入到长期状态c;
    第三个开关,负责控制是否把长期状态c作为当前的LSTM的输出

    如何在算法中实现这三个开关?

    方法:用 门(gate)

    定义:gate 实际上就是一层全连接层,输入是一个向量,输出是一个 0到1 之间的实数向量。
    公式为:

    回忆一下它的样子:

    gate 如何进行控制?

    方法:用门的输出向量按元素乘以我们需要控制的那个向量
    原理:门的输出是 0到1 之间的实数向量,
    当门输出为 0 时,任何向量与之相乘都会得到 0 向量,这就相当于什么都不能通过;
    输出为 1 时,任何向量与之相乘都不会有任何改变,这就相当于什么都可以通过。


    LSTM 前向计算

    在 LSTM-1 中提到了,模型是通过使用三个控制开关来控制长期状态 c 的:

    这些开关就是用门(gate)来实现:

    接下来具体看这三重门


    LSTM 的前向计算:

    一共有 6 个公式

    遗忘门(forget gate)
    它决定了上一时刻的单元状态 c_t-1 有多少保留到当前时刻 c_t

    输入门(input gate)
    它决定了当前时刻网络的输入 x_t 有多少保存到单元状态 c_t

    输出门(output gate)
    控制单元状态 c_t 有多少输出到 LSTM 的当前输出值 h_t


    遗忘门的计算为:

    forget

    遗忘门的计算公式中:
    W_f 是遗忘门的权重矩阵,[h_t-1, x_t] 表示把两个向量连接成一个更长的向量,b_f 是遗忘门的偏置项,σ 是 sigmoid 函数。


    输入门的计算:

    input

    根据上一次的输出和本次输入来计算当前输入的单元状态:

    当前输入的单元状态c_t

    当前时刻的单元状态 c_t 的计算:由上一次的单元状态 c_t-1 按元素乘以遗忘门 f_t,再用当前输入的单元状态 c_t 按元素乘以输入门 i_t,再将两个积加和:
    这样,就可以把当前的记忆 c_t 和长期的记忆 c_t-1 组合在一起,形成了新的单元状态 c_t
    由于遗忘门的控制,它可以保存很久很久之前的信息,由于输入门的控制,它又可以避免当前无关紧要的内容进入记忆。

    当前时刻的单元状态c_t


    输出门的计算:

    output

    LSTM 的反向传播训练算法

    主要有三步:

    1. 前向计算每个神经元的输出值,一共有 5 个变量,计算方法就是前一部分:

    2. 反向计算每个神经元的误差项值。与 RNN 一样,LSTM 误差项的反向传播也是包括两个方向:
    一个是沿时间的反向传播,即从当前 t 时刻开始,计算每个时刻的误差项;
    一个是将误差项向上一层传播。

    3. 根据相应的误差项,计算每个权重的梯度。


    gate 的激活函数定义为 sigmoid 函数,输出的激活函数为 tanh 函数,导数分别为:

    具体推导公式为:

    具体推导公式为:


    目标是要学习 8 组参数,如下图所示:

    又权重矩阵 W 都是由两个矩阵拼接而成,这两部分在反向传播中使用不同的公式,因此在后续的推导中,权重矩阵也要被写为分开的两个矩阵。

    接着就来求两个方向的误差,和一个梯度计算。
    这个公式推导过程在本文的学习资料中有比较详细的介绍,大家可以去看原文:
    https://zybuluo.com/hanbingtao/note/581764


    1. 误差项沿时间的反向传递:

    定义 t 时刻的误差项:

    目的是要计算出 t-1 时刻的误差项:

    利用 h_t c_t 的定义,和全导数公式,可以得到 将误差项向前传递到任意k时刻的公式:


    2. 将误差项传递到上一层的公式:


    3. 权重梯度的计算:

    以上就是 LSTM 的训练算法的全部公式。

    参考博客:https://zhuanlan.zhihu.com/p/123211148

                    https://blog.csdn.net/Lison_Zhu/article/details/97236501

     

  • 相关阅读:
    【Unity】预制体材质变(Clone)克隆体问题
    JavaScript 通过数组对JSON key字段进行排序
    Vue3 set up 的使用
    AI创作与大语言模型:2023亚马逊云科技中国峰会引领企业应用新潮流
    【毕业设计】基于SSM与大数据分析的停车场管理系统
    how to view linux man file or .1 file on windows
    数据结构之线性表的顺序表(c语言)
    NIFI从Oracle11G同步数据到Mysql_亲测可用_解决数据重复_数据跟源表不一致的问题---大数据之Nifi工作笔记0065
    Node + Express 后台开发 —— 上传、下载和发布
    揭秘Spring Boot内嵌Tomcat原理
  • 原文地址:https://blog.csdn.net/qq_46454669/article/details/133756597