您当前的位置: 首页 >  网络

大白话 5 分钟带你走进人工智能:神经网络之反向传播详细案例及解释

蔚1 发布时间:2019-10-20 23:30:58 ,浏览量:2

神经网络是一门重要的机器学习技术。它是目前最为火热的研究方向--深度学习的基础。学习神经网络不仅可以让你掌握一门强大的机器学习方法,同时也可以更好地帮助你理解深度学习技术。而 反向传播是神经网络的核心原理,了解 反向传播的具体细节,会对以后在深度学习里面的探索起到触类旁通的重要作用。

我们的愿景是打造全网 AI 最通俗博客,赠人玫瑰,手有余香,在人工智能前行的路上一起前行。以通俗简介的方式,让每一位热爱着深入其中。

在本 Chat 中,你将收获如下内容:

  1. 反向传播前述
  2. 第一个案例解说反向传播
  3. 通用案例形式
  4. 逻辑回归案例
  5. 总结

适合人群: 对神经网络有兴趣,想探索深度学习领域的技术人员。

反向传播前述

我们知道正向传播就是把 x 拿下来一层层的和 w 乘,然后经过 function 非线性变化,最后得到一个 y 输出结果。反向传播(reverse-mode autodiff)就是反过来,从最后的 y 到 x,反向的自动求导。前向传播是 make predictions,去预测ŷ,然后计算出误差,再计算出每个神经节点对误差的贡献。这里的求贡献就是反向传播过程,首先根据前向传播的误差来求梯度,梯度越大贡献越大。然后根据梯度调整原来的权重。总结下来反向传播就是求导、求梯度,然后根据梯度在迭代里面调整 w 的一个过程。

反向自动求导是 tensorflow 实现的方案,首先,它执行图的前向阶段,从输入到输出,去计算节点值;然后反向阶段,从输出到输入去计算所有变量的偏导。

什么是偏导数:在数学中,一个多变量的函数的偏导数,就是它关于其中一个变量的导数而保持其他变量恒定(相对于全导数,在其中所有变量都允许变化)。偏导数在向量分析和微分几何中是很有用的。

说白了就是假如 f 对 x 求偏导:∂f*∂x。就是把除 x 以外的自变量当成常数,然后再进行正常的求导即可。

第一个案例解说反向传播

比如f(x, y)=x\^{2} * y+y+2这个计算逻辑,即这个算法。可以用如图来表达正向传播和反向传播逻辑。图中红色虚线表示正向传播,黑色实线是反向传播。

如果 x=3,y=4,正向传播之后,结果为 42,体现在n7 节点上。

那反向传播是做什么事情呢?怎样传播? 如何计算每根线上面的梯度呢?

这里依赖反向自动求导(reverse-mode autodiff),求解的想法是逐渐的从上往下,来计算 f(x,y)的偏导,使用每一个中间连续的节点,直到我们达到变量节点,这里严重依赖链式求导法则。

链式求导法则,就是 x 不能直接连接 f,我们通过一个中间的节点,比如 ni,如果 ni 可以连接 f,就可以让 f 对 ni 求偏导;然后 x 可以连接 ni,ni 对 xi 求偏导,然后根据链式求导法则相乘,得到的就是 f 对 x 求偏导的一个值。

在这里插入图片描述

比如上图中的算法逻辑我们最终的 f 对 x 来求偏的,f 是最后节点出现的结果,x 是第一个节点,中间有好长的路要走。所以如果对 x 求偏导的话,得把每一步节点输出对 x 求偏导。n1 节点没有直接连上 n7 节点,n1 节点也没有直接连上 n5 节点,但是 n1 节点可以连上 n4 节点;n4 节点连不上 n7 节点,但是能连接 n5 节点。那么我们可以让 xn1 通过 n4 去连接 n5,然后再通过 n5 连接到 n7,它就成为一条链,求这条链上面的导数,最后就可以把 n7 对 n1 也就是 f 对 x 偏导求出来。

因为最后的 function,对 x 求偏导,不能直接对 x 求导,我们倒过来一点点来推,所以它叫反向传播,反过来一点点的去传播梯度。

接下来我们一层一层的解释。

对于 f 来说,f 就是 n7 的结果,所以 f 对 n7 求导。因为是对本身求导,相当于 f(x)=x 这种情况下,对 x 求导,结果就变成前面的一个系数,等于 1。

在这里插入图片描述

下一层,我们要求图中红色这根线上所对应的梯度

在这里插入图片描述

