一、循环神经网络基础

​ 在前面的文章中,介绍了全连接神经网络(DNN)和卷积神经网络(CNN),以及它们的训练和使用。回忆一下,它们都是能单独的处理一个个的输入,前一个输入和后一个输入是完全没有关系的。然后,现实当中是,某些任务需要能够更好的处理序列性质的信息,即前面的输入和后面的输入是有关系的。例如,当我们理解一句话意思时,孤立的理解这句话的每个词都是不够的,我们需要处理这些词连接起来的整个序列;当我们处理视频时,也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列。这时,使用我们前文介绍的DNN和CNN是不够的,而需要用到深度学习领域中另一类非常重要的神经网络:循环神经网络(Recurrent Neural Network, RNN)。RNN种类繁多,过程繁琐,本部分首先对其结构进行剥茧抽丝,以理解RNNs及其训练算法;进一步地,介绍两中常见的RNN类型:长短时记忆网络(Long Short-Term Memory Network,LSTM),门控循环单元(Gated Recurrent Unit, GRU)。

1.1 从语言模型开始

为什么要从语言模型开始呢?因为,RNN是在自然语言处理领域中最先被用起来的,例如,RNN可以构建语言模型。那什么是语言模型呢?

我们可以让电脑做这样一个练习:写出一个句子前面的一些词,然后,让电脑帮我们写出接下来的一个词。比如下面这句话:

我昨天上学迟到了,老师批评了____。

在这个句子中,接下来的词最有可能的是“我”,而不是“小明”,更不会是“吃饭”。

在这个例子中,语言模型是这样的一个东西:给定一个一句话前面的部分,预测接下来最有可能的一个词是什么。

语言模型是对一种语言的特征进行建模,它有很多用处。比如在语音转文本(STT)的应用中,声学模型输出的结果,往往是若干个可能的候选词,这时候就需要语言模型来从这些候选词中选择一个最有可能的。当然,它同样也可以用在图像到文本的识别中国(OCR)。

在使用RNN之前,语言模型主要采用N-Gram算法。N是一个自然数,比如2或者3.它的含义是:假设一个词出现的概率只与前面N个词相关。我们以2-Gram为例,对这句话给出部分进行分词:

我|昨天|上学|迟到|了|,|老师|批评|了|____。

如果用2-Gram进行建模,那么电脑在预测的时候,只会看到前面的“了”,然后,电脑会在语料库中,搜索“了”后面最有可能的一个词。不管最后电脑选择的是不是“我”,显然这个模型是不靠谱的,因为“了”前面说了那么一大推实际上是没有用到的。如果使用3-Gram模型呢,会搜索“批评了”后面最有可能的词,感觉比2-Gram靠谱了不少,但还是远远不够的。因为这句话最关键的信息“我”,远在9个词之前。

看到这儿,大家可能会想,可以继续提升N的值呀,比如4-Gram、5-Gram、\(\dots\)。实际上,大家再深入想一下就会发现,这个想法是没有实用性的,因为当我们想处理任意长度的句子时,N设为多少都是不合适的;另外,模型的大小和N的关系是指数级的,4-Gram模型就会占用海量的存储空间。

所以,就该轮到RNN出场了,RNN理论上可以往前看(或往后看)任意多个词。

1.2 什么是循环神经网络?

循环神经网络种类繁多,我们先从最简单的基础循环神经网络开始吧~

1.2.1 基本循环神经网络

下图是一个简单的循环神经网络,它由输入层、一个隐藏层和一个输出层组成:

循环神经网络的实在是太难画出来了,网上所有大神们都不得不用了这种抽象的手法。不过,仔细看的话,如果把上面有\(W\)的那个带箭头的圈去掉,它就变成了最普通的全连接网络了。\(x\)是一个向量,它表示输入层的值(这里没有画出来表示输入层神经元节点的圆圈),\(s\)是一个向量,它表示隐藏层的值(这里隐藏层画了一个节点,你也可以想象这一层其实是多个节点,节点数目与向量\(s\)的维度相同);\(U\)是输入层到隐藏层的权重矩阵;\(O\)也是一个向量,它表示输出层的值;\(V\)是隐藏层到输出层的权重矩阵。那么,现在我们来看看\(W\)是什么,循环神经网络的隐藏层的值\(s\)不仅仅取决于当前这次输入\(x\),还取决于上一次隐藏层的值\(s\)。权重矩阵\(W\)就是隐藏层上一次的值作为这一次的输入的权重。

如果我们把上面的图展开,循环神经网络的也可以画成下面的样子:

在这里插入图片描述

现在看上去就比较清晰了,这个网络在\(t\)时刻接收到输入\(x_t\)之后,隐藏层的值是\(s_t\),输出值是\(o_t\)。关键一点是,\(s_t\)的值不仅仅取决于\(x_t\),还取决于\(s_{t-1}\)。我们可以用下面的公式来表示循环神经网络的计算方法:

​ $$o_t=g(Vs_t) \tag{1}$$

​ $$s_t = f(Ux_t+Ws_{t-1}) \tag{2}$$

