本文目录
常见神经网络
卷积神经网络
卷积神经网络(Convolutional Neural Networks,CNN)属于前馈神经网络的一种,其特点是每层的神经元节点只响应前一层局部区域范围内的神经元$($全连接网络中每个神经元节点响应前一层的全部节点$)$。卷积神经网络中最重要的事卷积算法。
卷积算法的计算过程如下面这张动图所示:
具体的卷积层中某个神经元的输出计算的方式可以用下面的公式描述:
\[z_{i, j, k}=b_{k}+\sum_{u=1}^{f_{h}} \sum_{v=1}^{f_{w}} \sum_{k^{\prime}=1}^{f_{n^{\prime}}} x_{i^{\prime}, j^{\prime}, k^{\prime}} w_{u, v, k^{\prime}, k} \\ with \left\{\begin{array}{l}{i^{\prime}=u \cdot s_{h}+f_{h}-1} \\ {j^{\prime}=v \cdot s_{w}+f_{w}-1}\end{array}\right.\]- 式中$z_{i,j,k}$是第$l$层卷积层中的位于第$k$个特征层(feature map 或者说 channel)中的第$i$行第$j$列的神经元的输出。
- $s_h$以及$s_w$分别对应高度$H$以及宽度$W$方向上的步伐(strides),$f_h$以及$f_w$对应的是一次卷积操作范围的高度和宽度(比如上面的动图就是$3 \times 3 $ ),$f_{n’}$表示前一层即第$l-1$层的特征层的数量。
- $x_{i’, j’, k’}$是第$l-1$层上的位于第$k’$个特征层中的第$i’$行第$j’$列的神经元的输出。
- $b_k$是第$l$层卷积层的偏差(bias)
- $w_{u,v, k’, k}$ 是第$l$层卷积层中的第$k$个特征层上的神经元与前一层卷积层中位于第$u$行第$v$列第$k’$个特征层的神经元的输出的权重连接。
一个深度卷积神经网络模型通常由若干卷积层叠加若干全连接层组成,中间也包含各种非线性操作以及池化操作:
深度卷积神经网络同样可以使用反向传播算法进行训练,相较于其他网络模型,卷积操作的参数共享特性使得需要优化的参数数目大大缩减,提高了模型的训练效率以及可扩展性。由于卷积运算主要用于处理类网格结构的数据,因此对于时间序列以及图像数据的分析与识别具有显著优势。
卷积操作的特性
-
稀疏交互。在卷积神经网络中,卷积核尺度远小于输入的维度,这样每个输出神经元仅与前一层特定局部区域内的神经元存在连接权重(即产生交互,如下图所示),我们称这种特性为稀疏交互。
稀疏交互的物理意义是,通常图像、文本、语音等现实世界中的数据都具有局部的特征结构,我们可以先学习局部的特征,再将局部的特征组合起来形成更复杂和抽象的特征。
-
参数共享。在卷积神经网络中,卷积核中的每一个元素将作用于每一次局部输入的特定位置上。根据参数共享的思想,我们只需要学习一组参数集合,而不需要针对每个位置的每个参数都进行优化,从而大大降低了模型的存储需求。
参数共享的物理意义是使得卷积层具有平移等变性。假如图像中有一只猫,那么无论它出现在图像中的任何位置,我们都应该将它识别为猫,也就是说神经网络的输出对于平移变换来说应当是等变的。
池化操作
池化操作(pooling)是深度卷积神经网络中的重要组成部分。常用的池化操作主要包括均值池化(mean pooling),最大池化(max pooling)等。这两种池化方式
- 均值池化通过对邻域内特征数值求平均来实现,能够抑制由于邻域大小受限造成估计值方差增大的现象,特点是对背景的保留效果更好。
- 最大池化则通过取邻域内特征的最大值来实现,能够抑制网络参数误差造成估计均值偏移的现象,特点是更好地提取纹理信息。
池化操作的本质是降采样。池化操作除了能显著降低参数量外,还能够保持对平移、伸缩、旋转操作的 不变性。这种不变形使得它特别适合放在CNN后面,用于图像的特征提取。
用于文本分类的CNN
卷积神经网络的核心思想是捕捉局部特征,它不仅在图像领域取得了巨大的成功,在文本分类领域也有很好的效果。对于文本来说,局部特征就是由若干个单词组成的滑动窗口,类似于N-gram。卷积神经网络的优势在于能够自动地对N-gram特征进行组合和筛选,获得不同抽象层次的语义信息。下面是使用CNN进行文本分类的示意图:
需要注意的是,若词向量的维数为$d$,那么卷积核的宽度必须与$d$相同,而卷积核的高度可以理解成N-gram中的N,表示从文本中提取类似N-gram的局部特征。
深度残差网络
在神经网络训练中,网络层数的增加会引发梯度消失的问题,这是因为梯度在反向传播时会逐渐衰减,使得远离输出层(即接近输入层)的网络层不能够得到有效的学习,影响了模型泛化的效果。
深度残差网络(Deep Residual Network,ResNet)的提出就是为了解决或缓解深层的神经网络训练中的梯度消失问题而提出的。
ResNet的调整如下图所示:
相比起标准的网络结构,ResNet将可以将$l$层输入直接短接到$l+2$层,这样,上图所示的$F(x)$只需要拟合输入$x$与目标输出$H(x)$的残差$H(x) - x$,残差网络的名称也因此而来。如果某一层的输出已经较好的拟合了期望结果,那么多加入一层不会使得模型变得更差,因为该层的输出将直接被短接到两层之后,相当于直接学习了一个恒等映射,而跳过的两层只需要拟合上层输出和目标之间的残差即可。
ResNet可以有效改善深层的神经网络学习问题,使得训练更深的网络成为可能。
循环神经网络(Recurrent Neural Network,RNN)
循环神经网络(Recurrent Neural Network,RNN)的提出是为了用来建模序列化数据。
我们知道,传统的前馈神经网络一般的输入都是一个定长的向量,无法处理变长的序列信息,即使通过一些方法把序列处理成定长的向量,模型也很难捕捉序列中的长距离依赖关系。与前馈神经网络不同的是,RNN可以通过将神经元串行起来处理序列化的数据。由于每个神经元能用它的内部变量保存之前输入的序列信息,因此整个序列经过RNN后被浓缩成抽象的表示,并可以据此进行分类或生成新的序列。
Vanilla RNN
最简单的RNN模型如下图所示:
由图可见,一个长度为$t$的序列用循环神经网络建模,展开之后可以看作是一个$t$层的前馈神经网络。$h_{(t)}$与$x_{(t)}^T$和$h_{(t-1)}$的关系如下:
\[\mathbf{h}_{(t)}=f\left(\mathbf{x}_{(t)}^{T} \cdot \mathbf{w}_{x}+\mathbf{h}_{(t-1)}^{T} \cdot \mathbf{w}_{y}+b\right) \\ \mathbf{y}_{(t)} = g(\mathbf{h}_t \cdot \mathbf{w}_z)\]其中,$f$和$g$为激活函数,$w_x, w_y, w_z$表示权重矩阵。由上可以看出, RNN中第$t$层的隐含状态$h_t$ 编码了序列中前$t$个输入的信息,可以通过当前的输入$x_t$ 和上一层神经网络的状态$h_{t-1}$ 计算得到;最后一层的状态$h_t$ 编码了整个序列的信息,因此可以作为整篇文档的压缩表示,以此为基础的结构可以应用于多种具体任务。
Vanilla RNN的局限性
循环神经网络模型的求解可以采用BPTT(Back Propagation Through Time,基于时间的反向传播)算法实现,实际上是反向传播算法的简单变种。如果将循环神经网络按时间展开成$T$层的前馈神经网络来理解,就和普通的反向传播算法没有什么区别了。
但是由于BPTT计算过程中,预测的误差沿着神经网络的每一层反向传播,每一层梯度可以表示成连乘的形式,随着离输出越来越远,每层的梯度大小会呈指数增长,导致梯度爆炸,或者是指数缩小,导致梯度消失。
梯度爆炸的问题可以通过梯度裁剪来缓解,即当梯度的范式大于某个给定值时,对梯度进行等比收缩。而梯度消失问题相对比较棘手,需要对模型本身进行改进。深度残差网络是对前馈神经网络的改进,通过残差学习的方式缓解了梯度消失的现象,从而使得我们能够学习到更深层的网络表示;而对于循环神经网络来说,长短时记忆模型(LSTM)及其变种门控循环单元(GRU)等模型通过加入门控机制,很大程度上弥补了梯度消失所带来的损失。
注意:RNN 中的梯度消失/梯度爆炸和普通的 MLP 或者深层 CNN 中梯度消失/梯度爆炸的含义不一样。MLP/CNN 中不同的层有不同的参数,各是各的梯度;而 RNN 中同样的权重在各个时间步共享,最终的梯度 $g$ 各个时间步的梯度 $g_t $的和,所以,RNN中总的梯度是不会消失的,即便梯度越传越弱,那也只是远距离的梯度消失,由于近距离的梯度不会消失,所有梯度之和便不会消失。RNN 所谓梯度消失的真正含义是,梯度被近距离梯度主导,导致模型难以学到远距离的依赖关系。
LSTM
LSTM的结构如下所示:
其中:
先忽略LSTM内部的结构,可以发现,LSTM仍然是基于$x_t$以及隐状态(这里是$h_t$还有$c_t$) 来计算下一步的隐状态的。但是,LSTM内部中加入了输入门$i_t$ ,遗忘门$f_t$以及输出门$o_t$三个门和一个内部记忆单元$c_t$。 输入门控制当前计算的新状态以多大程度更新到记忆单元中,遗忘门控制前一步记忆单元中的信息有多大程度被遗忘掉;输出门控制当前的输出有多大程度上取决于当前的记忆单元。
那么LSTM是怎么学习到序列之间的长期依赖的呢?在一个训练好的LSTM中,当输入的序列中没有重要信息时,LSTM的遗忘门的值接近于1,输入门的值接近于0,此时过去的记忆会被保存,从而实现了长期记忆功能;当输入的序列中出现了重要的信息时,LSTM应当把其存入记忆中,此时其输入门的值会接近于1;当输入的序列中出现了重要信息,且该信息意味着之前的记忆不再重要时,输入门的值接近1,而遗忘门的值接近于0,这样旧的记忆被遗忘,新的重要信息被记忆。经过这样的设计,整个网络更容易学习到序列之间的长期依赖。
关于LSTM需要注意的点:
窥孔机制(Peephole)的定义
窥孔机制(Peephole)是在经典LSTM计算门控时,让记忆$c_{t-1}$也参与到门控的计算中,此时输入门的更新方式变为
\[\mathbf{i}_{(t)}=\sigma\left(\mathbf{W}_{x i}^{T} \cdot \mathbf{x}_{(t)}+\mathbf{W}_{h i}^{T} \cdot \mathbf{h}_{(t-1)}+\mathbf{W}_{c i}^{T} \cdot \mathbf{c}_{(t-1)}+\mathbf{b}_{i}\right)\]其余门控单元的计算类似。
LSTM比起Vanilla RNN的优势:
LSTM能学习到序列之间的长距离依赖。而Vanilla RNN中由于梯度被近距离梯度主导,远距离的梯度很弱(或者消失),导致模型难以学到远距离的依赖关系。
为什么LSTM能克服这个问题呢?比起Vanilla RNN,LSTM 中梯度的传播有很多条路径, \(\mathbf{c}_{(t)}=\mathbf{f}_{(t)} \otimes \mathbf{c}_{(t-1)}+\mathbf{i}_{(t)} \otimes \mathbf{g}_{(t)}\) , 这条路径上只有逐元素相乘和相加的操作,梯度流很稳定,虽然在其他梯度路径上,LSTM的梯度流和Vanilla RNN并无区别,但是由于 总的远距离梯度 = 各条路径的远距离梯度之和,即便其他远距离路径梯度消失了,只要保证有一条远距离路径梯度不消失,总的远距离梯度就不会消失(正常梯度 + 消失梯度 = 正常梯度)。因此 LSTM 通过改善一条路径上的梯度问题拯救了总体的远距离梯度。
GRU
GRU是对LSTM单元的一种简化,GRU的结构如下所示:
其中:
由上可以看出,GRU对LSTM的简化主要包括以下几点:
- LSTM中有两个状态向量$h_t, c_t$, GRU只有$h_t$
- 移除了输出门,$y_{(t)} = h_{(t)}$
- GRU中的遗忘门以及输入门是联动的。如果遗忘门为1,那么输入门就为0,反之亦然。
在实际应用中,LSTM和GRU的效果差别并不大。GRU更为简单,计算效率占优,而LSTM更为复杂,表达能力更强点。
RNN的应用
上图是RNN在实际使用中的几种用法:
-
一对多,比如图像的标题生成
- 多对一,比如句子的情感分析
- 多对多(seq2seq模型):
- encoder-decoder模式,RNN在处理整个输入序列之后再产生另外一个序列,如文本翻译或者文本摘要,encoder-decoder模型有助于RNN获得全局的信息。
- 无时差的序列到序列转化,比如给一个录像中的每一帧贴标签。
参考
A technical report on convolution arithmetic in the context of deep learning