前言
之前讲了前向传播,这篇文章讲一下反向传播的原理,以及神经网络怎么更新参数的,讲了一下梯度下降法的计算过程和收敛过程。
梯度与梯度下降
简单介绍
摘自百科上的一段话:
梯度(英语:gradient)是一种关于多元导数的概括。平常的一元(单变量)函数的导数是标量值函数,而多元函数的梯度是向量值函数。多元可微函数𝑓在点𝑃上的梯度,是以𝑓在𝑃上的偏导数为分量的向量。
通俗的话来说,多元函数的梯度,是由每个偏导数组成的向量,每一点的梯度方向就是多元函数在该点梯度值所表示得向量方向。对于一元函数来说,梯度就相当于一元函数的微分/导数,下面从一元函数开始出发,演示一下梯度是如何作用的。
一元函数导数
对于函数f(x)=x2,其导数为f′(x)=2x来说,很容易知道其极值点/最小值点在x=0取得,即fmin(x)=f(0)=0。那么如何用梯度下降的方法来让计算机寻找极值/最值呢?
- 随机取一个x=x0,在该点的导数值(“梯度值”)为f′(x)=2x0
- 更新参数,利用梯度值如何更新呢?梯度下降法,顾名思义,沿着梯度的负方向更新即可,就变成:xnew=x−f′(x)=x0−2x0=−x0
- 我们发现,x确实更新了,而且变成了−x0,但是又发现一个问题,距离真的极值点的距离没有变。
- 继续按照上述方法计算下去,明显都不收敛了,所以需要引入一个机制让过程收敛才行——那便是学习率,记为lr,通常取很小的值,比如lr=0.1
引入学习率lr=0.1之后,会发生什么呢?
- 继续第二步,xnew=x−lr×f′(x)=x0−0.1×2x0=0.8x0,发现离真实值近了很多。
- 不如继续用这种方法更新,假设x0=1000,那么在进行100次之后,x0≈2.04×10−7,f(x0)≈4.15×10−14,很明显非常接近真实值了。
多元函数梯度
对于函数f(x,y)=x2+y2,其偏导数为∂x∂f=2x,∂y∂f=2y,极值点也很明显在(x,y)=(0,0)取得。
- 随机选取初始值X=(x0,y0),同样的分别求出该点的偏导数值,然后利用更新公式进行更新
- Xnew(x,y)=(x0−lr×2x0,y0−lr×2y0),计算个许多次,就可以发现该函数收敛了
一个思考
上述两个例子,都是直接把导数的解析式写出来的,但是在神经网络这么多参数中,不可能都写出导数解析式,该如何求这个导数呢?而且,神经网络如何快速求导数来快速更新参数呢?下面就要讲到反向传播的原理了。
反向传播
简单介绍
摘自百科上的一段话:
反向传播(英语:Backpropagation,意为误差反向传播,缩写为BP)是对多层人工神经网络进行梯度下降的算法,也就是用链式法则以网络每层的权重为变量计算损失函数的梯度,以更新权重来最小化损失函数。
简单来说,反向传播是为了快速更新权重的方法。所以一次神经网络的计算会分为两个步骤,先进行前向传播计算预测值,然后再反向传播链式更新参数。
单个神经元的反向传播
注: 先前的一元/多元函数例子中,并没有介绍什么是损失函数,也没有关注损失函数是啥。而是简单用函数来替代损失函数了(上述损失函数实际上是:Loss(x)=x2以及Loss(x,y)=x2+y2),仅仅是因为这两个函数可以反应与真实值的误差,因为梯度下降法是要求损失函数关于各个参数的偏导数,下面会引入损失函数来计算。
先用单个神经元举例子
x经过上述神经元计算出来的是预测值y^=f(wx+b),其中w是权重,b是偏置,f是激活函数,假设真实值输出为y,损失函数记为l。
我们可以写出损失函数来:Loss=l(y^,y)。这里有两个量需要更新,一个是权重,一个是偏置。
∂w∂l=∂y^∂l×∂w∂y^=∂y^∂l×∂w∂y^∂b∂l=∂y^∂l×∂b∂y^=∂y^∂l×∂b∂y^
由高等数学可知上述的公式(假设激活函数可导)。假设损失函数为MSELoss
,激活函数为sigmoid
:
loss:n1i=1∑n(y^i−yi)2sigmoid:S(x)=1+e−x1,S′(x)=(1+e−x)2e−x=S(x)(1−S(x))
下面来分布计算一下每个函数过程,先是在输出层C
处的计算
l(y^,y)=(y^−y)2,∂y^∂l=2(y^−y)
上述式子可以计算出第一步来,而且只需要代值进去即可。然后在神经元b
处的计算
y^=f(wx+b)=1+e−(wx+b)1,∂w∂y^=xS(wx+b)(1−S(wx+b))=vw∂b∂y^=S(wx+b)(1−S(wx+b))=vb
可以看出,在某一层计算的时候,只需要下一层给一个值,然后就能够在当前进行计算了,然后利用更新式子更新即可wnew=w−lr×vw,bnew=b−lr×vb,实现反向传播,下面给出多层的例子。
多层神经元举例子
用下述神经网络举例子
之前的博客已经讲过了前向传播,符合记法也在之前的博客中有,前向传播就是从输入到输出。假设已经完成了前向传播,现在开始反向传播。
继续假设损失函数为MSELoss
,激活函数为sigmoid
- 先计算损失值,并写出损失函数
Loss=l(y^1,y^2,y^3,y1,y2,y3)=31[(y^1−y1)2+(y^2−y2)2+(y^3−y3)2]∂y^1∂l=32(y^1−y1)
- 先算输出层,一层中各个神经元之间并没有什么练习,所以对某个神经元偏导是不会包含其他神经元的参数的。记任何一层神经元的输入为Xi(i=1,2,3,y),某个神经元的输入就是xij(i=1,2,3,y),(j=1,2,3),下面来计算
y1
这个神经元吧
∂w411∂l=∂y^1∂l⋅∂w411∂y^1=∂y^1∂l⋅x411
- 还有一个点需要被意识到,x411实际上也是y31,也就是
L31
的输出,我们在前向传播中已经求过了,这里可以直接用,就能够非常快的求出上述式子的导数值了,记为v,根据梯度下降法可以很快的更新参数了,w411=w411−lr×v,即可更新一次
- 继续计算
L31
这一层的权重,这里有三个的原因是,L31
这个神经元经过三条路才到达损失函数,L31->L41, L31->L42, L31->L43
,因为L31
和后一层是全连接的
∂w311∂l=∂y^1∂l⋅∂x411∂y^1⋅∂w311∂x411+∂y^2∂l⋅∂x412∂y^2⋅∂w311∂x412+∂y^3∂l⋅∂x413∂y^3⋅∂w311∂x413
- 用同样的方法来计算上述公式,就以第一项为例
∂y^1∂l⋅∂x411∂y^1⋅∂w311∂x411
-
计算上述公式,第一项不用说了,前面算过了
-
值得注意的是,y^1=x411+x421+x431,所以中间这一项为1,不用算
-
对于右边这一项,由于引入了激活函数,所以还需要计算激活函数的值
∂w311∂x411=y31f′(w311y31+b31)
- 同样,可以快算在该层算出来,继续用梯度下降法更新即可
参考链接