式1是输出层的计算公式,输出层是全连接层,也就是它的节点都是和隐藏层的每个节点相连。\(V\)是一个输出层的权重矩阵,\(g\)是激活函数。式2是隐藏层的计算公式,它是循环层。\(U\)是输入\(x\)的权重矩阵,\(W\)是上一次输出值\(s_{t-1}\)作为这一次输入的权重矩阵,\(f\)是激活函数。

从上面的公式我们可以看出,循环层和全连接层的区别就是循环层多了一个权重矩阵\(W\)

如果反复把式2带入到式1,我们可以得到:

​ $$\begin{aligned}o_t &=g(Vs_t) \ &=Vf(Ux_1+Ws_{t-1})\ &=Vf(Ux_t+Wf(Ux_{t-1}+Ws_{t-2}))\&=Vf(Ux_t+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Ws_{t-3})))\ &=Vf(Ux_t+Wf(Ux_{t-1}+Wf(Ux_{t-2}+Wf(Ux_{t-3}+\dots)))) \end{aligned}$$

从上面可以看出,循环神经网络的输出值\(o_t\),是受前面历次输入值\(X_t\)\(X_{t-1}\)\(X_{t-2}\)\(\dots\)影响的,这也是为什么循环神经网络可以往前看任意多个输入值的原因。

1.2.2 双向循环神经网络

对于语言模型来说,很多时候光看前面的词是不够的,比如下面这句话:

我的手机坏了,我打算____一部新手机。

可以想象的是,如果我们只看到横线前面的词,手机坏了,那么我是打算修一修?换一部新的手机?还是哭哭?这些都是无法确定的。但是如果我们还看到横线后面的词是“一部新手机”,那么,横线上的词填“买”的概率就大得多了。

在上一节中的基本循环神经网络是无法对此进行建模的,因此,我们需要双向循环神经网络,如下图所示:

在这里插入图片描述

当遇到这种从未来穿越回来的场景时,难免处于懵逼的状态。不过我们还是可以用屡试不爽的老办法:先分析一个特殊场景,然后再总结一般的规律。我们先考虑上图中,\(y_2\)的计算。

从上图可以看出,双向循环神经网络的隐藏层要保存两个值,一个\(A\)参与正向计算,另一个值\(A\’\)参与计算。最终的输出值\(y_2\)取决于\(A_2\)\(A_2\’\)。其计算方法为:

\(y_2=g(VA_2+V\’A_2\’)\)

其中\(A_2\)\(A_2\’\)的计算为:

\(A_2=f(WA_1+UX_2)\)

\(A_2\’=f(W\’A_3\’+U\’X_2)\)

至此,我们已经可以看出一般的规律:正向计算时,隐藏层的值\(S_t\)\(S_{t-1}\)有关;反向计算时,隐藏层的值\(S_t\’\)\(S_{t+1}\’\)有关;最终的输出取决于正向和反向计算的加和。现在,我们仿照式1和式2,写出双向循环神经网络的计算方法:

\(O_t=g(VS_t+V\’S_t\’)\)

\(S_t=f(UX_t+WS_{t-1})\)

\(S_t\’=f(U\’X_t+W\’S_{t+1}\’)\)

从上面的三个公式可以看到,正向计算和反向计算不共享权重,也就是说\(U\)\(U\’\)\(W\)\(W\’\)\(V\)\(V\’\)都是不同的权重矩阵。

1.2.3 深度循环神经网络

前面我们介绍的循环神经网络只有一个隐藏层,当然了,也可以堆叠两个以上的隐藏层,这样就得到了深度循环神经网络。如下图所示:

在这里插入图片描述

我们把第\(i\)个隐藏层的值表示为\(S_t^{(i)}\)\(S_t\’^{(i)}\),则深度循环神经网络的计算方式可以表示为:

\(O_t=g(V^{(i)}S_t^{(i)}+V\’^{(i)}S_t\’^{(i)})\)

\(S_t^{(i)}=f(U^{(i)}S_t^{i-1}+W^{(i)}S_{t-1})\)

\(S_t\’^{(i)}=f(U\’^{(i)}S_t\’^{(i-1)}+W\’^{(i)}S_{t+1}\’)\)

\(\cdots\)

\(S_t^{(1)}=f(U^{(1)}X_t+W^{(1)}S_{t-1})\)

\(S_t\’^{(1)}=f(U\’^{(1)}X_t+W\’^{(1)}S_{t+1}\’)\)

1.3 循环神经网络的训练

1.3.1 循环神经网络的训练算法:BPTT

\(BPTT\)算法是针对循环层的训练算法,它的基本原理和\(BP\)算法是一样的,也包含同样的三个步骤:

  1. 前向计算每个神经元的输出值;

  2. 反向计算每个神经元的误差项\(\delta_j\)值,它是误差函数\(E\)对神经元\(j\)的加权输入\(net_j\)的偏导数;

  3. 计算每个权重的梯度。

    循环层如下图所示:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a8kYlBqb-1583227061275)(./img2/5.png)]

最后再用随机梯度下降算法更新权重。

前向计算

使用前面的式2对循环层进行前向计算:

\(S_t=f(UX_t+WS_{t-1})\)

注意:上面的\(S_t\)\(X_t\)\(S_{t-1}\)都是向量,用黑体字母表示(在这里都用大写替代表示了

版权声明:本文为RoyalFlush原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/RoyalFlush/p/12488238.html