​这根线的输出是 n5 节点,所以就要求一下 n7 对 n5 节点 function 的一个偏导,根据链式法则,如图,把它俩的结果相乘。f 对 n7 这一部分已经得到了结果,n7 节点的 function 是加和,n7=n5+n6,如果 n7 对 n5 求偏导,结果就是 1。可以这样理解这一步,比如 f(x)=ax+by,对 x 求导,那跟 b、y 没有关系,只用看 x 前面所对应的斜率,就等于 a,这里同样只看 n5 前面的系数即为 1。记住:

对谁求偏导,就把谁看做未知数。其他的都是常数!

∂f/∂n5=∂f*∂n7*∂n7/∂n5,就是 1*1=1,所以图中这根红线上的梯度就是 1。此时我们有一个中间结果,

接下来再往下来传播。求如下红色线的梯度:

在这里插入图片描述

​即求∂f/∂n4,等于∂f/∂n5*∂n5/∂n4,上一步求出来的∂f/∂n5=1,接着计算∂n5/∂n4,n5 的计算节点的 function 是,乘法。n5=n4*n2,对 n4 求偏导,把 n4 当做未知数,n2 为系数,所以结果是 n2。同理,反过来,对 n2 求偏导结果 n4。然后把 n2 节点的数值 4 代进来,即∂f/∂n4=1*4=4。

再往下传播:求图中红色线梯度

在这里插入图片描述​即∂f/∂x,这里有两根线,根据上面传播下来的梯度,那∂f/∂x=∂f/∂n4*∂n4/∂n1,∂f/∂n4 已经根据前面算出来的逻辑,∂f/∂n4=4,下面求∂n4/∂n1,∂n4/∂n1 看 n4 节点的 function 逻辑。此时 n4=n1*n1=n1\^2。因为(x\^2)'=2x,所以∂n4/∂n1=2n1=6。所以∂f/∂x=∂f/∂n4*∂n4/∂n1=4*6=24。

下面求f 对 y 的梯度,y 就是 n2,如图,因为 y 是有两条线连接,先求下图左边的梯度:

在这里插入图片描述

n2 上面连接 n5,那么梯度∂f/∂n2=∂f/∂n5*∂n5/∂n2,∂f/∂n5=1(上面已经求出),∂n5/∂n2 这部分看 n5 的逻辑是 n5=n4*n2,对 n2 求偏导结果为 n4。n4 不用算,因为在正向传播的时候,每个节点的值已经算出来了,所以 n4 是 3\^2=9。即∂n5/∂n2=9。所以∂f/∂n2=∂f/∂n2=∂f/∂n5*∂n5/∂n2=1*9=9。

然后再求 y 连线的右半部分如图:

在这里插入图片描述

​n7 经过 n6 再连接 n2,那么∂n7/∂n2=∂n7/∂n6*∂n6/∂n2,∂n7/∂n6 看 n7 的逻辑 n7=n5+n6,对 n6 求偏导结果为 1;∂n6/∂n2 看 n6 的逻辑 n6=n2+n3,对 n2 求偏导也是 1。所以∂n7/∂n2=1*1=1。

所以最后∂f/∂y=∂f/∂n2+∂nf/∂n2=1+9=10。

我们再看下 f 对 n3 的梯度:

在这里插入图片描述

​其实我们也不用算这根线,换成机器学习的角度去看,n1 是第一个维度 x1,n2 是第而个维度 x2,n3 是截距,对截距求偏导,把 n3 看做未知数,前面系数恒为 1。所以对截距求偏导结果恒为 1。

反向传播,如果想求每根线上所对应的梯度,得从后面往前,反着一层层的推出来,才能推出来。这样沿着图一路向下,我们可以计算出所有连线梯度,最后就能计算出??/?x = 24, ?? /?y = 10。

同理那我们就可以利用和上面类似的方式方法去计算?cost/?w,如下看一个通用的损失函数对参数求梯度的过程。

通用案例形式

抛开具体的实例,我们看下通用的神经元的求导,如图:

在这里插入图片描述

这是一个神经元,里面有∑加和,还有 f 激活函数。正向传播会求得相对应的结果z,一直传播会得到 Loss 损失;如果我们想要知道最右边红色这根线上面的梯度,就是∂L/∂z 求得一个结果。再往前反着推,想知道 x 这根线上所对应的梯度,用∂L/∂x,根据链式求导法则,先要得到∂L/∂z,然后再得到∂z/∂x ,此时∂L/∂x 即已经求得;∂z /∂x 这一部分要看前面的逻辑是什么。

