本篇文章被Google中国社区组织人转发,评价: 条理清晰,写的很详细!

被阿里算法工程师点在看!

所以很值得一看!

前言

目录:

RNN提出的背景

- 一个问题

- 为什么不用标准神经网络

- RNN模型怎么解决这个问题

- RNN模型适用的数据特征

- RNN几种类型

RNN模型结构

- RNN block

- 简化符号表示

- stacked RNN

- 双向RNN

- 梯度消失爆炸问题

GRU模型结构

LSTM模型结构

- LSTM背后的关键思想

- Step by Step理解LSTM

本文可以解答:

  • RNN用来解决什么问题,什么样的数据特征适合用它来解决

  • ​RNN的缺陷是什么,LSTM,GRU是如何解决这些缺陷的

  • 理解从简单RNN到LSTM的每个模型的结构

RNN提出背景/适用场景

一个问题

我们考虑一下这么一个问题,任意给定一句话,判断句子里的单词是不是人名的一部分。比如输入

x : Harry Potter and Hermione Granger invented a new spell.

单词有

['Harry', 'Potter', 'and', 'Hermione', 'Granger', 'invented', 'a', 'new', 'spell']

如果1表示单词是人名一部分,0表示不是人名的部分,那么输出的y就应该是

[1, 1, 0, 1, 1, 0, 0, 0, 0]

y的组成是和x等长,相同的index对应x中元素是不是人名。我们把x中的每个单词用one-hot向量来表征,如下所示。

为什么不用标准的神经网络?

如果我们用标准的神经网络来解决这个问题,标准神经网络的结构是这样的

标准神经网络的流程,将样本数据x一次性输入,从左边传到右边(输出层)。这样做不好的地方在于:

  • 输入和输出的长度不固定,比如有的句子输入长度是10,有的句子长度就不是10。

  • 如果使用标准网络,它不能共享文本不同位置学习到的东西,比如知道Harry是人名一部分,如果第i个位置又出现了Harray,它是不能自动识别的。

RNN模型怎么解决这个问题

 

RNN对数据的处理流程如上图所示,它不会同时输入数据。我们将首先输入X1(第一个单词Harray)得到预估值y1(Harray是不是人名一部分),然后将X1计算的结果传递到下一层与输入X2(第二个单词Potter)结合输出对X2的预测y2(Potter是不是人名一部分),这样y2的预测其实受X1的影响,以此类推。这样就解决了标准神经网络带来的问题。

RNN模型适用的数据特征

 

上面的句子有个特征:

  • States Dependency:当前的状态和上一步的状态是相关的;

  • 数据是序列的(sequential): 当我们说一个数据是序列的,是指数据之间有时间顺序,它是在不同时间输入的,如果我们更改顺序,把句子中的单词打乱,它就变的不同失去含义了。能用标准神经网络训练的数据就是可以打乱顺序,所以我们可以在一开始就输入它们。

所以用RNN最大的动力就是它可以连接之前的数据,意味着这个模型关心之前的东西是什么,接下来将要出现什么。

RNN的几种类型

除了上面的例子,RNN根据不同的输入和输出数量,有以下几种类型:

one on one: 输入一张图片,输出图片中的活动。

one  to many: 输入一张图片,输出描述图片中的内容,其中输出的内容前后是有依赖的,相关的,比如上面一张图就是‘一个人在跑步’,‘一个’和‘人’是相关的,如果‘一个’变了,那么‘人’可能也会变。

many to one: 情感分类,输入是一个句子,输出是评分,输入的前后是依赖相关的。

many to many: 翻译系统,将德语翻译成英语,输入和输出都是相关的。

many to many: 语音识别,传入一段语音,输出是转换成的文字。

RNN的模型结构

RNN block

 

我们的模型将会采用两个值,t时间处,X的输入值和前一个单元格 t-1 时间处的输出值A。左边是传统的神经网络模型,它在左边基础上是如何变成右边的?我们用第一个单元的运算来举例。

