人工神经网络也称为类神经网络,是由众多人工神经元相互连接而组成的。根据组成结构的不同,它主要分为前馈(feedforward)和反馈(feedback)两种类型。
前馈型人工神经网络也称为多层感知机(MLP,multi-layer perceptron),神经元从输入开始,每一层神经元接收前一级的输入并输出到下一级,直至输出层,网络结构中没有反馈,是一种单向多层的结构。通常将和外界输入相连的第一层称为输入层,将输出结果的最后一层称为输出层,将其他中间所有层统一称为隐藏层或中间层。
在反馈型人工神经网络中,神经元从输出到输入还具有反馈连接,比如Elman神经网络、Jordan神经网络、Hopfield神经网络等,系统的下一个状态输出取决于当前输入以及当前状态,这在需要关注上下文时,或者在有关时间序列的计算中是非常有用的。反馈型人工神经网络具有类似大脑的联想记忆功能。比如语音识别中,如果识别出们“mén”这个音,可能无法判断是“门”还是“们”,但如果结合前面的音是“wǒ”,就很容易识别出应该是“我们”这两个字了。当然,如果上下文是“他叫住了我,门开了”,要识别出是“我”和“门”这两个字,引入记忆功能就更容易做到。这一类反馈型人工神经网络又称为时间递归神经网络(RNN,recurrent neural network),也称为循环神经网络。需要注意的是,还有一种结构上递归的神经网络(RNN,recursive neural network),缩写形式和时间递归神经网络相同,它主要是一种采用树状结构的神经网络,目前相比循环神经网络还未体现出明显的优势,仍然是一个开放的研究领域。当提到递归神经网络时,应该指这两种结构,只是因为时间递归循环网络及其变种目前应用领域更广,所以RNN有时主要指时间递归神经网络。
这里主要介绍前馈型人工神经网络。它是其他各种结构的人工神经网络的基础。图4.26所示为一个基本的全连接型前馈型人工神经网络示意图。所谓全连接,是指相邻两层神经元之间任意2个神经元节点都是连接的。
图4.26 全连接型前馈型人工神经网络示意图
神经网络可以看作是一个在权重w和偏置b参数下,对输入X求输出f(X)的函数。比如,在手写数字识别中,数据集MINST中的数据是一个784(=28×28)像素的灰度图像,可以将这784个值作为输入X,而输出则是0~9这10个数字的分类结果。那么,对于输入层来说,就需要784个神经元来接收784个像素点的值,而输出层则应该有10个神经元,对应着10种不同类别的数字。
显然,对于某一个输入X,输出f(X)和真实的结果Y越接近,表示识别越准确,模型的健壮性越好。这样,就可以定义一个损失函数(loss function),L(Y,f(X)),用来衡量模型的输出和真实值的不一致程度。比如,可能会想到使用欧氏距离来进行度量——平方损失函数就采用了该方法。事实上,由于样本的分布不同以及对于计算的需求不同等因素,有着许多不同类型的损失函数可以用来衡量模型的输出和真实值之间的差异。损失函数的值越小,说明输出和真实值越接近。
在监督学习中,用于学习的数据及其对应的结果(又称标签)是已知的。所谓神经网络的学习或者训练过程,就是调整权重w以及偏置b(下面统一称为θ),使得损失函数的值达到最小的过程。但是由于训练数据集中的数据很多,因此更希望使平均损失最小化。在前面介绍支持向量机时提到过,训练好的分类器对训练数据分类得到的误差称为经验风险,对应的风险函数(risk function)就可以理解为损失函数的期望,一般称为代价函数(cost function),表示对所有训练数据的平均误差,所以训练的目标这时就变成了最小化经验风险,即最小化C(θ):
但是,是否经验风险最小就是最好呢?答案是否定的,因为还存在着过拟合的问题,即对训练数据拟合得非常好,可是预测时效果不太好。欠拟合、合适拟合、过拟合示意图如图4.27所示。
图4.27 欠拟合、合适拟合、过拟合示意图
过拟合和欠拟合是机器学习中很重要的两个概念。在学习和训练一个模型时,采用的方法是针对训练数据使输出误差最小。但训练的目的并不是针对已知数据,而是希望能找到相关领域的一般化问题的解。然而,通过数据集学习到的模型和真实模型之间是有差距的。训练数据集的误差和一般数据集的误差之间的差异,称为泛化误差(generalization error)。泛化误差由偏差(bias)、方差(variance)和噪声(noise)三个部分组成。偏差反映了学习算法本身的拟合能力,方差反映了数据变动造成的影响,噪声则反映了学习问题本身的难度。偏差反映的是训练数据和真实结果之间的差异,而方差反映的是相同分布的不同训练数据与真实结果之间的差异。图4.28反映了两者之间的关系,其中靶心代表真实值。
图4.28 偏差和方差示意图
过拟合意味着在训练数据集上具有高方差和低偏差,导致模型的泛化能力不佳。欠拟合容易导致低方差和高偏差。偏差和方差往往存在冲突,需要进行权衡。
如果过于追求模型对训练数据的预测能力,就可能导致获得的模型复杂度比真实模型更大,从而发生过拟合。容易导致过拟合的因素还有训练数据较少、噪声干扰过大等。
为了防止出现过拟合,一种方法就是避免模型太复杂,也就是使结构风险最小。这时,我们可以定义一个函数Φ(θ)来度量模型的复杂度。该函数又称为正则化项(regularizer term)或惩罚项(penalty term)。它一般是参数θ中权重w的L1-范数或L2-范数的平方除以2。参数θ中权重w的L1-范数和L-2范数的平方除以2分别叫L1正则项和L2正则项。
这样,神经网络的训练就变成了找到使目标函数(代价函数+正则化项)最小化的θ值,即:
其中,λ∈[0,∞),用来权衡代价函数和正则化项在目标函数中所占的比例。如果λ=0,就表示没有正则化项部分,神经网络训练过程就变成了让代价函数最小化。λ越大,正则化项部分所占比重就越大。当目标函数取L1正则化项时,;当取L2正则化项时,
常用的损失函数如下。
(1)平方损失(square loss)函数。
平方损失也称为均方误差,为了求导计算方便,没有计算平均,改为乘以1/2。
(2)交叉熵损失(cross entropy loss)函数。
如果将真实的输出Y理解为一种概率分布,那么训练的过程就是希望在输入样本为X的情况下,输出概率和真实概率一致。如果用P(Y|X)表示样本X在分类为Y的情况下的概率,那么显然这里希望调整参数,使得P(Y|X)最大化,也可以理解为通过已知样本来训练模型的参数,找到在已知样本分布情况下,最有可能产生对应Y分布的参数值。而作为损失函数,则是希望调整参数θ后,P(Y|X)和Y的差异达到最小,所以,引入交叉熵损失函数。交叉熵和熵的定义相似,只是交叉熵定义在两个概率分布之上,反映了它们之间的差异程度。当两个概率分布相等时,交叉熵取得极小值。交叉熵损失函数定义为
其中:yic为样本i的分类标签;pic为每一类别的预测输出值,因为通常会用softmax函数作为最后的输出,所以结果类似概率的形式。
由于在分类任务中,只有正确类别的标签为1,其他类别的标签都是0,因此在计算时,只需要计算正确分类那一项的输出的自然对数的负值即可。比如,在手写数字识别中,如果输入的图像是3,对应的输出是0.5,那么交叉熵损失为:-ln0.5=0.693。
交叉熵损失函数Python代码实现参考如下:
其中,delta的定义是为了防止出现f_x=0的情况,此时求对数将会得到负无穷。y为NumPy数组存储标签,f_x数组存储输出,返回值为损失值。
损失函数确定后,代价函数就可以看作是损失函数的期望,可以定义为
其中,N为样本数,M为分类数,yic为样本的分类标签,pic为每一类的预测输出值。
特别地,对于二分类问题,如果预测样本i为正样本的概率为pi,则有
后面还将介绍在神经网络中激活函数使用sigmoid函数或softmax函数,损失函数使用交叉熵损失函数,还能进一步减少学习和训练过程中的计算量,加速收敛过程。
(3)铰链损失(hinge loss)函数。
铰链损失的思想是希望让属于某一类和不属于这一类的距离达到一个最大间隔Δ,如果在M个类别中,属于这一类的输出一个数值f作为分数,不属于这一类的输出为f',则当f和f'的差距超过Δ时,就认为两者都正确分类了,误差记为0,否则就累积计算两者的差值f'-f和Δ的差距。通过训练,使得总误差为0,也就是将不同类别的差距都至少保持在Δ之上。这样,既通过调整权值来使所有不同的类别尽可能分开,同时又不希望过大的差距数值对整体训练带来影响,所以只关注间隔没达到Δ的类别。它主要用于最大间隔(maximum margin)算法中。最大间隔算法是支持向量机支持向量机中的主要算法,所以该损失函数在支持向量机中较常用。铰链损失函数的定义为
其中,求和符号表示所有预测错误的类的分数按照公式进行累加。
例4.7 某神经网络用于识别猫、狗、猪三种动物的图片,使用铰链损失函数作为损失函数,现在输入一张猫的图片时,经过该神经网络在这三类下的输出分数分别为12,11,-5,假设Δ=10,计算此时损失函数的输出值。
解 由式(4.54),得
L=max(0,11-12+10)+max(0,-5-12+10)=9+0=9
所以得到此时损失函数的输出值为9。
对于多样本训练,通常是求损失函数的期望,也就是代价函数再加上正则化项,就是目标函数。
铰链损失函数还有其他一些变体形式,比如在二分类问题中,定义为
其中,y为标签值,常用-1或+1。
当预测为1时,函数图形如图4.29所示。因和铰链形状相似,故名为铰链损失。
图4.29 铰链损失和0-1损失示意图
也有人(Weston和Watkins)提出不用所有分类错误预测分数的累加而改用错误分类预测的最大值作为损失,即
铰链损失函数是一个凸函数(convex function),适用于机器学习的所有凸优化中。虽然该函数不可微,但是可以分段求其梯度:
确定了损失函数以后,接下来就是解决如何对神经网络的参数进行训练这个问题了。对于神经网络的训练,就如同是在搜索过程中,以参数的初始值作为初始状态,以调整参数的值作为算符,将能使损失函数取得最小值的参数作为目标状态,在评估函数的指引下,尽快到达目标状态。这个过程和第3章中的爬山法搜索类似,爬山法搜索要找到极大值,所以选择的是沿着梯度上升的方向;这里要尽快使损失函数取得最小值,所以应该是采用沿着梯度下降的方向,也就是采用梯度下降法(gradient descent method)或最速下降法(steepest descent method)。
在微积分里面,对多元函数的各个变量参数求偏导数,把求得的偏导数以向量的形式写出来,就是梯度。比如对于函数f(x,y),分别对x,y求偏导数,求得的梯度向量就是(∂f/∂x,∂f/∂y)T,写作grad f(x,y)或者f(x,y)。对应在点(x0,y0)的具体梯度向量就是(∂f/∂x0,∂f/∂y0)T或者f(x0,y0)。如果是3个参数的向量梯度,就是(∂f/∂x,∂f/∂y,∂f/∂z)T,以此类推。
从几何意义上来说,函数的梯度方向就是函数增加最快的方向。比如,对于函数f(x,y),在点(x0,y0),沿着梯度向量(∂f/∂x,∂f/∂y)T的方向,f(x,y)增加最快。也就是说,沿着梯度向量,会更快找到函数的最大值。反过来说,沿着梯度向量相反的方向,也就是-(∂f/∂x0,∂f/∂y0)T的方向,函数值减小最快,将会更容易找到函数的最小值。
在神经网络的训练过程中,就是希望通过逐步调整参数,找到使损失函数(目标函数)达到最小的参数值。这个时候,就可以沿着梯度减小的方向来迭代调整参数值,直到梯度减小为0,损失函数达到极小值。此时,有可能找到的是局部最小值,而不是全局最优解,所以我们需要限定损失函数为凸函数,这样就能保证找到全局最优解。
调整参数时,有一个很重要的概念就是学习速率(learning rate,也称为步长)。它决定了在沿着梯度下降的方向迭代的过程中,每一步沿梯度负方向前进的长度。参数θ调整的一般公式为
θ=θ-lr·θJ(θ) (4.58)
其中,lr表示学习速率,J(θ)为目标函数。
例4.8 使用梯度下降法调整x参数,使得函数y=x2取得最小值。
解 首先定义函数及其一阶导数:
让x以沿梯度负方向以一定的步长,即学习速率进行调整。
为了作图方便,程序的返回值是一个列表,该列表记录了每次调整后的x值。如果设置学习速率lr=0.3,x初始值为5,调整15次,则调整过程如图4.30(a)所示,可以看到x值很快靠近到能使函数取得极小值的点。图4.30(b)和(c)所示分别为学习速率设置得较大(lr=0.7)以及较小(lr=0.05)两种情况下的调整过程。(参考代码c4/s4_3/s4_8_GD01.py。)
(www.xing528.com)
图4.30 梯度下降法调整过程示意图
可以看到,如果学习速率设置得较大,则可能会出现步长过大,导致来回振荡甚至无法收敛的问题;而如果学习速率太小,则可能导致收敛速率太慢,迭代很多次后还没有到达极小值处。所以,通常会选一个较小的值来测试,逐渐增大学习速率进行调整。也可以通过判断损失函数每一次迭代后值下降的程度来判断是否已经趋于收敛状态。
更一般地,可以对学习速率增加一个衰减因子,使学习速率随着迭代次数的增加而自动逐渐减小。比如:“lr_i=lr*1.0/(1.0+decay*i)”,其中,“decay”为衰减因子,“i”为迭代次数,用“lr_i”代替“lr”作为学习速率用于参数调整。(参考代码c4/s4_3/GD02.py。)
另外一种对学习速率的改进方法是引入动量(momentum)参数,在相同方向的参数调整过程中,加快学习速度,而当发生方向改变时,降低学习速度。具体做法是:调整参数时,结合参数上一次的状态,比如采用指数加权移动平均之后的梯度代替原梯度进行参数更新。(参考代码c4/s4_3/GD03.py。)
在梯度下降的过程中,如果对于所有样本点采用目标函数来求解梯度,则称为批量梯度下降法(batch gradient descent method);而如果只选用一个随机样本来求梯度,则称为随机梯度下降法(stochastic gradient descent method)。这两个方法看上去好像处于两个极端,有一种方法,称为小批量梯度下降法(mini-batch gradient descent method)就可以看作是二者的折中。它从训练数据中随机选择一部分数据进行学习。
使用梯度下降法,需要解决目标函数对神经网络参数的求导问题,得到目标函数对于各参数的梯度值,然后再配合梯度下降法完成网络的训练,这就要用到反向传播算法,所以这类神经网络也称为BP神经网络。
反向传播算法是指由输出向输入方向,利用求导的链式法则(chain rule)来逐级传播误差。所谓链式法则,就是多元复合函数的求导公式,设h=f(u,v),u=g1(x,y),v=g2(x,y),则h对x、y的偏导数分别为:
这样,在反向传播误差时,就相当于乘以局部导数,然后传到下一级。
下面通过一个具体的例子来说明反向传播的计算过程。
例4.9 假设神经网络结构如图4.31所示,包含输入层i1、i2,隐藏层h1、h2,输出层o1、o2,隐藏层和输出层都包含一个偏置。假设初始输入、权重、偏置分别为X=(0.05,0.10);。b1=0.35,b2=0.60。激活函数使用sigmoid函数,损失函数采用均方误差损失函数,希望训练的结果为To1=0,To2=1。假设学习速率为0.5,试着写出经过第一次误差反向传播,采用梯度下降法进行参数调整的过程及具体值。
图4.31 简单神经网络示意图
解 (1)首先根据初始值计算当前输出值。
假设隐藏层求和的输出为Y,经过激活函数后的输出为H,则由Y=wTX+b得
同样,算出h2=0.596 89。
进一步算出输出层。
同样,算出o2=0.772 93。
(2)计算损失值。
由,分别计算每一个输出的误差。
同样,算出Lo2=0.025 78,于是
(3)反向传播。
通过反向传播来更新权重,使损失函数值最小化,也就是使神经网络的输出和希望的目标靠近。从最后的输出反向进行,比如调整,想知道它对损失函数值的影响情况,求损失函数对其的偏导数,即,应用链式法则,有
每一级函数及其导数表达式分别为:
于是得到
这样,对于就可以使用梯度下降法进行更新了。
采用同样的方法,可以算出
接着继续反向传播,计算隐藏层的参数,由链式法则得
因为h1的输出连到了o1、o2两个神经元,所以
其中
同样,得到
于是
接着计算
所以
依此类推,可以求出
(4)采用梯度下降法更新权重值。
(5)计算更新后的损失值。
L=0.300 48,损失函数值下降量并不大,但是循环执行10 000次后,分别输入0.05和0.1,神经网络的输出将分别为0.011 66和0.988 31,损失函数值将变为0.000 14。
损失函数与激活函数组合在一起使用往往可以简化计算,所以通常令
则损失函数对参数的偏导数就写为
比如,如果损失函数使用交叉熵损失函数,激活函数使用softmax函数,如图4.32所示,因为标签p1为1,其余标签均为0,则由式(4.51)得交叉熵为
其导数为
而由式(4.46)、式(4.47)得softmax的偏导数为
由链式法则有
可以看到,反向传播的计算量变少许多。
图4.32 softmax函数输出层示意
同样,交叉熵损失函数配合sigmoid函数也能使计算简化许多,读者可以作为练习自行推导。
以上分析了全连接型前馈型人工神经网络的基本结构和具体实现方法。首先在结构设计上,不难发现,输入层神经元的数量是由输入数据的特征(又称维度)所决定的;输出层神经元的数量则是由任务,比如分类的类别数决定的。那么,对于隐藏层,如何选择才最佳呢?是隐藏层越多越好吗?每一个隐藏层神经元的数目也是越多越好吗?理论上来说,隐藏层的层次越深、规模越大,所表示的函数就可以越复杂。然而,实际应用中并非如此。比如,更复杂的神经网络所带来的计算量的增加也是显著的,而且随着神经网络的加深,会出现梯度消失、梯度爆炸等一系列的问题。只有解决这些问题,更深层的神经网络结构带来的优势才能体现出来。深度学习就是指神经网络的层较多较深时的一些特殊结构和处理方法。目前的全连接型前馈型人工神经网络,对于如何选择和设计隐藏层并没有一个标准的方法,更多的是通过实践去调试、去优化。另外,对于参数的选择,主要包括每层的神经元所采用的激活函数、系统所使用的目标函数、梯度下降法中的学习速率等,同样需要通过实际的测试来获得最佳的组合。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。