前馈神经网络

人法地,地法天,天法道,道法自然。 – 《道德经》

总述

人工神经网络(以下简称NNet)是一种很著名的机器学习算法,其学习方式的独特性和自动提取数据特征的能力使得它能够独立于其它的传统机器学习方法(比如SVM、决策树等)而自成一派。随着深度学习的普及,NNet大有立于时代浪潮之巅的势头。然而,如今火热的NNet算法,自其诞生开始就历经了波折,其进化之旅并不是一帆风顺的。本文将从NNet的演进开始介绍,重点涉及前馈神经网络及其最核心的后向传播算法,同时附带一些优化技巧,作为近期学习和使用的阶段性总结。

演进

NNet并不是一种很年轻的算法。相反,最早的NNet研究从1943年就已经开始了。当全世界都还处在二战的阴影中时,心理学家McCulloch和数学家Pitts参考生物神经元结构(如下图),提出了一种Mindlike Machine的构想,指出这种机器可以通过模拟生物神经元互相联结的结构(轴突与树突)来实现,从而第一次将类神经元模型引入了计算机领域。

此后不久,Rosenblatt创造出了著名的感知器模型,并成功地完成了一些简单的机器学习任务,从此NNet的研究便开始变得火热起来。然而好景不长,Minsky和Papert从数学上证明了感知器模型并不能实现复杂的逻辑功能,因此将不同的感知器通过多层叠加以实现非线性逻辑成为了一种必然,这就形成了类神经网络的雏形,然而这种多层感知器的训练却一直是个难以解决的问题。所幸在20世纪80年代,Rumelhart和Hinton提出了著名的后向传播算法(Backpropagation),解决了这一棘手难题,并在前馈神经网络中普及应用,NNet模型终于开始大规模地在工业领域铺开。

但是随着数据变得越加复杂,数据量呈指数级增长,受限于当时的计算机算力,类神经网络模型渐渐地被训练更加高效的其它机器学习算法取代(尽管这些算法往往需要非常优秀的特征工程作为辅助手段),其应用规模和影响力逐渐下滑,并在20世纪90年代进入低谷期,尤其是在90年代中期,NNet模型更是遭遇到了来自SVM的强有力挑战(全局最优解、高效训练)。

10年沉沦之后,在2006年,提出了后向传播算法的Hinton在《Science》上发表了论文,首次提出了“深度信度网络”的概念,通过预训练(pre-training)和微调(fine-tuning)过程的结合,大大减少了多层NNet的训练时间,同时有赖于计算机算力的提升(尤其是GPU提供的强大的矩阵运算能力),NNet在训练上的劣势逐渐变得不再重要,相反,自动提取数据特征这一优势却使得NNet超越了其它模型而鹤立鸡群,这一模型学习方式就是现在最火热的“深度学习”,这种多层的NNet也被称为“深度神经网络”。现如今,深度网络已经逐渐在图像领域实现了大规模成功的应用,在NLP领域也有不少成功的例子,其火热程度目前没有任何一个机器学习算法可以匹敌。

在这一部分的剩余篇幅内,我们将介绍NNet演进过程中的三个里程碑式的模型:感知器、类神经网络以及深度神经网络。

感知器(Perceptron)

感知器是模拟生物神经元的产物,其基本结构如下图所示:

最左边的一列代表外界的输入值,在生物神经元模型中类比外界刺激,每一个刺激都有一个权重与之相称,代表这个刺激对触发神经元的贡献大小。通过输入与权重相乘并加总之后,我们就得到了一个触发值,经过一个非线性函数的转换,这个神经元最终的触发结果就被确定了。整个过程非常类似生物神经元模型中神经元接受外界刺激并作出应激反应,因此这一模型也被称为“感知器模型”。用数学的形式来定义感知器模型,可以描述成以下线性函数的形式:
$$g(X) = W^TX$$
上式中X是输入向量,W是权重向量。感知器其实就是一个线性函数。

优点

  • 模型简单易解释,权重易于计算
  • 通过多个感知器在同一层的加入,可以模拟任何线性分类逻辑

缺点

  • 不能模拟非线性逻辑(比如异或运算)

类神经网络(Artificial Neural Network)

通过多层、每层多个感知器的叠加,我们就构建出了类神经网络。本文将重点介绍前馈神经网络(以下的NNet将特指此类网络)及其训练方法。一个典型的NNet一般具有如下结构:

左边第一层称为输入层,右边第一层称为输出层,其余层均称为隐藏层。除了输入层以外,每一层都由若干个神经元组成。除了输出层以外,每一层都有一个非零的偏差项(bias),用来在普通神经元计算结果为0的时候仍然能够有非零的输出。除输出层外,每一个神经元有一个激活函数,用来产出这个神经元最终的计算结果。一个NNet的预测过程,就是从一个输入数据出发,后面每一层对上一层的输入进行线性组合(称为分数,score)并完成非线性转换,最终输出预测结果(称为假设,hypothesis)。由于有这样从前到后的预测过程,这种网络也被称为前馈神经网络

