深度学习入门(7)
参考原文链接🔗:https://developer.aliyun.com/article/105339
“人世间,很多事情虽然已经做过了,却不为人知,但那又如何,重要的是,我已做过,并从中获得了很多。”
多层感知机网络遇到的大问题
第六讲中提到的多层前馈网络,有时也被称为多层感知机(MLP)。但是这个提法导致概念多少有些混淆,因为,在多层前馈网络中,神经元的内部构造已经悄然发生了变化,即激活函数从简单粗暴的“阶跃函数”变成了比较平滑的挤压函数Sigmoid。
为什么要换成这个激活函数呢?原因并不复杂,这是因为感知机的激活函数是阶跃函数,不利于求导,今儿求损失函数的最小值。当分类对象是线性可分,且学习率η足够小时,感知机还堪胜任,其构建的网络,还可以训练达到收敛。但分类对象不是线性可分时,感知机就无法胜任了。因此,通常感知机并不能推广到一般前馈网络中。
按照我们前面章节的说法,所谓的机器学习,简单来说,就是找到一个好用的函数,从而较好地实现某个特定的功能。一言蔽之,函数就是功能。对于某个特定的前馈神经网络,给定网络参数(连接权值和阈值),其实就是定义了一个具备数据采集(输入层)、加工处理(隐含层),然后是输出结果(输出层)的函数。
如果仅仅给定一个网络结构,其实它定义的是一个函数集合,因为不同的网络参数(连接权值与阈值),实现的功能“大相径庭”。功能不同,自然函数也是不同的。
针对前馈神经网络,我们需要实现的目的很简单,就是想让损失函数达到最小值,因为只有这样,实际输出和预期输出的差值才最小。那么,如何从众多的网络参数(神经元之间的连接)中选择最佳的参数呢?
最简单粗暴的方法,当然就是枚举所有可能值。
但是这种暴力策略,对稍微复杂一点的网络就不可取的,例如,用于语音识别的神经网络,假设网络结构有7层,每一层有1000个神经元,那么仅一层之间的全连接权值,就达到1000*1000=1000000个,一旦层次多了,那权值数量就太多了。
到底什么是梯度?
为了克服多层感知机存在的问题,人们设计了一种名为delta法则的启发式方法,该方法可以让目标收敛到最佳解的近似值。
该法则的思想在于,使用梯度下降的方法找极值。具体来说,就是在假设空间中搜索可能的权值向量,并以“最佳”的姿态,来拟合训练集合中的样本。那么,何为最佳拟合呢?当然就是让损失函数达到最小值!
我们知道,求某个函数的极值,难免用到“导数”的概念。什么是导数呢?导数就是用来分析函数“变化率”的一种度量。针对函数中某个特定点x0,该点的导数就是x0点的“瞬间斜率”,也即切线斜率,见公式:
如果这个斜率越大,就表明其上升的趋势越强劲。当这个斜率为0时,就达到了这个函数的极值点,而前文提到的损失函数,如果要达到损失最小,就难免用到导数“反向指导”如何快速抵达最小值。
在单变量的实值函数中,梯度就可以简单地理解为只是导数,或者说对于一个线性函数而言,梯度就是线的斜率。但对于多变量的函数,它的梯度概念就不那么容易理解了。
在向量微分中,标量场的梯度其实是一个向量场。对于特定函数的某个特定点,它的梯度就表示从该点出发,该函数值增长最为迅猛的方向。假设一个标量函数f的梯度记为:f或gradf,这里的表示向量微分算子,那么,在一个三维直角坐标系,该函数的梯度就可以表示为公式:
求这个梯度值,难免用到“偏导”的概念。说到“偏导”,这里顺便提一下国内的翻译,其英文是“partial derivatives(局部导数)”,书本上常翻译为“偏导”,可能会把读者的思路引导“偏”。
什么是“局部导数”呢?对于多维变量函数而言,当求某个变量的导数(相比于全部变量,这里只求一个变量,即为“局部”),就是把其他变量视为常量,然后整个函数求其导数。之后,整个过程对每个变量都“临幸”一遍,放在向量场中,就得到了这个函数的梯度了。举例来说,对于三变量的函数f = x^2 3xy y^2 z^3。它的梯度可以这样求得:
这时,梯度可以理解为,站在向量点A(1,2,3),如果想让函数f的值增长得最快,那么它的下一个前进的方向,就是朝着向量B(8,7,27)方向进发。很显然,梯度最明显的应用,就是快速找到多维变量函数的极(大/小)值。
在这里需要说明的是,我们用“局部函数”的翻译,仅仅用来加深对“偏导”的理解。
到底什么是梯度下降?
下面我们说说,在求损失函数的极小值的过程中,常常提到的“梯度递减”的概念。
如果把登山过程中求某点的斜率称为“梯度(gradient)”,而找谷底的方法,就可以把它称之为“梯度递减(gradient descent)”。
“梯度递减”体现出来的指导意义,就是“机器学习”中的“学习”的内涵。“学习”的本质,在于性能的提升,利用“梯度递减”的方法,的确在很大程度上,提升了机器的性能,所以,它就是“学习”。
重温神经网络的损失函数
针对前馈神经网络的设计,输入和输出层设计比较直观。
针对前馈神经网络的设计,输入和输出层设计比较直观。比如说,假如我们尝试判断一张手写数字图片上面是否写着数字“2”。很自然地,我们可以把图片像素的灰度值作为网络的输入。如果图片的维度是16×16,那么我们输入层神经元就可以设计为256个(也就是说,输入层是一个包括256个灰度值向量),每个神经元接受的输入值,就是规格化的灰度值。
而输出层的设计也很简单,就是需要包含10神经元,输出是数字“0~9”的分类概率(也就是说,输出层是一个包括10个概率值的向量)。择其大者而判之,如图7-7所示,如果判定为“2”的概率(比如说80%)远远大于其他数字,那么整个神经网络的最终判定,就是手写图片中的数字是“2”,而非其它数字。
相比于神经网络输入、输出层设计的简单直观,它的隐含层设计,可就没有那么简单了。说好听点,它是一门艺术,依赖于“工匠”的打磨。说不好听点,它就是一个体力活,需要不断地“试错”。
但通过不断地“折腾”,研究人员还真是掌握了一些针对隐层的启发式设计规则(如下文即将提到的BP算法),以此降低训练网络所花的开销,并尽量提升网络的性能。
那么,怎样才算是提升神经网络的性能呢?这就要用到我们前面提到的损失函数了。在第六章我们提到,所谓“损失函数”,就是一个刻画实际输出值和期望值之间“落差”的函数。
为了达到理想状态,我们当然希望这种“落差”最小,也就是说,我们希望快速配置好网络参数,从而让这个损失函数达到极小值,神经网络的性能接近最优。
关于求损失函数极小值,给出一个通俗易懂的例子,对于识别手写数字的神经网络,训练数据都是一些“0,1,2,...,9”等数字图像。
由于人们手写数字的风格不同,图像的残缺程度不同,输出的结果又是并不能是“十全十美”,于是我们就用损失函数来衡量二者的误差,前面我们提到,常用的损失函数是:
机器学习的任务,很大程度上,找一个模型,拟合或者说“适配”给定的训练数据,然后再用这个模型预测新数据。这个模型的表现形式,具体来说,就是设计一个好用的函数,用以揭示这些训练样本随着自身变量的变化关系。揭示拟合好坏的程度,就要用到损失函数。“损失”越小,说明拟合的效果越好。
在我们训练神经网络时,损失函数说白了,就是有关“权值参数”的函数。为了求损失函数的极小值,就不可避免地需要计算损失函数中的每一个权值参数的偏导数,这时前文中提到的“梯度递减”的方法就派上用场了。训练线性单元的梯度递减算法如上图所示,图中的参数η就是“学习率”,它决定了梯度递减搜索的步长,这个步长“过犹不及”。如果值太小,则收敛慢,如果值太大,则容易越过极值,导致网络震荡,难以收敛。
上图仅给出一个权值变量wi的梯度示意图,而实际上,神经网络的参数是非常多的,因此针对损失函数L的权值向量的梯度可以记作:
在这里,梯度本身就是一个向量,它的多个维度分别由损失函数L对多个权值参数wi求偏导所得。当梯度被解释为权值空间的一个向量时,它就确定了L对陡峭上升的方向。
如果需要根据公式来更新权值,我们需要一个更加实用的方法,在每一步重复计算。幸运的是,这个过程并不复杂,通过简易的数学推导,我们可以得到每个权值分量wi更简明的计算公式:
其中,xid表示训练集合的第d个样例的输入分量xi,yd表示第d样例的期望输出值,yd'表示第d样例的实际输出值,这二者差值就是“损失”,也称为误差。有了公式做支撑,算法就可行之有“章法”了。
对于前文所言,对于特定训练集合,第d个样本的预期输出yd和实际输出yd',都是“尘埃落定”的常数,对于求权值分量wi的偏导(部分导数)来说,除了作为变量的系数可以保留之外,其他统统都可以看作“浮云”。此外,注意到:
因此,可以进一步将公式化简:
有了该公式做支撑,梯度下降的权值更新法则可以用如下公式表示:
有了前面的知识铺垫,我们终于可以在下一章谈谈误差反向传播(BP)算法了。
小结
在本章中,我们主要讲解了梯度的概念,所谓梯度,就是该函数增长最迅猛的方向,然后我们介绍了梯度下降法则。
在下一章中,我们将用最通俗易懂的方式,详细解释误差反向传播算法。深度学习之所以性能奇佳,不仅仅因为它有一个“无监督”的逐层预训练,除此之外,预训练之后的“微调”,还是需要“有监督”的BP算法作为支撑。
深度学习离不开“BP”算法。