CS231n(四)Back Propagation Notes

反向传播是利用链式法则递归计算表达式的梯度的方法。

 

导数的意义:函数变量在某个点周围的极小区域内变化,而导数就是变量变化导致的函数在该方向上的变化率

\frac{df(x)}{dx}= lim_{h\to 0}\frac{f(x+h)-f(x)}{h}

函数关于每个变量的导数指明了整个表达式对于该变量的敏感程度。

 

使用链式法则计算复合表达式

知识回顾

复合函数,比如f(x,y,z)=(x+y)z。虽然这个表达足够简单,可以直接微分,但是在此使用一种有助于直观理解反向传播的方法。将公式分成两部分:q=x+yf=qz

因为fqz相乘,所以\displaystyle\frac{\partial f}{\partial q}=z,\frac{\partial f}{\partial z}=q,又因为qx+y,所以\displaystyle\frac{\partial q}{\partial x}=1,\frac{\partial q}{\partial y}=1。然而,并不需要关心中间量q的梯度,因为\frac{\partial f}{\partial q}没有用。相反,函数f关于x,y,z的梯度才是需要关注的。链式法则指出将这些梯度表达式链接起来的正确方式是相乘,比如\displaystyle\frac{\partial f}{\partial x}=\frac{\partial f}{\partial q}\frac{\partial q}{\partial x}。 

 

下图是可视化计算过程

前向传播从输入计算到输出(绿色),反向传播从尾部开始,根据链式法则递归地向前计算梯度(显示为红色),一直到网络的输入端。可以认为,梯度是从计算链路中回流。

每个门单元(图中的圆圈)都会得到一些输入并立即计算两个东西:1. 这个门的输出值   2.其输出值关于输入值的局部梯度。

一旦前向传播完毕,在反向传播的过程中,门单元门将最终获得整个网络的最终输出值在自己的输出值上的梯度。

门单元应该将回传的梯度乘以它对其的输入的局部梯度,从而得到整个网络的输出对该门单元的每个输入值的梯度。

以上图为例子:+这个门单元为例子。它获得*门单元传来的梯度1,它自局部梯度为df/dq=z=-4,所以它的梯度为-4*1=-4。

 

除了上文介绍的加法门,乘法门,取最大值门,还有下面这4种:


\displaystyle f(x)=\frac{1}{x} \to \frac{df}{dx}=-1/x^2
\displaystyle f_c(x)=c+x \to \frac{df}{dx}=1\displaystyle f(x)=e^x \to \frac{df}{dx}=e^x
\displaystyle f_a(x)=ax \to \frac{df}{dx}=a

 

举个实际的例子:

求x和w的梯度。

这里有个小技巧:

\displaystyle\sigma(x)=\frac{1}{1+e^{-x}}\displaystyle\to\frac{d\sigma(x)}{dx}=\frac{e^{-x}}{(1+e^{-x})^2}=(\frac{1+e^{-x}-1}{1+e^{-x}})(\frac{1}{1+e^{-x}})=(1-\sigma(x))\sigma(x)

所以我们令t=w0x0+w1x1+w2所以df/dx=df/dt*dt/dx

w = [2,-3,-3] # 假设一些随机数据和权重
x = [-1, -2]

# 前向传播
t = w[0]*x[0] + w[1]*x[1] + w[2]
f = 1.0 / (1 + math.exp(-t)) # sigmoid函数

# 对神经元反向传播
dt = (1 - f) * f # 点积变量的梯度, 使用sigmoid函数求导
dx = [w[0] * dt, w[1] * dt] # 回传到x
dw = [x[0] * dt, x[1] * dt, 1.0 * dt] # 回传到w
# 完成!得到输入的梯度

分段反向传播上面的代码展示了在实际操作中,为了使反向传播过程更加简洁,把向前传播分成不同的阶段将是很有帮助的。比如我们创建了一个中间变量t,它装着wx的点乘结果。在反向传播的时,就可以(反向地)计算出装着wx等的梯度的对应的变量(比如dtdxdw)。

再举个栗子

前向传播:

sigy = 1.0 / (1 + math.exp(-y))

num = x + sigy  分子

sigx = 1.0 / (1 + math.exp(-x))

xpy = x + y

xpysqr = xpy**2

den = sigx + xpysqr  分母

invden = 1.0 / den 

f = num * invden

反向传播:

dnum = invden 分子的梯度

dinvden = num

dden = (-1.0 / (den**2)) * dinvden 分母的梯度

dxpysqr = (1) * dden

dsigx = (1) * dden

dxpy = (2 * xpy) * dxpysqr

dx = (1) * dxpy 

dy = (1) * dxpy

dx += ((1 - sigx) * sigx) * dsigx  回传 sigx = 1.0 / (1 + math.exp(-x))

dx += (1) * dnum   回传 num = x + sigy

dx += (1) * dnum 

dsigy = (1) * dnum

dy += ((1 - sigy) * sigy) * dsigy

在不同分支的梯度要相加:如果变量x,y在前向传播的表达式中出现多次,那么进行反向传播的时候就要非常小心,使用+=而不是=来累计这些变量的梯度(不然就会造成覆写)。

 

总结:

讨论了分段计算在反向传播的实现中的重要性。应该将函数分成不同的模块,这样计算局部梯度相对容易,然后基于链式法则将其“链”起来。重要的是,不需要把这些表达式写在纸上然后演算它的完整求导公式,因为实际上并不需要关于输入变量的梯度的数学公式。只需要将表达式分成不同的可以求导的模块(模块可以是矩阵向量的乘法操作,或者取最大值操作,或者加法操作等),然后在反向传播中一步一步地计算梯度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值