在机器学习中,神经网络(neural networks)一般是指“神经网络学习”。所谓神经网络,目前用得最广泛的一个定义是“神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所做出的反应”。它是一种黑箱模型,解释性较差,但效果很好。目前已有一些工作尝试改善神经网络的可解释性。
这一章的内容大致如下:
-
神经元模型:什么是神经元模型?它的构造是怎样的?激活函数是什么?如何组建神经网络?
-
感知机与多层网络:感知机的构造是怎样的?感知机不能解决什么问题?多层网络是怎样的?多层前馈神经网络有什么特点?
-
误差逆传播算法:BP算法如何调整参数?有什么值得注意的地方?标准BP算法和累积BP算法有什么区别?如何设置隐层神经元的个数?如何处理BP神经网络的过拟合问题?
-
全局最小与局部极小:什么是全局最小?什么是局部极小?如何跳出局部极小?
-
其他常见神经网络:有哪些常见的神经网络?它们各自有什么特点?什么是竞争型学习?可塑性、稳定性、增量学习、在线学习各指什么?
-
深度学习:深度学习是如何提升模型容量的?如何训练深度神经网络?怎么理解深度学习?
神经元(neuron)模型是神经网络最基本的组成成分,不妨对比一下生物学中的神经元和机器学习中的神经元:
在生物学中,每个神经元都有多个树突(dendrite),一个轴突(axon),以及一个细胞体(cell body)。当它兴奋时,就会向相连的神经元发送化学物质,从而改变它们内部的电位。如果一个神经元的电位超过了阈值(threshold,也称bias),那它就会被激活,也即兴奋,继而向其他相连神经元发送化学物质。
在机器学习中,最常用的是右图的M-P神经元模型(亦称为阈值逻辑单元(threshold logic unit))。树突对应于输入部分,每个神经元接收到若干个来自其他神经元的输入信号,这些信号通过带权重的连接(connection)传递给细胞体,这些权重又称为连接权。细胞体分为两部分,前一部分计算总输入值(即输入信号的加权和,或者说累积电平);后一部分先计算总输入值与该神经元的阈值的差值,然后通过**激活函数(activation function)**的处理,从轴突输出给其它神经元。也即:
最理想的激活函数是阶跃函数,但它不连续。类似于线性分类,可以采用Sigmoid函数来近似。因为这类函数能把较大范围内变化的输入值挤压到 (0,1) 输出值范围内,所以也称为挤压函数(squashing function)。
将多个神经元按一定的层次结构连接起来,就得到了神经网络。它是一种包含许多参数的模型,比方说10个神经元两两连接,则有100个参数需要学习(每个神经元有9个连接权以及1个阈值)。若将每个神经元都看作一个函数,整个神经网络就是由这些函数相互嵌套而成。
**感知机(Perceptron)**仅由两层神经元组成,如下图:
两层是指输入层和输出层,但只有输出层是M-P神经元,也即只有一层功能神经元(functional neuron)。输入层只负责把每一个样本的各个属性传递给输出层(输入层的神经元数量等于样本的属性数目),不进行函数处理。其实说白了这个模型跟逻辑回归是一样的,不过按我的理解就是感知机的输出层可以有多个神经元,产生多个输出。而且线性模型中偏置项是和属性一起加权求和的,但神经网络中则是求属性加权和和预测的差。
有时候阈值
其中,$\eta$ 称为学习率(learning rate),取值范围是 (0,1)。感知机是逐个数据点输入来更新的。设定初始的权重后,逐个点输入,如果没有预测错就继续检验下一个点;如果预测错了就更新权重,然后重新开始逐个点检验,直到所有点都预测正确了就停止更新(所以这其实是一种最小化经验误差的方法)。
已经证明了,若两类模式是线性可分(linearly separable)的,即存在一个线性超平面能将它们分开。比如二维平面上可以用一条直线完全分隔开两个类别的点。由于感知机只有一层功能神经元,所以学习能力极其有限,只能处理线性可分问题。对于这类问题,感知机的学习过程必然收敛(converge)而求出适当的权向量;对于线性不可分问题,感知机的学习过程会发生振荡(fluctuation),难以稳定下来。
使用多层的功能神经元可以解决线性不可分问题,比方说两层(功能神经元)的感知机就可以解决异或问题(在二维平面中需要使用两条直线才能分隔开)。在输入层和输出层之间的层称为隐层或者隐含层(hidden layer),隐含层的神经元也是功能神经元。
上图展示的最为常见的多层神经网络——多层前馈神经网络(multi-layer feedforward neural networks),它有以下特点:
- 每层神经元与下一层神经元全互连
- 神经元之间不存在同层连接
- 神经元之间不存在跨层连接
因为说两层网络时容易有歧义(只包含输入层输出层?还是包含两层功能神经元?),所以一般称包含一个隐含层的神经网络为单隐层网络。只要包含隐层,就可以称为多层网络。神经网络的学习其实就是调整各神经元之间的**连接权(connection weight)**以及各神经元的阈值,也即是说,神经网络学到的东西都蕴含在连接权和阈值中了。
训练多层网络要比感知机复杂多了,感知机的学习方法是不够的。误差逆传播算法(error BackPropagation,简称BP)也称为反向传播算法,是最为成功的一种神经网络学习方法之一。一般而言,BP神经网络是指用BP算法训练的多层前馈神经网络,但BP算法也能训练其他类型的神经网络,如递归神经网络。
假设要训练的是一个单隐层的前馈神经网络,BP算法使用均方误差作为性能度量,基于**梯度下降(gradient descent)**策略,以目标函数的负梯度方向对参数进行调整。
流程如下:
输入:训练集 $D = {(\mathbf{x}_k,\mathbf{y}k)}^m{k=1}$,学习率
过程:
1:在
2:$\mathbf{repeat}$
3:$\quad$
4:$\quad$
5:$\quad$
6:$\quad$
7:$\quad$
8:$\quad$
9:$\mathbf{until}$ 达到停止条件
输出:连接权与阈值确定的多层前馈神经网络
所谓逆传播其实就是从输出层开始逐步往后更新,因为输出层的误差确定后就可以对输出层的连接权和阈值进行更新,并且可以推算出隐含层输出的“真实值”,从而计算出隐含层的“误差”,然后更新隐含层的连接权和阈值。BP就是这样一种利用一层层倒推来最终更新整个神经网络的方法,每一层的更新公式其实和感知机用的是类似的。
在学习过程中,学习率
BP算法的目标是最小化训练集
而标准BP算法每输入一个样例就进行一次更新,所以它的参数更新非常频繁,而且不同样例可能会对更新起到抵消效果,从而使得模型需要更多次迭代才能到达累积误差的极小点。
标准BP算法和累积BP算法的区别类似于随机梯度下降和标准梯度下降的区别。
如果把更新方式变为每输入一遍训练集进行一次更新,就得到累积BP算法,更新公式需要重新推导一下。这样更新一次就称为**一轮(one round,亦称one epoch)**学习。
使用累积BP算法时参数更新的频率要低得多,但是!在很多人任务中,累积误差在下降到一定程度后,进一步下降会非常缓慢。此时标准BP算法能更快地获得较好的解(特别是训练集
已证明只需一个包含足够多神经元的隐层,多层前馈神经网络就能以任意精度逼近任意复杂度的连续函数。那么该怎样设置隐层神经元的个数呢?并不是越多越好,因为可能会出现过拟合问题而得不偿失。
目前尚未有成熟的理论可以确定怎样设置隐层神经元的个数还有隐层的层数。实际应用中主要靠**试错法(trial-by-error)**来调整,也即是不断改变设置,试验模型给出的应答,然后选择结果最好的。
鉴于BP神经网络强大的表达能力,很容易会遇到过拟合问题。主要有以下两种应对策略:
-
早停(early stopping):把数据集分为训练集和验证集,若训练集误差降低但测试集误差升高,就停止训练,并返回具有最小验证集误差的连接权和阈值。
-
正则化(regularization):在目标函数中添加一个用于描述网络复杂度的部分,比如连接权和阈值的平方和。这样训练时就会偏好较小的连接权和阈值,从而令输出更“光滑”。为什么可以用正则化来避免过拟合呢?可以看看知乎上的解答。带正则化项的目标函数如下:
其中
学习模型的过程其实就是一个寻找最优参数的过程,在谈到最优时,一般会提到局部极小(local minimum)和全局最小(global minimum)。
- 局部极小解:参数空间中的某个点,其邻域点的误差函数值均不小于该点的误差函数值。
- 全局最小解:参数空间中的某个点,所有其他点的误差函数值均不小于该点的误差函数值。
这两个解对应的误差函数值分别成为局部最小值和全局最小值。
要成为局部极小,只要满足该点在参数空间中梯度为0就可以了。局部极小可以有多个,全局最小则只有一个。全局最小一定也是局部极小,反之则不成立。
因为用梯度下降搜索最优解可能会陷入非全局最小解的局部极小解,在现实任务中,人们会使用以下这些策略试图跳出局部极小:
-
以多组不同参数值初始化多个神经网络:经过训练后,取误差最小的解作为最终参数。这种方法相当于从多个不同的初始点开始搜索,从而增加找到全局最小解的可能性。
-
**模拟退火(simulated annealing)**技术:每次迭代都以一定的概率接收比当前解差的结果,从而有机会跳出局部极小(当然也有可能跳出全局最小),每次接受“次优解”的概率会随着时间推移逐渐减小,从而保证了算法的稳定。
-
随机梯度下降(stochastic gradient descent,简称SGD):在计算梯度时加入了随机因素,因此即便陷入局部极小点,梯度依然可能不为0,从而有机会跳出局部极小,继续搜索。
除了这些方法之外,遗传算法也常用于训练神经网络以逼近全局最小。当这些技术大多是启发式,没有理论的保障。也就是说,这些方法指示基于直观或者经验构造的,能在可接受的时间和空间花费下给出待解决的组合优化问题的一个可行解,但不能估计可行解与最优解的偏离程度。
RBF(Radial Basis Function)网络是一种单隐层前馈神经网络,它使用径向基函数作为隐层神经元的激活函数。输出层则直接使用隐层神经元的线性组合。
竞争型学习(competitive learning)是神经网络中常用的一种无监督学习策略。使用该策略时,网络中的输出神经元相互竞争,每次只有一个竞争获胜的神经元被激活,其它输出神经元被抑制,这种机制又称为胜者通吃(winner-take-all)。
ART(Adaptive Resonance Theory,自适应谐振理论)网络是竞争型学习的重要代表。该网络由四部份组成:比较层、识别层、识别阈值、重置模块。比较层就是输入层,只负责把样本传递给识别层。识别层也即输出层,但识别层的每个神经元对应一个模式类,而且神经元的数目可以在训练过程中动态增加以增加新的模式类。
识别层的每个神经元有一个对应的模式类的代表向量,每次输入一个样本,各识别层神经元相互竞争,代表向量与样本距离最小的胜出并被激活。获胜神经元会向其他神经元发送信号,抑制其激活。如果样本与获胜神经元的距离小于识别阈值,则被分到对应的模式类。否则,重置模块会在识别层新增一个神经元,代表向量为该样本。
ART能有效缓解竞争型学习中的可塑性-稳定性窘境(stability-plasticity dilemma)。可塑性指神经网络要有学习新知识的能力,稳定性则指神经网络在学习新知识时要保持对旧知识的记忆。
ART具备可塑性和稳定性,因此能进行增量学习(incremental learning)和在线学习(online learning)。
增量学习可以理解为建立模型后再收到新的样例时可以对模型进行更新,但不用重新训练整个模型,先前学得的有效信息会被保存。它可以逐个新样例进行更新,也能以批模型(batch-mode),每次用一批新样例来更新。
在线学习则可以理解为每拿到一个新样本就进行一次模型更新,不需要一开始就准备好完整的训练集,每次收到新样例都能继续训练。可以看作增量学习的一个特例。
SOM(Self-Organizing Map,自组织映射)网络,又称为自组织特征映射网络或Kohonen网络。同样是一种竞争学习型无监督神经网络,只有输入层和输出层两层,输出层以矩阵形式排列。与样本距离最近的输出层神经元获胜,称为最佳匹配单元(best matching unit)。最佳匹配单元和邻近神经元的权向量会被调整,使得下次遇到相似的样本时距离更小。如此迭代,直至收敛。
级联相关(Cascade-Correlation)网络是一种典型的结构自适应网络,这类网络不仅通过训练来学习合适的连接权和阈值等参数,还会在训练过程中找到最符合数据特点的网络结构。
级联相关神经网络有两个主要成分:
-
级联:指建立层次连接的层级结构。开始训练时,只有输入层和输出层,随着训练进行逐渐加入隐层神经元,从而建立层级结构。注意,隐层神经元的输入端连接权是冻结固定的。
-
相关:指通过最大化新神经元的输出与网络误差之间的相关性(correlation)来训练相关的参数。
递归神经网络(recurrent neural networks,简称RNN)允许网络中出现环形结构,即一些神经元的输出可以反馈回来当输入信号,从而能够处理与时间有关的动态变化。
Elman网络是最常用的递归神经网络之一,只有一个隐层,并且隐层神经元的输出会被反馈,在下一时刻与输入层神经元的输入信号一起作为隐层神经元的新输入。隐层神经元一般采用Sigmoid函数作为激活函数,并用BP算法训练整个网络。
神经网络中有一类基于能量的模型(energy-based model),把网络状态定义为一个能量,能量最小时网络达到理想状态,模型的学习过程就是最小化能量函数。Boltzmann机就是这样的模型,同时也是一种RNN。
Boltzmann机的神经元分为显层与隐层,显层用于表达数据的输入与输出,隐层则是数据的内在。每个神经元只有0、1两种状态,也即抑制和激活。
标准的Boltzmann机是全连接图,即任意两个神经元之间都相连。但复杂度太高,难以用于解决现实任务,实际应用中用的是受限Boltzmann机(Restricted Boltzmann Machine,简称RBM),把标准Boltzmann机退化为二部图,只保留显层和隐层之间的连接,同一层直接不相连。
理论上,参数越多,模型复杂度就越高,**容量(capability,第12章中会讲到)**就越大,从而能完成更复杂的学习任务。**深度学习(deep learning)**正是一种极其复杂而强大的模型。
怎么增大模型复杂度呢?两个办法,一是增加隐层的数目,二是增加隐层神经元的数目。前者更有效一些,因为它不仅增加了功能神经元的数量,还增加了激活函数嵌套的层数。但是对于多隐层神经网络,经典算法如标准BP算法往往会在误差逆传播时发散(diverge),无法收敛到稳定状态。
那要怎么有效地训练多隐层神经网络呢?一般来说有以下两种方法:
-
无监督逐层训练(unsupervised layer-wise training):每次训练一层隐结点,把上一层隐结点的输出当作输入来训练,本层隐结点训练好后,输出再作为下一层的输入来训练,这称为预训练(pre-training)。全部预训练完成后,再对整个网络进行微调(fine-tuning)训练。一个典型例子就是深度信念网络(deep belief network,简称DBN)。这种做法其实可以视为把大量的参数进行分组,先找出每组较好的设置,再基于这些局部最优的结果来训练全局最优。
-
权共享(weight sharing):令同一层神经元使用完全相同的连接权,典型的例子是卷积神经网络(Convolutional Neural Network,简称CNN)。这样做可以大大减少需要训练的参数数目。
事实上,深度学习可以理解为一种特征学习(feature learning)或者表示学习(representation learning),无论是DBN还是CNN,都是通过多个隐层来把初始与输出目标联系不大的输入表示转化为与输出目标更密切的表示,使原来只通过单层映射难以完成的任务变为可能。也即通过多层处理,逐渐将初始的“低层”特征表示转化为“高层”特征表示,从而使得最后可以用简单的模型来完成复杂的学习任务。
传统任务中,样本的特征需要人类专家来设计,这称为特征工程(feature engineering)。特征好坏对泛化性能有至关重要的影响。而深度学习为全自动数据分析带来了可能,可以自动产生好的特征。
问:试述将线性函数$f(\mathbf{x}) = \mathbf{w}^T\mathbf{x}$ 用作神经元激活函数的缺陷。
问:试述使用对数几率函数作为激活函数的神经元与对率回归的联系。
问:对于图5.7中的$v_{ih}$,试推导出BP算法中的更新公式(5.13)。
问:试述式(5.6)中学习率的取值对神经网络训练的影响。
问:试编程实现标准BP算法和累积BP算法,在西瓜数据集3.0上分别用这两个算法训练一个单隐层网络,并进行比较。
问:试设计一个BP改进算法,能通过动态调整学习率显著提升收敛速度。编程实现该算法,并选择两个UCI数据集与标准BP算法进行实验比较。
问:根据式(5.18)和(5.19),试构造一个能解决抑或问题的单层RBF神经网络。
问:从网上下载或自己编程实现SOM网络,并观察其在西瓜数据集3.0$\alpha$上产生的效果。
问:试推导用于Elman网络的BP算法。
问:从网上下载或自己编程实现一个卷积神经网络,并在手写字符识别数据MNIST上进行实验编程。