逻辑回归案例

在这里插入图片描述

​一个神经元分为两部分,一部分是加和∑,一部分是 f 激活函数,前面有很多的输入 x1,x2,x0 恒为 1,x1 对应 w1,x2 对应 w2,x0 对应 w3,然后它们相乘相加,如果 f 是 Sigmoid 函数的话,经过相乘相加得到 f(w,x)。加和∑和 function 两个逻辑。

算法逻辑用图的方式表达出来如下:

在这里插入图片描述

​如果正向传播,w0 和 x0 相乘,w1 和 x1 相乘。绿色数字为传入的值,比如 w0=2,x0=-1,w0*x0 结果为-2;w1=-3,x1=-2,结果为 6;w 与 x 相乘完之后,还有加和的节点,加和之后再加上偏距 w2,结果为 1,即 z 算出来为 1。之后要带到 Sigmoid 函数里面去,首先坐变化-z,即 z 乘以(-1)=-1 然后经过 e\^-z,即 e\^-1=0.37,然后分母+1,0.37+1=1.37,然后求倒数,1/1.37=0.73。

所以在 x1=-2;x2=-1;x0=1;w2=2;w1=-3;w0=-3 的数值下,相当于给了 x 输入和 w,经过相乘相加之后,再经过 Sigmoid 函数计算,得到结果 0.73。0.73 的这个输出结果,很有可能再往下去传递,变成下一个神经元的输入。

我们的目标是调整参数 w1,w2,w0,因此需要求出梯度 g1,g2,g0。所以我们要算 g1=∂L/∂w1,g2=∂L/∂w2,g0=∂L/∂w0。

怎么反向求梯度 g?首先得知道 L 走一条线是什么样的如图,反向传播的线路图(也就是图中蓝色的线)。

在这里插入图片描述

​假设神经元的输出 0.73 就是终点,如果我们假设输出不是终点的话,我们就没法知道这根线上的梯度是多少,就没法往回去传。

最后一根线的梯度相当于对自己求导,它的梯度就是 1。我们要求 g0,g2,g1,即求在 w 它们线上所对应的 g0,g1,g2。

根据前面描述最后结节对本身求梯度相当于对自己求导,所以梯度是 1,从后往前传播。那么∂f/∂n6=∂n7/∂n6*∂f/∂n7,∂f/∂n7=1,∂n7/∂n6 这部分要看 n7 的计算逻辑是 1/x,(1/x)'=-1/x\^2,相当于 n6 是 x,因为 n6 是 1.37,那么∂n7/∂n6=-1/(1.37)\^2=-0.53。

接着 n5 到 n6 这条线上的梯度,就是∂f/∂n5=∂n6/∂n5 *∂f/∂n6,∂f/∂n6 这一部分刚刚求得是-0.53,∂n6/∂n5 看 n6 的计算逻辑 f(x)=x+1,求导结果为 1。那么∂f/∂n5=1*(-0.53)=-0.53。

接着求 n4 到 n5 这个线上的梯度,∂f/∂n4=∂n5/∂n4 *∂f/∂n5,∂f/∂n5 这一部分刚刚求得是-0.53,∂n5/∂n4 看 n5 的计算逻辑是 exp,f(x)'=(e\^x)'=ex,n4 的输出-1 作为 x,所以∂f/∂n4=e\^-1*0.53=1/e*(-0.53)=-0.2。

然后求 n4 到 n3 这个线上的梯度,∂f/∂n3=∂f/∂n4 *∂n4/∂n3,∂f/∂n4 刚求得是-0.2,∂n4/∂n3 看 n4 的计算逻辑是 f(x)=-x,求导是-1,所以∂n4/∂n3=-1。那么∂f/∂n3=-0.2*(-1)=0.2。

然后求梯度 g2,即 n3 和 w2 的连线。∂f/∂w2=∂f/∂n3 *∂n3/∂w2,∂f/∂n3 等是 0.2,∂n3/∂w2 看 n3 的逻辑为加和,w2 前面系数为 1,所以∂n3/∂w2=1,那么 g0=∂f/∂w2=0.2*1=0.2。

g2 求出来了,怎么用 梯度下降调整 w2?

用梯度下降的公式,w2\^(t+1)=w2\^t-α*g2,α学习率,是传进来的超参数,比如学习率是 0.01,g2 是 0.2,那么得到新 w2\^(t+1)=-3.002,它会影响正向传播每条线上绿色数值,之后它又会影响下次反向传播的梯度。

