图解反向传播流程

图源CS231n课程slider

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

  • 反向传播计算过程如下:

\(\frac{\partial f}{\partial f}=1\)

\(f=q*z\)

\(\frac{\partial f}{\partial z}=q=3\) ; \(\frac{\partial f}{\partial q}=z=-4\)

\(q=x+y\)

\(\frac{\partial f}{\partial x}=\frac{\partial f}{\partial q}*\frac{\partial q}{\partial x}=z*1=-4\) ; \(\frac{\partial f}{\partial y}=\frac{\partial f}{\partial q}*\frac{\partial q}{\partial y}=z*1=-4\)

  • Python代码实现

# 设置输入值
x = ‐2; y = 5; z = ‐4

# 进行前向传播
q = x + y # q becomes 3
f = q * z # f becomes ‐12

# 进行反向传播:
# 首先回传到 f = q * z
dfdz = q  # df/dz = q, 所以关于z的梯度是3
dfdq = z  # df/dq = z, 所以关于q的梯度是‐4

# 现在回传到q = x + y
dfdx = 1.0 * dfdq # dq/dx = 1. 这里的乘法是因为链式法则
dfdy = 1.0 * dfdq # dq/dy = 1
  • 反向传播可以看做是门单元之间在通过梯度信号相互通信,只要让它们的输入沿着梯度方向变化,无论它们
    自己的输出值在何种程度上升或降低,都是为了让整个网络的输出值更高

图源CS231n课程slider

门是相对随意的,任何可微分的函数都可以看做门。可以将多个门组合成一个门,也可以根据需要将一
个函数分拆成多个门。如下列表达式:

\[f(w,x)=\frac{1}{1+e^{-(w_0x_0+w_1x_1+w_2x_2)}} \]

  • 反向传播计算过程如下:

    • [local gradient] x [upstream gradient]

\(\frac{\partial f}{\partial f}=1\)

\(f(x)=\frac{1}{x}\) \(\frac{\partial f}{\partial x}=-\frac{1}{x^2}=-\frac{1}{1.37^2}=-0.53\) \(-0.53*1=-0.53\)

\(f_7(x)=x+1\) $\frac{\partial f}{\partial x}=$1 \(1*(-0.53)=-0.53\)

\(f_6(x)=e^x\) \(\frac{\partial f}{\partial x}=e^x=e^{-1}=0.37\) \(0.37*(-0.53)=-0.20\)

\(f_5(x)=x*(-1)\) \(\frac{\partial f}{\partial x}=-1\) $ -1*(-0.20)=0.20$

\(f_4(x)=f_3+w_2\) \(\frac{\partial f_4}{\partial f_3}=1\) \(1*0.20=0.20\)

\(\frac{\partial f_4}{\partial w_2}=1\) \(1*0.20=0.20\)

\(f_3(x)=f_1+f_2\) \(\frac{\partial f_3}{\partial f_1}=1\) \(1*0.20=0.20\)

\(\frac{\partial f_3}{\partial f_2}=1\) \(1*0.20=0.20\)

\(f_2(x)=w_0*x_0\) \(\frac{\partial f_2}{\partial w_0}=x_0=-1\) \((-1)*0.20=-0.20\)

\(\frac{\partial f_2}{\partial x_0}=w_0=2\) \(2*0.20=0.40\)

\(f_1(x)=w_1*x_1\) \(\frac{\partial f_1}{\partial w_1}=x_1=-2\) \((-2)*0.20=-0.40\)

\(\frac{\partial f_1}{\partial x_1}=w_1=-3\) \((-3)*0.20=-0.60\)

  • \(f_4\)\(f\)之间的运算可以简化为sigmoid函数\(\sigma(x)\)

激活函数sigmoid函数\sigma(x)

  • Python代码实现

​ 为了使反向传播过程更加简洁,把向前传播分成不同的阶段将是很有帮助的。比如我们创建了一个中间变量dot,它装着w和x的点乘结果。在反向传播的时,就可以(反向地)计算出装着w和x等的梯度的对应的变量(比如ddot,dx和dw)。

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

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

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

# 完成!得到输入的梯度

参考链接

【1】CS231n 课堂slider

【2】https://zhuanlan.zhihu.com/p/21930884

posted @ 2019-03-09 21:45  清风与归_G  阅读(1884)  评论(0编辑  收藏  举报