搞懂RNN

本文为李弘毅老师【Recurrent Neural Network(Part I)】和【Recurrent Neural Network(Part II)】的课程笔记,课程视频来源于youtube(需翻墙)。
下文中用到的图片均来自于李宏毅老师的PPT,若有侵权,必定删除。

1 什么是RNN

顾名思义,RNN就是一个不断循环的神经网络,只不过它在循环的过程当中是有记忆的,这也是发明RNN的初衷,就是希望神经网络在看一个序列的输入的时候可以考虑一下前面看过的内容。

我们以Slot Filling来举例。Slot Filiing就是填空的意思,比如今天有一个旅客说了一句"I would like to arrive Taipei on November 2nd",我们的订票系统就需要从这句话中找到"目的地"和"期望的到达时间"这两个slot。而帮助订票系统来解析这个句子的,也就是我们的RNN模型。
1
RNN是怎么运作的呢?简单粗暴地来说,就比如我们先往RNN里塞进一个"arrive"和一个随机初始化的状态向量 a 0 a^0 a0,然后RNN会输出一个output( y i y^i yi)和一个hidden state( a i a^i ai)。output用来表示"arrive"这个词在每个slot中的概率,hidden state是一个向量,包含着看过"arrive"之后,模型自己记下来的信息,然后再把这个hidden state和下一个输入"Taipei"塞进RNN里,如此反复,直到把整个句子看完。这就是一个最最最简单的RNN的运作流程, a i a^i ai就表示着RNN的记忆。不过也正是因为RNN需要记忆,所以RNN没法并行计算。
2
市面上两种RNN的记忆方法,一种是利用hidden state来当作记忆,叫做"Elman Network",另一种是利用"output"当作记忆,叫做"Jordan Network"。据说,output是有label在监督的,不像hidden state那么自由,所以"Jordan Network"的效果会好一些。不过,市面上也是有把两者结合起来的记忆方法的,名字就不知道了。
3
当然,这样的记忆只是单向的,有些时候句子的理解是需要句子后面的一些词汇的辅助的。为了解决这个问题,也就有了双向的RNN。双向的RNN的两个方向是可以并行计算的。下面这幅图应该是比较清楚的了,每个output是结合了从头到尾和从尾到头两个方向的output。
4

2 LSTM

市面上在使用的RNN并不是上述那么简单的,其中LSTM是比较常用的一种方法。LSTM的每一个cell的结构如下图所示,它吃四个input,吐出一个output。四个input分别是该time step的输入、控制input gate的信号、控制forget gate的信号以及控制output gate的信号。最中间的那个memory cell是用来存储之前序列留下的记忆信息的。input gate用来决定要不要接收这个输入,forget gate用来决定要不要使用之前的记忆,output gate用来决定要不要输出这个输出。
5
这么说可能还是有点糊涂,看下面这张图吧。比如我们某个time step的输入为 x t x^t xt,首先这个 x t x^t xt会分别乘以一个矩阵得到LSTM需要的四个输入。
z = W x t + b z f = W f x t + b f z i = W i x t + b i z o = W o x t + b o z = Wx^t+b\\ z^f = W^fx^t+b^f\\ z^i = W^ix^t+b^i\\ z^o = W^ox^t+b^o z=Wxt+bzf=Wfxt+bfzi=Wixt+bizo=Woxt+bo

然后, z i z^i zi会经过一个激活层,来控制输入 z z z,我们把这个中间量记作 i n p u t input input吧。
i n p u t = σ ( z i ) ∗ z input = \sigma(z^i)*z input=σ(zi)z

同时, z f z^f zf也会经过一个激活层,来决定是否要使用之前的记忆 c t − 1 c^{t-1} ct1,我们记这个中间变量叫做 m e m o r y memory memory吧。
m e m o r y = σ ( z f ) ∗ c t − 1 memory = \sigma(z^f)*c^{t-1} memory=σ(zf)ct1

这个 i n p u t input input m e m o r y memory memory会相加在一起,作为输出的结果,这个结果由经过一层激活层的 z o z^o zo来控制。这个输出我们叫做hidden state( h h h)。
h = σ ( z o ) ∗ σ ( i n p u t + m e m o r y ) h = \sigma(z^o)*\sigma(input+memory) h=σ(zo)σ(input+memory)
最后的结果 y t y^t yt一般还要来一层全连接。
y t = W y h y^t = W^yh yt=Wyh
6
不过这只是一个time step,LSTM在多个循环的时候,长下面这样。
7
可见,实际情况下,我们的输入并不是 x t x^t xt,而是 x t x^t xt h t h^t ht c t − 1 c^{t-1} ct1的结合。其中,利用 c t − 1 c^{t-1} ct1的这个操作被称为peehole。

而现在主流的框架之间的实现,也略有差别,比如pytorch的实现就没有利用peehole,激活层也有一些区别,不过整体的思路是完全一致的。

3 Training

3.1 Learning Target

