针对初学者的循环神经网络介绍

2019 年 8 月 20 日 Python程序员

简单介绍什么是RNN,它们如何运行,以及如何用Python从头构建一个RNN。


循环神经网络(RNN)是一种专门处理序列的神经网络。它们通常用于自然语言处理(NLP)任务,因为它们在处理文本方面非常有效。在本文中,我们将探索什么是RNN,了解它们是如何工作的,并使用Python从头构建一个真正的RNN(仅使用numpy库)。


这篇文章假设你有神经网络的基本知识。我对神经网络的介绍涵盖了你需要知道的一切,所以我建议你先读一下(https://victorzhou.com/blog/intro-to-neural-networks/  )。

我们开始吧!


1、为什么有用


标准神经网络(以及CNN)的一个问题是,它们只能处理预先确定的大小: 它们接受固定大小的输入并产生固定大小的输出。RNN是有用的,因为它允许我们使用可变长度的序列作为输入和输出。下面是一些RNN的例子:


输入为红色,RNN本身为绿色,输出为蓝色。来源:Andrej Karpathy


这种处理序列的能力使RNN非常有用。例如:


  • 机器翻译(比如谷歌翻译)是通过“多对多”RNN完成的。原始文本序列被输入一个RNN,然后该RNN会生成翻译文本作为输出。

  • 情感分析 (例如,这是一个积极的还是消极的评论?)通常是通过“多对一” 的RNN完成的。要分析的文本被输入一个RNN,然后该RNN会生成一个单独的输出分类(例如,这是一个积极的评论)。


在本文的后面,我们将从头构建一个“多对一”的RNN来执行基本的情感分析。

2、工作原理


我们假设有一个带有输入x0,x1,...xn的“多对多”的RNN,我们希望它产生输出y0,y1,...yn。这些xi 和yi是向量,可以有任意的维数。


RNN利用以任意给定的步长t反复地更新一个隐藏状态h来运行,h是一个向量,也可以有任意的维数。


  1. 下一个隐藏状态ht是使用前一个隐藏状态ht -1和下一个输入xt进行计算的。

  2. 下一个输出yt是使用ht进行计算的。

一个多对多RNN


这就是使RNN循环的东西: 它对每个步骤使用相同的权重。具体来说,一个典型的标准RNN只使用3组权重来进行计算:


  • Wxh, 用于所有的 xt → ht 连接。

  • Whh, 用于所有的 ht-1 → ht 连接。

  • Why, 用于所有的 ht → yt 连接。


我们也对我们的RNN使用两个偏差:


  • bh,计算ht时加上。

  • by, 计算yt时加上。


我们用矩阵表示权重,用向量表示偏差。这3个权重和2个偏差就构成了整个RNN!


下面是把所有东西放在一起的方程式:


不要略过这些方程。停下来,盯着这个方程看一分钟。另外,记住权重是矩阵,其它变量是向量。


所有的权重都使用矩阵乘法进行应用,并将偏差加到结果乘积中。然后,我们使用tanh作为第一个方程的激活函数(其它激活函数像sigmoid也可以使用)。


不知道什么是激活函数?请认真阅读我之前提到的神经网络介绍。

3、要解决的问题


我们来动手干吧!我们将从头实现一个RNN来执行一个简单的情感分析任务: 确定给定的文本字符串是积极的还是消极的。


下面是我为本文收集的小数据集中的一些例子:



4. 计划


由于这是一个分类问题,我们将使用“多对一" RNN。这与我们前面讨论的“多对多”RNN类似,只不过它只使用最终的隐藏状态来产生一个输出y:

一个多对一RNN


每个xi都是一个向量,表示文本中的一个单词。输出y将是一个包含两个数字的向量,一个表示积极的,另一个表示消极的。我们将使用Softmax将这些值转换为概率,并最终在积极的/消极的之间进行决定。


我们来开始构建我们的RNN!


5. 预处理


我前面提到的数据集由两个Python字典组成:


True=积极的,False=消极的


我们必须做一些预处理才能把数据转换成可用的格式。首先,我们将构造一个包含我们数据中所有单词的词汇表:



vocab现在包含了至少在一个训练文本中出现的所有单词的列表。接下来,我们将分配一个整数索引来表示vocab中的每个单词。



我们现在可以用对应的整数索引表示任意给定的单词!这是必要的,因为RNN不能理解单词——我们必须给它们提供数字。


最后,回想一下RNN的每个输入xi都是一个向量。我们将使用one-hot向量,它除了包含一个1之外,其余值都是0。每个one-hot向量中的“1”将位于这个单词对应的整数索引处。


由于我们的词汇表中有18个唯一的单词,每个xi将是一个18维的one-hot向量。



稍后,我们将使用createInputs()来创建向量输入,并将其传入我们的RNN。


6. 正向阶段


是时候开始实现我们的RNN了!我们将从初始化我们的RNN所需要的3个权重和2个偏差开始:


注意:我们除以1000是为了减小权重的初始方差。这并不是初始化权重的最佳方法,但它很简单,适合本文。


我们使用np.random.randn()从标准正态分布来初始化我们的权重。


接下来,我们来实现RNN的正向传递。还记得我们之前看到的这两个方程吗?



下面是这些同样的方程被写入代码中的形式:



很简单,对吧?注意,我们在第一步中将h初始化为零向量,因为此时没有可以供我们使用的前一个h。


让我们来试试:


如果你需要复习一下Softmax,请阅读我对Softmax的简要说明。


我们的RNN可以运行,但还不是很有用。我们来改变这一点……


7. 逆向阶段


为了训练我们的RNN,我们首先需要一个损失函数。我们将使用交叉熵损失函数,它通常与Softmax配对使用。我们是这样计算它的:

其中pc 是我们的RNN对正确类(积极的或消极的)的预测概率。例如,如果一个积极的文本被我们的RNN预测为90%的积极度,则损失为:

现在我们有了一个损失,我们将使用梯度下降训练我们的RNN来最小化损失。这意味着是时候推导一些梯度了!


⚠️以下部分假设你有多变量微积分的基本知识。如果你愿意,你可以跳过它,但我建议即使你不太明白也要略读一下。我们将在推导结果时逐步编写代码,即使表面的理解也会有所帮助。


如果你想了解这部分的额外背景知识,我建议你先阅读我的《神经网络介绍》中的《训练神经网络》部分。此外,这篇文章的所有代码都在Github上,所以如果你愿意,你可以follow它。


准备好了吗?我们开始吧。


7.1 定义


首先,我们来看一些定义:


  • 让 y代表来自我们RNN的原始输出。

  • 让p代表最终的概率:p=softmax(y).

  • 让c 指代一个特定文本例子的真实标签,也可以说是“正确的”类。 

  • 让L代表交叉熵损失:L=-ln(pc)

  • 让Wxh 、Whh 和Why代表我们的RNN中的3个权重矩阵。

  • 让bh和by 代表我们的RNN中的两个偏差向量。


7.2设置


接下来,我们需要编辑正向阶段来缓存一些数据,以便在反向阶段中使用。在此过程中,我们还将为反向阶段设置骨架。它是这样的:



想知道我们为什么要进行缓存吗?请阅读我在我的CNN介绍的训练概述中的说明。我在其中做了同样的事情。


7.3梯度


是用到数学的时候了!我们从计算∂L/∂y开始。我们知道:

我将把使用链式法则推导∂L/∂y的过程留给你,但是推导出来的结果是漂亮的:

例如,如果我们有p = [0.2, 0.2, 0.6],并且其正确的类是c=0,那么我们就会得到 ∂L/∂y=[−0.8,0.2,0.6] 。这转换称代码也是很容易的:



漂亮!下一步,我们来为Why和by尝试一下梯度,它们的梯度只用与将最终的隐藏状态转换为RNN的输出。我们有:


式中,hn是最终的隐藏状态,因此,

类似地,

现在,我们可以开始实现 backprop()!



提醒: 我们之前在forward()中创建了self.last_hs。


最后,我们需要Whh 、Wxh 和bh的权重,它们将在RNN中的每一步使用。我们有:

因为改变Wxh会影响每一个ht ,而每一个ht都会影响y,并最终影响L。为了完全计算Wxh的梯度,我们需要反向传播所有的步长,这也被称为随时间反向传播(BPTT):



随时间进行的反向传播


Wxh被用于所有的xt  —> ht 正向连接,因此我们必须反向传播回这些连接的每一个。


一旦我们到达了一个给定的步长t,我们需要计算∂ht/∂Wxh

tanh的推导是众所周知的:

我们和平常一样使用链式法则:

类似地,

我们需要的最后一个东西是∂y/∂ht,我们可以递归地计算它:

我们将从最后的隐藏状态开始,并逆向运行来实现BPTT,这样当我们想要计算∂y/∂ht+1的时候我们就已经有了∂y/∂ht!最后的隐藏状态hn是一个例外:

现在我们有了最终实现BPTT和完成backprop()所需要的所有东西:


一些需要注意的东西:


  • 为了方便起见,我们已经将(∂L/∂y)*(∂y/∂h)合并到 ∂L/∂h中了。

  • 我们需要不断地更新一个保存最近的∂L/∂ht+1值的变量d_h,我们计算∂L/∂ht需要用到这个值。

  • 在完成BPTT之后,我们使用np.clip()截取小于-1或大于1的梯度值。这有助于缓解梯度爆炸问题,这是因为有很多相乘项时,梯度就会变的非常大。对于普通的RNN来说,梯度爆炸或梯度消失是很有问题的——像LSTM这样更复杂的RNN通常能够很好地处理它们。

  • 一旦所有的梯度被计算出,我们就使用梯度下降来更新权重和偏差。


我们做到了!我们的RNN是完整的。


8. 高潮


终于到了我们一直等待的时刻——我们来测试我们的RNN!


首先,我们将编写一个辅助函数来使用我们的RNN处理数据:



现在,我们可以编写训练循环:



运行main.py应该会输出如下内容:



从结果来看我们自己建立的RNN还不错。


想自己尝试或修改这段代码吗?请在浏览器中运行这个RNN(https://repl.it/@vzhou842/A-RNN-from-scratch)。你也可以在Github上找到它。(https://github.com/vzhou842/rnn-from-scratch)


9. 结尾


就是这样!在这篇文章中,我们完成了一个循环神经网络的一个演示,包括它们是什么,它们是如何工作的,它们为什么有用,如何训练它们,以及如何实现一个。虽然如此,你还有很多事情可以做:


  • 学习长短期记忆网络,一个更强大更流行的RNN架构,或者学习门控循环单元(GRU),一个著名的LSTM变体。

  • 使用合适的ML库(比如Tensorflow、 Keras或 PyTorch)对更大/更好的RNN进行实验。

  • 阅读关于双向RNN的内容。它会正向和反向处理序列,因此,有更多的信息对于输出层来说是可用的。

  • 尝试词嵌入(比如 GloVe 或 Word2Vec),你可以使用它们将单词转换成更有用的向量表示形式。 

  • 尝试自然语言工具集(NLTK),一个流行的处理人类语言数据的Python库。


我写了很多关于机器学习的文章,所以如果你有兴趣从我这里获得前沿的ML内容,请订阅我的时事通讯。


感谢阅读!


英文原文:https://victorzhou.com/blog/intro-to-rnns/ 
译者:Nothing
登录查看更多
7

相关内容

RNN:循环神经网络,是深度学习的一种模型。
一份循环神经网络RNNs简明教程,37页ppt
专知会员服务
168+阅读 · 2020年5月6日
一份简短《图神经网络GNN》笔记,入门小册
专知会员服务
224+阅读 · 2020年4月11日
【MIT深度学习课程】深度序列建模,Deep Sequence Modeling
专知会员服务
76+阅读 · 2020年2月3日
【强化学习】深度强化学习初学者指南
专知会员服务
178+阅读 · 2019年12月14日
注意力机制模型最新综述
专知会员服务
260+阅读 · 2019年10月20日
注意力机制介绍,Attention Mechanism
专知会员服务
165+阅读 · 2019年10月13日
深度学习自然语言处理综述,266篇参考文献
专知会员服务
225+阅读 · 2019年10月12日
干货 | 循环神经网络(RNN)和LSTM初学者指南
THU数据派
15+阅读 · 2019年1月25日
可视化循环神经网络的注意力机制
论智
22+阅读 · 2018年9月23日
深度学习循环神经网络详解
七月在线实验室
15+阅读 · 2018年5月28日
基础 | 基于注意力机制的seq2seq网络
黑龙江大学自然语言处理实验室
16+阅读 · 2018年3月7日
深度学习基础之LSTM
全球人工智能
26+阅读 · 2017年12月18日
LSTM入门必读:从基础知识到工作方式详解
炼数成金订阅号
6+阅读 · 2017年7月26日
RNN | RNN实践指南(2)
KingsGarden
19+阅读 · 2017年5月4日
Neural Image Captioning
Arxiv
5+阅读 · 2019年7月2日
Arxiv
17+阅读 · 2019年4月5日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
19+阅读 · 2018年10月25日
Recurrent Fusion Network for Image Captioning
Arxiv
3+阅读 · 2018年7月31日
Arxiv
15+阅读 · 2018年6月23日
Arxiv
25+阅读 · 2018年1月24日
Arxiv
5+阅读 · 2017年11月13日
Arxiv
4+阅读 · 2017年7月25日
VIP会员
相关VIP内容
一份循环神经网络RNNs简明教程,37页ppt
专知会员服务
168+阅读 · 2020年5月6日
一份简短《图神经网络GNN》笔记,入门小册
专知会员服务
224+阅读 · 2020年4月11日
【MIT深度学习课程】深度序列建模,Deep Sequence Modeling
专知会员服务
76+阅读 · 2020年2月3日
【强化学习】深度强化学习初学者指南
专知会员服务
178+阅读 · 2019年12月14日
注意力机制模型最新综述
专知会员服务
260+阅读 · 2019年10月20日
注意力机制介绍,Attention Mechanism
专知会员服务
165+阅读 · 2019年10月13日
深度学习自然语言处理综述,266篇参考文献
专知会员服务
225+阅读 · 2019年10月12日
相关资讯
干货 | 循环神经网络(RNN)和LSTM初学者指南
THU数据派
15+阅读 · 2019年1月25日
可视化循环神经网络的注意力机制
论智
22+阅读 · 2018年9月23日
深度学习循环神经网络详解
七月在线实验室
15+阅读 · 2018年5月28日
基础 | 基于注意力机制的seq2seq网络
黑龙江大学自然语言处理实验室
16+阅读 · 2018年3月7日
深度学习基础之LSTM
全球人工智能
26+阅读 · 2017年12月18日
LSTM入门必读:从基础知识到工作方式详解
炼数成金订阅号
6+阅读 · 2017年7月26日
RNN | RNN实践指南(2)
KingsGarden
19+阅读 · 2017年5月4日
相关论文
Neural Image Captioning
Arxiv
5+阅读 · 2019年7月2日
Arxiv
17+阅读 · 2019年4月5日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
19+阅读 · 2018年10月25日
Recurrent Fusion Network for Image Captioning
Arxiv
3+阅读 · 2018年7月31日
Arxiv
15+阅读 · 2018年6月23日
Arxiv
25+阅读 · 2018年1月24日
Arxiv
5+阅读 · 2017年11月13日
Arxiv
4+阅读 · 2017年7月25日
Top
微信扫码咨询专知VIP会员