方程①:就像我们使用简单ANN所做的那样,它也存在权重Wax,Waa和偏差Ba。它只是增加一个输入值A0(前一个单元的输出值)。

单元有两个不同的输出: A1的输出(由公式②得到)将转到下一个单元,公式③的最终输出Y1。

所有权重的下标意思是,第一个下标是计算某类型的量,第二个下标是你要乘以的类型。比如Wax,它乘以的是X1,要计算的是A1,所以它的下标是ax。

现在,让我们进入下一个单元。整个过程如下图所示。

简化符号表示

但是为了简化符号,后面图中的公式都是简化的符号, 令:

于是:

我们将

变成

符号变了,但是意思是没有变的,只是为了方便简写,所以后面都是用简化后的公式。

 

Stacked RNN

如果把RNN堆在一起,输出的y又可以作为x输入到另一个神经网络中,那么它的结构就是这样的。

 

双向RNN

如果我们输入以下句子:

He said, “Teddy bears are on sale!”

模型可能会判断‘Teddy’是一个人名,是因为模型没有考虑之后句子的含义,所以,这时候又要考虑前面又要考虑后面,就需要双向的RNN,它的结构是这样的:

梯度消失/爆炸问题

 

我们看这样一个例子:

The cat,which already ate ...(中间省略很长很长), was(预测这个单词) full

The cats,which ate ...(中间省略很长很长), were(预测这个单词) full

当预测一个很长的句子,而预测的值依赖于很前面的信息(cat/cats),RNN就难以预测,这就是RNN不擅长处理的长依赖关系。为什么呢?

关键问题就在于向后传播。

向后传播的目的是在每一层更新权重,为了更新权重,我们将计算损失函数的梯度,并且因为链式法则,会把多个梯度相乘。试想一下,如果梯度大于1,那么多个梯度相乘将会使得数值比较大,用它来更新优化权重会比较大,这种情况我们叫做梯度爆炸(exploding gradients),这还不是大问题,因为我们可以做个梯度修剪,如果大于某个值就缩放就行了;真正的问题是,如果梯度小于1,那么连乘梯度将使得结果非常的小,这样它就不能更新权重,输出的结果就没有什么不同,这样的情况我们叫梯度消失(vanishing gradients),这就表明向后传播是不能影响很前面层的。

这就是人们说RNN的记忆不好,如果输入长度太长,我们就不能预测实际的值,造成这样结果最根本原因就是神经网络中的权重更新。

那么我们怎么解决这个问题呢?

一个思想就是,与其记住所有的过去,不如选择性的记住重要的信息而忽略其它信息。

GRU模型结构

如何做到选择性的记忆之前的信息?关键思想是提出了一个门控循环单元(Units Gated Recurrent Units),用它来控制重要信息。

注: 图中的tanh就是上面图中激活函数g的具体化函数。

GRU相对于RNN,多了一个绿色的框框,这个框框就是门控制器,我们把它叫做更新门,用来决定记住过去的信息多少的,提供模型的记忆能力。

GRU第一步也是和RNN第一步一样,用激活函数激活,但是它不会马上被使用,而是作为候选值静静等待。接着计算GRU更新门的值,由于它采用的是sigmoid函数,所以它的输出值范围是在0到1之间的。所以将第2步的值乘以第1步的值实际上就是在做"选择性记忆",如果是0,那么就是“不记忆/不更新/不使用”,如果是1,那么就是"记忆/更新/使用",就像一个打开关闭的门。GRU第三步就是用更新门的值来决定当前是用新的计算值还是用之前的值。

它比接下来讲的LSTM要简单,参数要少,更少的参数就意味着减少过拟合,减少训练时间。

LSTM的模型结构

 

LSTM背后的关键思想

 

LSTM的全称是Long Short Term Memory networks,LSTM被明确设计为避免长期依赖问题。长时间记住信息是它的默认行为,而不是它努力学习的东西。LSTM的关键是单元状态(cell state),最上面那条水平线。图中C表示,它将包含放在隐藏状态值之外的记忆值。它有点像是传送带,仅仅在一些微小的线性变换下贯穿整个链条,信息不加改变地流动非常容易。