在进行训练的时候,我们需要一个目标。这个目标其实是需要根据实际的应用场景来定的。比如,我们还是用上面订票系统的例子,我们的每一个time step的输出是一个概率向量,分别表示着[“other”, “dest”, “time”]的概率大小。我们的label就是一个one-hot encoding的向量,比如"arrive"的label中"other"的标签为1,其他为0;"Taipei"的label中"dest"的标签为1,其他为0;"on"的label中"other"的标签为1,其他为0;以此类推。然后用prediction算下cross entrophy loss就行了。

而RNN的反向传播也是和其他的神经网络一样,是可以用梯度下降来做的。不过,因为它是有时间顺序的,所以计算时略有不同,得要用一个叫做BPTT(Backpropagation through time)的方法来做,这里不详述了。总之就是可以和其他网络一样train下去。想了解的可以看下吴恩达的RNN W1L04 : Backpropagation through time
8

3.2 为什么难train

虽然RNN也是和正常的神经网络那样可以用gradient descent不断地更新参数来train下去,但在RNN刚出来的时候,几乎没有人可以把它train出来,往往会得到一条如下图绿色曲线这样的结果。只有一个叫做Razvan Pascanu的人,可以train出那条蓝色的曲线。其实原因时因为RNN的loss space非常陡峭,参数微小的变动,可能引起loss极大的改变。Razvan Pascanu在他写博士论文的时候,把他一直可以train出好结果的秘诀公布了出来,那就是gradient clipping,即人为地把gradient的大小限制住了。没错就是这么简单的一个技巧。
9
但究竟为什么RNN的梯度会发生这么大的变化呢?我们来举个例子说明一下。假如我们有一个全世界最简单的RNN,它输入的weight是1,输出的weight也是1,用来memory的weight为 w w w,那么当我们输入一个长度为1000,且只有第一个元素为1,其余都为0的序列时,最后一个time step的输出就为 y 1000 = w 999 y^{1000}=w^{999} y1000=w999

这是一个什么概念呢?比如我们的 w = 1 w=1 w=1,那么 y 1000 = 1 y^{1000}=1 y1000=1。而此时, w w w只要稍稍变大一点,那么 y 1000 y^{1000} y1000就会产生很大的变化,比如 w = 1.01 w=1.01 w=1.01时, y 1000 = 20000 y^{1000}=20000 y1000=20000。这时候也就会发生所谓的梯度爆炸。而当 w w w降到1一下时, y 1000 y^{1000} y1000又一直变为0了,这也就是所谓的梯度消失。

而这一切的一切都是因为RNN的参数在循环的过程中被不断的重复使用。
10
LSTM在一定程度上是可以解决梯度消失的问题的。为什么LSTM可以解决梯度消失?我感觉李老师这里还是有点没讲清楚,推荐看下这篇blog(需翻墙)。一句话就是,传统的RNN的反向传播操作(BPTT)有个连乘的东西在,在LSTM的BPTT里是连加的,然后LSTM又有forget gate这个门在,可以使得相隔较远的序列不相互影响。

简单来说就是用clip可以缓解梯度爆炸,用LSTM可以缓解梯度消失。

我有一点很想知道的是,发明LSTM的大佬,是为了解决梯度消失的问题而发明了LSTM呢?还是发明了LSTM之后,发现可以缓解梯度消失?这个也真是太6了~

4 应用举例

RNN的应用范围非常广泛,这里简单列举一下李老师视频中提到的一些例子。

4.1 Many To One

  • 情感分析。输入一段评论,输出该段评论是好评还是差评。
  • 关键信息提取。输入一篇文章,输出该文章中的关键信息。

4.2 Many To Many

  • 语音识别。输入一段语音,输出对应的文字。
  • 语言翻译。输入一段某国的文字或语音,输出一段另一个国家的对应意思的文字或语音。
  • 聊天机器人。输入一句话,输出回答。

4.3 其他

  • 句子文法结果分析。输入一个句子,输出该句子的文法结构。
  • 句子自编码。
了解一些常用的机器学习算法对于数据仓库项目确实很有帮助,因为它们可以帮助你在数据分析、预测分析以及业务智能方面提供支持。以下是几种常见的机器学习算法: 1. **线性回归** (Linear Regression):用于预测数值型结果,通过拟合数据找到最佳直线来估计因变量和自变量之间的关系。 2. **逻辑回归** (Logistic Regression):常用于分类问题,特别是二分类场景,将输入映射到0和1的概率上。 3. **决策树** (Decision Trees):直观易懂,常用于特征选择和划分数据集,可以生成规则模型。 4. **随机森林** (Random Forests):集成多个决策树,提高预测准确性和减少过拟合。 5. **支持向量机** (Support Vector Machines, SVM):适用于分类和回归,寻找最优超平面进行分割或预测。 6. **K近邻算法** (K-Nearest Neighbors, KNN):基于实例的学习,通过计算样本间的距离来进行预测。 7. **朴素贝叶斯** (Naive Bayes):基于概率统计的一种简单分类模型,假设特征间相互独立。 8. **神经网络** (Deep Learning):包括深度前馈网络、卷积神经网络(CNN) 和循环神经网络(RNN),广泛应用于图像识别、自然语言处理等领域。 理解这些算法的工作原理和应用场景,能让你在数据仓库的设计过程中更好地选择合适的工具和技术,优化数据挖掘过程,并帮助企业做出数据驱动的决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七元权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值