深度学习算法最后都归结为求解最优化问题,以达到我们想让算法达到的目标,即找到最好的那个决策。为了完成某一目标,需要构造出一个“目标函数”来,然后让该函数取极大值或极小值,从而得到深度学习算法的模型参数。
代价函数(Cost Function ): 用于找到最优解的目的函数,这也是代价函数的作用。代价函数是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均。
损失函数(Loss Function )是定义在单个样本上的,算的是一个样本的误差。
目标函数(Object Function)是最终需要优化的函数,等于经验风险+结构风险(也就是Cost Function + 正则化项)。
实际应用中损失函数和代价函数是同一个东西,目标函数是一个与他们相关但更广的概念。
目标函数介绍:
损失函数越小,就代表模型拟合的越好。那是不是我们的目标就只是让损失函数越小越好呢?还不是。这个时候还有一个概念叫风险函数(risk function)。风险函数是损失函数的期望,这是由于我们输入输出的(X,Y)遵循一个联合分布,但是这个联合分布是未知的,所以无法计算。但是我们是有历史数据的,就是我们的训练集,f(X)关于训练集的平均损失称作经验风险(empirical risk),所以我们的目标就是最小化经验风险。
但是会因为它过度学习历史数据,导致它在真正预测时效果会很不好,这种情况称为过拟合(over-fitting)。为什么会造成这种结果?大白话说就是它的函数太复杂了,这就引出了下面的概念,我们不仅要让经验风险最小化,还要让结构风险最小化。
这个时候就定义了一个函数J(f),这个函数专门用来度量模型的复杂度,在机器学习中也叫正则化(regularization)。常用的有L1, L2范数。到这一步我们就可以说我们最终的优化函数是最优化经验风险和结构风险,而这个函数就被称为目标函数
代价函数作用解析:
对于回归问题,我们需要求出代价函数来求解最优解,常用的是平方误差代价函数。
简单理解代价就是预测值和实际值之间的差距(两点之间的距离),那对于多个样本来说,就是差距之和。
比如,对于假设函数:
里面有 θ0 和 θ1 两个参数,参数的改变将会导致假设函数的变化,比如:
现实的例子中,数据会以很多点的形式给我们,我们想要解决回归问题,就需要将这些点拟合成一条直线,找到最优的 θ0 和 θ1 来使这条直线更能代表所有数据。
而如何找到最优解呢,就需要使用代价函数来求解了,以平方误差代价函数为例。从最简单的单一参数来看,假设函数为:
平方误差代价函数的主要思想就是将实际数据给出的值与我们拟合出的线的对应值做差,求出我们拟合出的直线与实际的差距。
实际值与拟合函数值之差有正有负,全部样本的代价加起来有可能正负相抵,
采用方差来解决正负的问题。在前面乘以1/2,是因为后面求导会有2,为了简便计算。这样,就产生了代价函数:
最优解即为代价函数的最小值,根据以上公式多次计算可得到代价函数的图像:
解(求导):可以看到该代价函数的确有最小值,这里恰好是横坐标为 1 的时候。
如果更多参数的话,就会更为复杂,两个参数的时候就已经是三维图像:
高度即为代价函数的值,可以看到它仍然有着最小值的,而到达更多的参数的时候就无法像这样可视化了,但是原理都是相似的。
因此,对于回归问题,我们就可以归结为得到代价函数的最小值:
梯度下降(Gradient Descent):
在上面的介绍中,构建了损失函数,再用优化算法对损失函数进行优化,找到最优参数。常用到的优化算法有梯度下降法和最小二乘法,这里总结梯度下降法。
先看一下各个梯度下降算法的可视化下降过程:
梯度下降法的基本思想可以类比为一个下山的过程。假设场景:一个人被困在山上,需要从山上下来(找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致可视度很低。因此,下山的路径就无法确定,他必须利用自己周围的信息去找到下山的路径。这个时候,他就可以利用梯度下降算法来帮助自己下山。具体来说就是,以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走。然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。
此人每走一段距离,都需要一段时间来测量所在位置最陡峭的方向,这是比较耗时的。那么为了在太阳下山之前到达山底,就要尽可能的减少测量方向的次数。这是一个两难的选择,如果测量的频繁,可以保证下山的方向是绝对正确的,但又非常耗时,如果测量的过少,又有偏离轨道的风险。所以需要找到一个合适的测量方向的频率,来确保下山的方向不错误,同时又不至于耗时太多!
梯度下降法及其实现:
首先,我们有一个可微分的函数。这个函数就代表着一座山。我们的目标就是找到这个函数的最小值,也就是山底。根据之前的场景假设,最快的下山的方式就是找到当前位置最陡峭的方向,然后沿着此方向向下走,对应到函数中,就是找到给定点的梯度 ,然后朝着梯度相反的方向,就能让函数值下降的最快!我们重复利用这个方法,反复求取梯度,最后就能到达局部的最小值,这就类似于我们下山的过程。而求取梯度就确定了最陡峭的方向,也就是场景中测量方向的手段。那么为什么梯度的方向就是最陡峭的方向呢?接下来,我们从微分开始讲起:
微分
看待微分的意义,可以有不同的角度,最常用的两种是:
函数图像中,某点的切线的斜率
函数的变化率
几个微分的例子:
上面的例子都是单变量的微分,当一个函数有多个变量的时候,就有了多变量的微分,即分别对每个变量进行求微分
梯度
梯度实际上就是多变量微分的一般化。
下面这个例子:
我们可以看到,梯度就是分别对每个变量进行微分,然后用逗号分割开,梯度是用<>包括起来,说明梯度其实一个向量。
梯度是微积分中一个很重要的概念,之前提到过梯度的意义
在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率
在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向
这也就说明了为什么我们需要千方百计的求取梯度!我们需要到达山底,就需要在每一步观测到此时最陡峭的地方,梯度就恰巧告诉了我们这个方向。梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向,这正是我们所需要的。所以我们只要沿着梯度的方向一直走,就能走到局部的最低点!
梯度下降算法的数学解释
上面我们花了大量的篇幅介绍梯度下降算法的基本思想和场景假设,以及梯度的概念和思想。下面我们就开始从数学上解释梯度下降算法的计算过程和思想!
此公式的意义是:J是关于Θ的一个函数,我们当前所处的位置为Θ0点,要从这个点走到J的最小值点,也就是山底。首先我们先确定前进的方向,也就是梯度的反向,然后走一段距离的步长,也就是α,走完这个段步长,就到达了Θ1这个点!
下面就这个公式的几个常见的疑问:
α是什么含义?
α在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过α来控制每一步走的距离,以保证不要步子跨的太大扯着蛋,哈哈,其实就是不要走太快,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以α的选择在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点!
为什么要梯度要乘以一个负号?
梯度前加一个负号,就意味着朝着梯度相反的方向前进!我们在前文提到,梯度的方向实际就是函数在此点上升最快的方向!而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号。
梯度下降法的具体做法是:损失函数对每一个参数自变量求偏导。然后每个偏导数乘以预先设定的步长,以此为本次学习的参数调整量。原参数减去参数调整量,则参数可以得到修正。修正之后,本轮学习结束。可再进行前向传播。(注:学习不止一轮)
这个下山的人实际上就代表了反向传播算法,下山的路径其实就代表着算法中一直在寻找的参数Θ,山上当前点的最陡峭的方向实际上就是代价函数在这一点的梯度方向,场景中观测最陡峭方向所用的工具就是微分 。在下一次观测之前的时间就是有我们算法中的学习率α所定义的。
反向传播(BP):
是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。
如果去问一下了解BP算法的人“BP算法怎推导?”,大概率得到的回答是“不就是链式求导法则嘛”,我觉得这种答案对于提问题的人来说没有任何帮助。BP的推导需要链式求导不错,但提问者往往想得到的是直观的回答,毕竟理解才是王道。
前向传播算法(Forward propagation)与反向传播算法(Back propagation)
“正向传播”求损失,“反向传播”回传误差。同时,神经网络每层的每个神经元都可以根据误差信号修正每层的权重,只要能明确上面两点,那么下面的例子,只要会一点链式求导规则,就一定能看懂!
BP算法,也叫δ算法,下面以3层的感知机为例进行举例讲解。
上图的前向传播(网络输出计算)过程如下:(此处为网络的整个误差的计算,误差E计算方法为MSE)
上面的计算过程并不难,只要耐心一步步的拆开式子,逐渐分解即可。现在还有两个问题需要解决:
误差E有了,怎么调整权重让误差不断减小?
E是权重w的函数,如何找到使得函数值最小的w。
解决上面问题的方法是梯度下降算法(简单图示如下)
通过下面的例子,相信绝大多数人也能很轻松的理解BP算法。如图是一个简单的神经网络用来举例:
下面是前向(前馈)运算(激活函数为sigmoid):
输入层---->隐含层:计算神经元h1的输入加权和
神经元h1的输出o1:(此处用到激活函数为sigmoid函数):同理,可计算出神经元h2的输出o2
.隐含层---->输出层:计算输出层神经元o1和o2的值
这样前向传播的过程就结束了,我们得到输出值为[0.75136507 , 0.772928465],与实际值[0.01 , 0.99]相差还很远,现在我们对误差进行反向传播,更新权值,重新计算输出。
下面是反向传播(求网络误差对各个权重参数的梯度):
我们先来求最简单的,求误差E对w5的导数。首先明确这是一个“链式求导”过程,要求误差E对w5的导数,需要先求误差E对out o1的导数,再求out o1对net o1的导数,最后再求net o1对w5的导数,经过这个链式法则,我们就可以求出误差E对w5的导数(偏导),如下图所示:
计算总误差,有两个输出,所以分别计算o1和o2的误差,总误差为两者之和。
隐含层---->输出层的权值更新:以权重参数w5为例,如果我们想知道w5对整体误差产生了多少影响,可以用整体误差对w5求偏导求出:(链式法则)
计算出各自的值, 最后三者相乘,计算出整体误差E(total)对w5的偏导值。
导数(梯度)已经计算出来了,下面就是反向传播与参数更新过程。
更新w5的值,其中是学习速率,这里我们取0.5;同理,可更新w6,w7,w8
--------------------------------------------------------------
如果要想求误差E对w1的导数,误差E对w1的求导路径不止一条,这会稍微复杂一点,但换汤不换药,方法其实与上面说的差不多,但是有个地方需要变一下,在上文计算总误差对w5的偏导时,是从out(o1)---->net(o1)---->w5,但是在隐含层之间的权值更新时,是out(h1)---->net(h1)---->w1,而out(h1)会接受E(o1)和E(o2)两个地方传来的误差,所以这个地方两个都要计算:
同理,额可更新w2,w3,w4的权值:
《神经网络与深度学习》书中传说的反向传播4大公式
仔细观察,你会发现BP1与BP2相结合就能发挥出最大功效,可以计算出任意层的误差,只要首先利用BP1公式计算出输出层误差,然后利用BP2层层传递,就无敌了,这也正是误差反向传播算法的缘由吧。同时对于权重w以及偏置b我们就可以通过BP3和BP4公式来计算了。
前两条公式就像是多米诺骨牌一样(求导的链式法则)。
第一条公式求出输出层每个神经元的误差(推倒第一枚多米诺骨牌)
第二条公式阐述了后面一层网络神经元的误差与前一层神经元的误差的联系(前一枚倒下可推导出下一枚也倒下)。
第三、四条公式,说明怎样以神经元误差得到两个参数(w, b)的梯度。
深度学习,天天向上