NNet模型相比于其它机器学习算法而言,其优势在于自动特征提取(但是数据质量仍然要保证)。通过多层感知器的叠加,模型可以自动提取数据中的关联关系并进行数据拟合,因此NNet可以被广泛应用在图像识别、声纹识别、NLP等数据特征不容易人为提取的应用领域。

激活函数

任何一个在定义域内连续的函数都能成为激活函数(或称转换函数)的备选项。之所以要求函数连续,是因为我们希望在应用类似梯度下降(gradient descent)算法进行训练的时候能够计算损失函数的梯度(依赖于微分计算)从而指引优化方向,而不连续的函数将在不连续的区间内给梯度计算带来不必要的麻烦。比较常见的激活函数包括logistic函数、tanh等。

同时,激活函数一般要求是非线性的,以实现非线性逻辑,否则N个线性组合的线性组合产生的结果仍将是一个线性变换能够实现的效果。

优点

  • 自动特征提取
  • 模拟线性或非线性逻辑

缺点

  • 训练成本随着网络层数增加而增加
  • 模型可解释性差
  • 可能陷入局部最优解

深度神经网络(Deep Neural Network)

本文只简要介绍深度神经网络(下称DNN)的结构,关于DNN的训练将会另外写一篇文章论述。

上图就是DNN的基本结构,真实的DNN可能拥有更多的隐藏层。每一个隐藏层其实都是一轮数据特征的提取,随着层数的增加,提取的特征也就越加丰富,直到最后一层高级特征用来做最终判断。

但是DNN也并不简单是多层网络的叠加,和传统NNet不同的是它的预训练过程。为了缓解NNet中的局部最优解问题,预训练通过训练数据的自表征(self-representation)来获取DNN的初始权重,而不是采用NNet中的随机赋值方法。这种训练自表征的机制又被称为自编码器(auto-encoder),优秀的自编码器能够让DNN在一个靠近全局最优解的位置开始梯度下降的训练,同时减少数据噪声的干扰。良好的预训练过程也能够使得后面的权重微调过程更快地收敛。

优点

  • 所有NNet的优点
  • 减少数据噪声的影响
  • 缓解局部最优解问题

缺点

  • 模型可解释性差
  • 需要比较大的算力支持

前馈神经网络的学习

前馈神经网络的学习依赖于一种叫做梯度下降的算法(及其变种,比如随机梯度下降)进行每一层神经元权重的学习。由于最终的训练结果与每一层神经元的权重相关,因此如何将预测误差合理分配到每个权重上就成了一个困难。这个困难曾经阻碍了NNet的发展,直到后向传播算法的出现。下面这一部分将重点介绍前馈神经网络中各神经元权重的学习过程。

变量定义

神经元层数:$$L \in \mathbb{N}^+$$

第l层第j个神经元的得分:$$s_j^{(l)}$$

激活函数:$$f(s)$$

输出标签:$$y \in \mathbb{R}$$

以权重矩阵W为参数的假设函数:$$h_W(X)$$

第n个数据的预测误差(本文使用平方误差作为损失函数):$$e_n = (y_n - h_W(X_n))^2$$

第n个数据的预测误差在第l层第i个参数的第j个神经元上的梯度:$$\triangledown h_W(X_n) = \frac{\partial e_n}{\partial w_{ij}^{(l)}}$$

后向传播(Backpropagation)

后向传播算法基于一种最直观的判断,即最终的预测误差是由上一层的计算直接导致的,而这一层的运算又是由之前一层的运算得出的,因此最终的错误责任应该可以从后往前推算,从而将错误的责任按照一定的规则分配到不同的神经元上。为此,我们先来看输出层(假设只有一个神经元)的梯度如何计算。

输出层梯度

使用平方误差,预测误差可以写成如下形式:

$$e_n = (y_n - h_W(X_n))^2 = (y_n - s_1^{(L)})^2 = (y_n - \sum_{i=0}^{d^{(L - 1)}}w_{i1}^{(L)}x_i^{(L-1)})^2$$

那么损失函数在输出层权重上的微分可以应用链式法则推导如下:

$$\delta_1^{(L)} = \frac{\partial e_n}{\partial w_{i1}^{(L)}} = \frac{\partial e_n}{\partial s_{1}^{(L)}} \cdot \frac{\partial s_1^{(L)}}{\partial w_{i1}^{(L)}} = 2(y_n - s_1^{(L)}) \cdot (x_i^{(L-1)})$$

一般情况的梯度

由上式进行泛化推导,可以得到如下的更一般的梯度计算方法:

$$\frac{\partial e_n}{\partial w_{ij}^{(l)}} = \frac{\partial e_n}{\partial s_{j}^{(l)}} \cdot \frac{\partial s_j^{(l)}}{\partial w_{ij}^{(l)}} = \delta_j^{(l)} \cdot (x_i^{(l-1)})$$

$\delta_1^{(L)}$已经在上一节获取到了,那么为了获取剩下的所有$\delta$值,我们要来看一下权重的传递关系:

$$s_j^{(l)} \stackrel{f}{\Longrightarrow} x_j^{(l)} \stackrel{w_{jk}^{(l)}}{\Longrightarrow} s^{(l+1)} \Longrightarrow \cdots \Longrightarrow e_n$$

第l层的分数经过激活函数转换后得到本层的输入,再与本层的权重进行线性组合得到下一层的分数,以此演进,直到最后输出。因此,一般的$\delta$的计算也可以通过使用链式法则得到:

$$\delta_j^{(l)} = \frac{\partial e_n}{\partial s_j^{(l)}} = \sum_{k=1}^{d^{(l+1)}} \frac{\partial e_n}{\partial s_k^{(l+1)}} \cdot \frac{\partial s_k^{(l+1)}}{\partial x_j^{(l)}} \cdot \frac{\partial x_j^{(l)}}{\partial s_j^{(l)}} = \sum_{k=1}^{d^{(l+1)}} (\delta_k^{(l+1)}) \cdot (w_{jk}^{(l)}) \cdot (f’(s_j^{(l)}))$$

所以,从输出层的$\delta$开始,我们可以通过层层回溯计算出每一层的梯度值。有了梯度之后,新的权重可以更新如下($\eta$为学习步长):

$$w_{ij}^{(l)} \leftarrow w_{ij}^{(l)} - \eta x_i^{(l-1)}\delta_j^{(l)}$$

经过多轮迭代之后,NNet的权重矩阵将会收敛到一个稳定的值附近,此时的权重矩阵就可以作为模型的最终训练结果了。

优化

NNet模型的训练存在某些问题,可能导致最终得到的模型的预测效果并不理想。下面浅列一些最常遇到的问题以及应对的办法。

局部最优问题

NNet模型的损失函数往往并不能保证是凸函数,因此往往存在多个局部最优解,即使使用梯度下降的方法也很难找到全局最优解。为了缓解这个问题,一般NNet的训练会要求使用若干随机的初始权重矩阵(矩阵中的值都比较小以避免过早梯度饱和),并且训练多个模型进行效果比较。

过拟合(Overfit)与正则化(Regularization)

NNet模型是一个强大的模型,只要神经元数量和层数越多,它对原始数据集的拟合程度就会越高,于是造成过拟合的问题,使得模型不能很好地应用到外部数据集上。为了解决这个问题,我们往往会在损失函数中引入正则项来“压缩”权重,防止过拟合。NNet中一般使用$L_2$正则来保证损失函数可微:

$$L_2 = \sum(w_{ij}^{(l)})^2$$

并且在实践中,更多使用基于$L_2$的权重消除正则方法使得小权重能够被缩减为0:

$$\sum \frac{(w_{ij}^{(l)})^2}{1 + (w_{ij}^{(l)})^2}$$

与此同时,NNet的训练还会采用提前终止(early stopping)的策略在适当的迭代次数后停止训练,防止过拟合。

后记

NNet模型是一个庞大的门类,本文介绍的前馈网络只是其中一种,还有反馈神经网络等其它类型的神经网络模型存在。但是随着深度学习的普及,前馈神经网络及其衍生模型开始大行其道,DNN在诸多领域中的成功应用也向人们昭示了这一模型的强大力量。这一篇简短的文章和训练推导过程既帮助我自己复习巩固所学,也希望能够帮到更多人了解并进一步掌握NNet模型的理论基础和一些实践技巧。

文章目录
  1. 1. 总述
  2. 2. 演进
    1. 2.1. 感知器(Perceptron)
      1. 2.1.1. 优点
      2. 2.1.2. 缺点
    2. 2.2. 类神经网络(Artificial Neural Network)
      1. 2.2.1. 激活函数
      2. 2.2.2. 优点
      3. 2.2.3. 缺点
    3. 2.3. 深度神经网络(Deep Neural Network)
      1. 2.3.1. 优点
      2. 2.3.2. 缺点
  3. 3. 前馈神经网络的学习
    1. 3.1. 变量定义
    2. 3.2. 后向传播(Backpropagation)
      1. 3.2.1. 输出层梯度
      2. 3.2.2. 一般情况的梯度
    3. 3.3. 优化
      1. 3.3.1. 局部最优问题
      2. 3.3.2. 过拟合(Overfit)与正则化(Regularization)
  4. 4. 后记
|