接下来调整 w0。w0 这部分是*的一个门操作:

在这里插入图片描述​f(a,b)=a*b,对 a 求导结果是 b,对 b 求导结果是 a。那么∂f/∂w0=0.2*∂w0*x2/∂w0,x0=-1,那么∂f/∂w0=-0.2。

之后按照公式,w0\^(t+1)=w0\^t-α*g0=2-0.01*(-0.2)=2.002,就是 w0 经过一次迭代调整之后的结果。

x0 前的梯度,因为它是*,跟 w0 有关系,所以梯度就是 0.2*2=0.4。

接下来调节 w1。

在这里插入图片描述

计算逻辑是*,那么 g1=x1*0.2=-2*0.2=-0.4。调 w1:w1\^t+1=w1\^t-α*g1=-3+0.01*0.4=-2.996,是 w1 经过一次迭代调整之后的结果。x1 前的梯度,和 w1 有关系,那么-3*0.2=-0.6。

现在我们得到图上每个线所对应的梯度,我们需要调的是 w2 所对的线 g2、w1 所对得线 g1,w0 所对得线 g0;我们不用调 x2,x1 两根线上的梯度,因为每一次迭代的时候,传的都是原始的那份数据。也就是说我们调的是 w,然后调完之后,下一次再把原始的的数据代进来,然后再正向传播,求这一路所有的绿色的数值。然后反向传播,再来调 w,然后再把 x 带进来,循环往复。

这就是梯度下降反向传播的流程。 它每一次迭代内部就是一个正向传播,求绿色的值,一次反向传播,求红色的梯度,然后在内部根据最优解的公式调 w,不同的最优解的求法,公式就不一样,但是不管什么方法,都要去求梯度。这个就是神经网络里面的反向传播,虽然以后写代码不需要自己去算,也不用去画图,它会自动帮你求导,但是要知道它自动求导数是怎样去求的。

假设 1/x 输出的结果就是最终的结果了,它求出来的梯度是 1。但实际上做机器学习的话,Sigmoid 函数出的结果不是咱们想象的,它输出的值相当于ŷ。也就是说我们还得根据ŷ和真实的 y 再去求一个损失函数,损失函数不管是交叉熵还是 mse,你还得画这样一个传播图,0.73 还没有完,还得再往后去,如果是 mse 的话,就用预测的 0.73 跟真实的相减,然后再汇总,计算 function 函数。

举个例子,比如后面是交叉熵,那ŷ还要经过节点 log,然后再接一个节点去乘以真实的 y,后面还得再去加和,最后输出的 L 才是 Loss function。

这里 x2,x1 是一个样本求梯度,如果去做批量梯度下降的时候,损失函数是 mse,它的公式是:

1 / \mathrm{m} \sum(\hat{\mathrm{y}} \mathrm{i}-\mathrm{yi})\^{2}

前面计算的 x2,x1 相当于批量梯度下降样本里的一条,而随机梯度下降需要 m 个样本,都来去算总的损失,因为这里用了一个加和,所以求它整体梯度的时候,需要求每一条样本梯度的加和平均。

比如如果 function 函数是 ax+by,如果对 x 求导,就看 ax 这一部分的导数,如果对 y 求导,只考虑 by 这一部分的导数,加和∑相当于把它俩导数再加和求平均,也就是相当于是每个样本求梯度的一个平均值。

总结

反向传播和梯度下降这两个词,第一眼看上去似懂非懂,不明觉厉。这两个概念是整个神经网络中的重要组成部分,是和误差函数/损失函数的概念分不开的。

神经网络训练的最基本的思想就是:先“蒙”一个结果,我们叫预测结果 h,看看这个预测结果和事先标记好的训练集中的真实结果 y 之间的差距,然后调整策略,再试一次,这一次就不是“蒙”了,而是有依据地向正确的方向靠近。如此反复多次,一直到预测结果和真实结果之间相差无几,亦即\|h-y\|->0,就结束训练。这里面不断地调整策略就是其背后的原理就是反向传播和梯度下降。

在神经网络训练中,我们把“蒙”叫做初始化,可以随机,也可以根据以前的经验给定初始值。即使是“蒙”,也是有技术含量的。

阅读全文: http://gitbook.cn/gitchat/activity/5dac150dd0ffe0604171796e

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

关注
打赏
1688896170
查看更多评论

蔚1

暂无认证

  • 2浏览

    0关注

    4645博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0531s