LSTM可以通过门这种结构给cell state移除或增加信息。门能够选择性让信息通过,它由sigmoid神经网络层和逐点乘法操作符组成。sigmoid层输出0到1的数字,描述每个组件应该让它通过多少。数值0表示都不通过,1表示让它全部通过。

LSTM有三个门来保护和控制cell state的状态。整个模型结构如下图

图中的三个绿色框框从左到右依次是忘记门(forget gate),更新门(update gate),输出门(output gate)。

Step by Step理解LSTM

 

先整体看一下LSTM和GRU的不同:

让我们看看右边,前两行其实就是和GRU一样,第3行等式,它是计算忘记门的值,它用于更新单元状态(第四行等式),最后第5行是计算输出门,用于得到第6行A在t时刻的值。

第一步就是决定我们要从cell state中丢弃哪些信息。这个决定是由叫‘forget gate layer’的sigmoid层指定的。它看起来像输入ht-1,xt,然后为每个ct-1(t-1时刻的cell state)变量中的数据输出0到1之间的数字。1就是保留全部,0是全部不要。

下一步是确定要在cell state下存储哪些新信息

这一步包括两个部分:

  • 首先,称为“更新门”的sigmoid层决定了我们将更新哪些值。

  • 接下来,tanh层创建新候选值(可以添加到cell state中的值)C̃ t向量。

下一步将会结合这两个值去对状态进行更新。

这一步是更新cell state

我们将旧状态值和忘记门相乘,目的是忘记该忘记的信息,只记住重要的信息;然后用更新门和候选状态相乘,目的是决定到底我们需要多少新状态值的信息。

最后,我们需要决定要输出什么

这个输出是在cell state基础上计算的,但是是它的过滤版本。首先我们用sigmoid层来确定要输出当前cell state的哪些部分;接着我们把结果送到tanh并和输出门相乘,这样我们就可以只输出我们期望的那部分结果。

因为有这三个额外的门,LSTM有着更强的记忆能力,它们控制着哪个部分需要记住,记住多少,所以它在处理序列模型的时候很受欢迎。

