循环神经网络之通俗易懂篇(东北话版)
欢迎关注本人的微信公众号AI_Engine
之前我们主要介绍了前馈神经网络和卷积神经网络,与之有共同特性的深度信念网络DNN我后续会逐步介绍。这三者都属于标准神经网络的范畴,但是标准神经网络在某些领域存在着一些不足:
1.他们在数据的局部依赖性感知度较高,即所有的训练数据与测试数据批次之间都是相互独立的。但是如果数据与数据之间存在着千丝万缕的联系时,标准神经网络的效果就不会太好。比如在视频中抽取的每一帧图像,音频中截取的每一段话,每段话中的每个单词,这些都不是独立的数据。所以在这种情况下,用标准神经网络训练数据就不是最佳的选择。
2.标准神经网络的输入都是标准等长的向量,比如输入层有10个节点,那就只能接受10个元素,多了或者少了都不行。但是类似于文本数据的长度并不固定就受到了限制。有人说:这有啥的,通过截取、填充等技术手段将文本数据归一化到一个固定的长度,不就完了?但是由于标准神经网络的每个输入节点之间是独立的,它们互相之间无法感知相邻数据的依赖关系,结果又成了互相独立的数据,最终算法对数据的表达效果也不会很好。
那你说咋整的?别激恼,循环神经网络RNN不就借这功夫呼之欲出了么。RNN的核心诉求之一就是将过去的信息连接到当前的任务中,也就是利用过往的知识经验预测未来.......(尼玛,说的可有点垒悬了)
还是先给大家一个直观的概念,这就是一个传统RDD的网络模型展开图:
循环神经网络之所以称为循环是因为RNN网络具有循环结构,从而使过去的信息能够作为'记忆'被保留下来,并作为当前输入的一部分。换句话说,在RNN中同一隐藏层之间的节点是有连接的。现在我来给大家讲解一下上面这幅网络结构究竟表达了什么。首先左侧是一个循环图,右侧是循环图的简易展开图。其中左侧图中的黑色方块主要描述了一个延迟连接,即从上一个时刻的隐藏状态S(t-1)到当前时刻的隐藏状态S(t)之间的连接。如果把上面有W的那个带箭头的圈去掉,它就变成了最普通的全连接神经网络。其中,x是一个向量,它表示输入层的值、s是一个向量,它表示隐藏层的值(这里隐藏层面画了一个节点,你也可以想象这一层其实是多个节点,节点数与向量s的维度相同)。U是输入层到隐藏层的权重矩阵。o也是一个向量,它表示输出层的值;V是隐藏层到输出层的权重矩阵。那么,现在我们来看看W是什么。循环神经网络的隐藏层的值S(t)不仅仅取决于当前这次的输入x,还取决于上一次隐藏层的反馈值S(t-1),因此W就是隐藏层上一次的值作为当前输入的权重矩阵。那现在就可以简单的推导一下:
0t=G(V * S(t)) .a
St=F(U * X(t) + W * S(t-1)) .b
.a主要讲了这么一个事,话说数据S(t)想从隐藏层往输出层跑,想出来混。这个时候它联合了输出层的权重矩阵V,告诉他你跟我混吧,别在这里待着了。于是乎二者相依相伴,并最终借助激活函数G的威力 liao(一声)了。
.b讲的就是隐藏层的事儿了,话说在S(t)跑出去之前,那它可是历经了层层磨难,最终修成了正果。S(t)的前世是S(t-1),S(t-1)买通了转世摆渡人(权重)W,跟他说:“我想投胎转世,需要借助你的力量”,W说:“我看你平时挺招人烦的,你快点走吧。但是若想转到现世,你需要在现世中找到一个肯与你同化的人,并且这个人需要经过现世摆渡人(权重)U的允许,你们二者才可结合。”S(t-1)最后是不负众望,借助激活函数F成功的转成了现世S(t)。
话说当S(t)出去了之后,拥有了一身的本领,其中就包括看穿过往与来世,它发现了这么个事:
S(t)瞬间顿悟,原来现在的自己不仅仅和'凡人' X(t)、X(t-1)、X(t-2)...有关,还和S(t)、S(t-1)、S(t-2)...这么多曾经的自己有关,看来自己真的是不容易啊。
好了,故事是讲完了。我们可以得出一个结论:最终的结果和每一次的输入和记忆都有关。这些就是历史输入信息(X(t),X(t-1),X(t-2),.....,X(1)),而这些就是记忆信息(S(t),S(t-1),S(t-2),...,S(1))
RNN的基本结构我们现在已经清楚了,下面的任务就是如何正确的训练它,也就是说如何找到最佳的权值矩阵。训练RNN的算法叫做时间反向传播BPTT。BPTT与BP有着异曲同工之妙,其核心任务就是利用反向传播进行调参,从而使得损失函数loss最小化。熟悉BP的同学应该就知道反向传播是个什么玩楞了,所以理解BPTT就不会很困难。如果不熟悉也没有关系,后续我会给大家梳理一下BP算法的基本原理以及相应流程。在RNN中有很多的变种,其变化的不同就在于隐藏层的设计中。基本原理就是把当前的输入和记忆信息进行组合,然后利用非线性的激活函数就行处理。那么说到这个激活函数,在RNN最差用的恐怕就是sigmoid了,这小子长这个B型:
当我们进行反向传播的时候势必要对去x进行求导,所以其导数值域锁定在[0,1/4]范围内。所以每一层的反向传播梯度就会以上一层1/4的速度递减,那可就是指数级的递减啊,这可不得梯度弥散么!梯度都消失了,参数就不知道往哪调了,损失函数最优解也就凉凉了。所以,RNN有一定的局限性!
针对传统RNN无法利用历史信息的问题,循环网络的一种变体:长短期记忆神经网络LSTM问世了。LSTM有自己独特的设计结构,可以很好的处理梯度消失的问题,适合解决时间间隔和延迟非常长的任务。这种独特的结构就是可控自循环,可以产生让梯度能够得以长时间的可持续流动(听不懂是吧?怪我没说人话,被着急,让我一点一点跟你解释)。我们先看一下传统RNN神经元和LSTM神经元(注意我说的是某一个神经元)对比图:
这个c就是记忆单元,也可称为“记忆块(memory block)”,用以取代传统的隐含神经元节点。c“合理地”保存长期的状态,并负责把记忆信息从序列的初始位置传递到序列的末端。我们将这个传递序列按时间步展开:
在LSTM结构中t时刻,当前神经元(粗红线标识)的输入有三个:当前时刻输入值Xt、前一时刻输出值St-1和前一时刻的记忆单元状态Ct-1。输出有两个:当前时刻LSTM输出值St和当前时刻的记忆单元状态Ct。需要注意的是,这里的x,s和c都是向量,里面都包含多个参数值。
Dui dui dui dui dui dui dui !重点来了!那就是如何有效控制这个长期状态c?那就是LSTM中的四大神门!
我们先看一个简易图(盗的,图中只表现了三个门。这第一把门开关,就是负责决定把前一个长期记忆 Ct-1 在多大程度上保留到 Ct 中,它可选择性地遗忘部分之前积累的信息;第二把门开关,就是负责控制以多大程度把当前即时状态存入到长期记忆状态 Ct中;第三把开关,负责控制是否把长期状态c,作为当前LSTM的输出:
下面我就对着四个门做详细的解释:
1.遗忘门:遗忘门输出的其实是一个’比例’,就是决定忘记多少的一种比例。σ表示激活函数,这里通常为sigmoid。 W tf表示遗忘门权重矩阵,
U tf是遗忘门输入层与隐层之间的权重矩阵, bf表示遗忘门的偏置。
我们可以看出遗忘门干的活就是将隐藏层上一次的输出与当前的输入做了线性组合,然后利用激活函数,将其输出值压缩到0到1的区间之内。当输出值越靠近1,表明记忆体(cell block)保留的信息就越多。反之,越靠近0,表明保留的就越少。遗忘门的逻辑设计图如下:
2.输入门:输入门输出的其实也是一个’比例’,就是决定从输入中保留多少的一种比例。
发现和遗忘门的区别只是权重和偏置不同而已,但是这就够了。输入门的逻辑设计图如下:
3.候选门:注意,这输出的就不是比例了!而是具体的信息,它主要负责“勾兑”当前输入信息和过去记忆信息,也就是候选门主要负责计算当前输入的单元状态 C't。
此时的激活函数也不是sigmoid了,变成了tanh。接下来,我们需要把记忆体中的状态从 Ct-1 变更到 Ct。记忆的更新可由两部分元素组成:
(1)通过遗忘门过滤掉不想保留得部分记忆,大小可记为: ft * Ct-1
(2)添加当前新增的信息,添加的比例由输入门控制,大小可记为:it * C't。然后将这两个部分线性组合,得到更新后的记忆信息 Ct。
那么输入门与候选门的组合图就应该是酱儿婶的:
4.输出门:这个就比较好理解了,就是控制Ct能输出多少并应用于下一个网络层的更新喽。当然它还是一个比例,激活函数同样为sigmoid。
但是这里的输出,也需要“把持住自己”,不能太“任性”的输出,因此还要用激活函数tanh把记忆值变换一下,将其变换为-1至+1之间的数。负值区间表示不但不能输出,还得压制一点,正数区间表示合理的输出。这样有张有弛,方得始终。
最后,我们给出LSTM隐层单元完整的逻辑图:
看到这里的朋友可能就会提问了,那LSTM究竟是如何处理梯度消失问题的呢?其实玄机就在于上述的加法操作,加法操作可以帮助LSTM在反向传播是时维持恒定的误差,而这个误差就是调参的方向,从而避免了梯度消失的问题。在LSTM训练过程中呢,除了前向传播和计算损失函数,在反向传播中根据损失函数的梯度指引,更新网络权值参数。与传统RNN类似,LSTM误差项的反向传播包括两个层面:一个是空间上层面的,将误差项向网络的上一层传播。另一个是时间层面上的,沿时间反向传播。即从当前t时刻开始,计算每个时刻的误差。
这篇文章与之前不同的是先不给出demo,为啥不给呢?因为没写呢,想要demo的可以私聊我,最主要的是关注我,微信公众号,简书,知乎都可以搜索AI_Engine,然后点击关注,双击666,东北老铁谢谢了奥!