参考资料:

  • 吴恩达deeplearning.ai第五门课 Module 1: Recurrent Neural Networks (RNNs)

  • The Most Intuitive and Easiest Guide for Recurrent Neural Network

  • Must-Read Tutorial to Learn Sequence Modeling (deeplearning.ai Course #5)

  • 2015-08-Understanding-LSTMs

今日互动

 

文首的问题你想清楚了吗?

吴恩达deepLearning.ai循环神经网络RNN学习笔记_没有复杂数学公式,看图就懂了!!!(理论篇)的更多相关文章

  1. 吴恩达deepLearning.ai循环神经网络RNN学习笔记_看图就懂了!!!(理论篇)

    前言 目录: RNN提出的背景 - 一个问题 - 为什么不用标准神经网络 - RNN模型怎么解决这个问题 - RNN模型适用的数据特征 - RNN几种类型 RNN模型结构 - RNN block - ...

  2. 用纯Python实现循环神经网络RNN向前传播过程(吴恩达DeepLearning.ai作业)

    Google TensorFlow程序员点赞的文章!   前言 目录: - 向量表示以及它的维度 - rnn cell - rnn 向前传播 重点关注: - 如何把数据向量化的,它们的维度是怎么来的 ...

  3. 一文看懂神经网络初始化!吴恩达Deeplearning.ai最新干货

    [导读]神经网络的初始化是训练流程的重要基础环节,会对模型的性能.收敛性.收敛速度等产生重要的影响.本文是deeplearning.ai的一篇技术博客,文章指出,对初始化值的大小选取不当,  可能造成 ...

  4. 吴恩达DeepLearning.ai的Sequence model作业Dinosaurus Island

    目录 1 问题设置 1.1 数据集和预处理 1.2 概览整个模型 2. 创建模型模块 2.1 在优化循环中梯度裁剪 2.2 采样 3. 构建语言模型 3.1 梯度下降 3.2 训练模型 4. 结论   ...

  5. 循环神经网络(RNN)--学习笔记

    一.基本概念 RNN针对的数据是时序数据.RNN它解决了前馈神经网络,无法体现数据时序关系的缺点.在RNN网络中,不仅同一个隐含层的节点可以相互连接,同时隐含层的输入不仅来源于输入层的输入还包括了上一 ...

  6. 吴恩达《AI For Everyone》_练习英语翻译_待更新

    AI For Everyone https://www.coursera.org/learn/ai-for-everyone 讲师: Andrew Ng (吴恩达) CEO/Founder Landi ...

  7. 吴恩达deeplearning之CNN—卷积神经网络

    https://blog.csdn.net/ice_actor/article/details/78648780 个人理解: 卷积计算的过程其实是将原始的全连接换成了卷积全连接,每个kernel为对应 ...

  8. 吴恩达DeepLearning 第一课第四周随笔

    第四周 4.1深度神经网络符号约定 L=4______(神经网络层数)   4.2 校正矩阵的维数 校正要点:,, dZ,dA,dW,db都与它们被导数(Z,A,W,b)的维数相同 4.3 为什么使用 ...

  9. 吴恩达 Deep learning 第一周 深度学习概论

    知识点 1. Relu(Rectified Liner Uints 整流线性单元)激活函数:max(0,z) 神经网络中常用ReLU激活函数,与机器学习课程里面提到的sigmoid激活函数相比有以下优 ...

随机推荐

  1. 重拾c++第一天(3):数据处理

    1.short至少16位:int至少与short一样长:long至少32位,且至少与int一样长:long long至少64位,且至少与long一样长 2.sizeof 变量  返回变量长度  或者s ...

  2. Java中的SPI扩展机制(有demo)

    参考连接:https://www.jianshu.com/p/3a3edbcd8f24 一.什么是SPI SPI ,全称为 Service Provider Interface,是一种服务发现机制.它 ...

  3. 单调队列优化 dp

    The only difference between easy and hard versions is the constraints. Vova likes pictures with kitt ...

  4. DP-Fibonacci

    善于发现 DP 中的 Fibonacci 我们在做 DP  题时  , 会发现有一些题 类似于找规律的题 ,观察测试样例 , 要对数据敏感 , 比如输入 2 输出 1 , 输入 3 就输出 2 …… ...

  5. django 建立安全索引

    上篇记录使用“CONCURRENTLY” 命令行执行不锁表索引,对于django, 如何执行呢?这里记录一种方法,修改django迁移文件. 在执行完迁移后,为了方便找到该迁移文件,可以采用指定命名迁 ...

  6. idea 2019.3 最新版破解教程

    背景 最近,idea又被整治了,所以一大批激活码都失效了.我之前已经有2018版的永久激活了,所以非常淡定~,也没打算升级版本.但是,最近发现周围的人都在讨论这个问题.于是,我也找到了2019.3最新 ...

  7. Nginx代理服务——常用的配置语法

    可以到官方查看所有代理的配置语法http://nginx.org/en/docs/http/ngx_http_proxy_module.html 缓存区 Syntax:proxy_buffering ...

  8. msi通过powershell安装、卸载

    function install_msi($url) { $telemetry = @{ DisplayName = "Telemetry Service"; filename = ...

  9. 如何在匿名thread子类中保证线程安全

    在做性能测试的过程中,我写了两个虚拟类ThreadLimitTimeCount和ThreadLimitTimesCount做框架,通过对线程的标记来完成超时请求的记录.旧方法如下: @Override ...

  10. ffifdyop——绕过中一个奇妙的字符串

    根据师傅们的博客总结如下: ffifdyop 经过md5加密后:276f722736c95d99e921722cf9ed621c 再转换为字符串:'or'6<乱码>  即  'or'66� ...