【深度学习】网络训练原理:前向传播+反向传播

前向传播

前向传播简单理解就是:将上一层的输出作为下一层的输入,并计算下一层的输出,一直到运算到输出层为止。即网络从输入得到最终输出结果的过程

在这里插入图片描述

如上图所示:

  • 输入为 X = [ x 1 x 2 ] = [ 1 0.5 ] X=\begin{bmatrix}x_1\\x_2\end{bmatrix}=\begin{bmatrix}1\\0.5\end{bmatrix} X=[x1x2]=[10.5]

  • 初始化的各个权重分别为 W 1 = [ w 1 w 3 w 2 w 4 ] = [ 0.5 2.3 1.5 3 ] , W 2 = [ w 5 w 6 ] = [ 1 1 ] W_1=\begin{bmatrix}w_1&w_3\\w_2&w_4\end{bmatrix}=\begin{bmatrix}0.5&2.3\\1.5&3\end{bmatrix},W_2=\begin{bmatrix}w_5\\w_6\end{bmatrix}=\begin{bmatrix}1\\1\end{bmatrix} W1=[w1w2w3w4]=[0.51.52.33],W2=[w5w6]=[11]

那么就有:

  • 经过第一个全连接层得到hidden layer的值为 H = [ h 1 h 2 ] = W 1 ⊤ X = [ 0.5 1.5 2.3 3 ] [ 1 0.5 ] = [ 1.25 3.8 ] H=\begin{bmatrix}h_1\\h_2\end{bmatrix}=W_1^\top X=\begin{bmatrix}0.5&1.5\\2.3&3\end{bmatrix}\begin{bmatrix}1\\0.5\end{bmatrix}=\begin{bmatrix}1.25\\3.8\end{bmatrix} H=[h1h2]=W1X=[0.52.31.53][10.5]=[1.253.8]
  • 经过第二个全连接层得到输出值为 y = W 2 ⊤ H = [ 1 1 ] [ 1.25 3.8 ] = 5.05 y=W_2^\top H=\begin{bmatrix}1&1\end{bmatrix}\begin{bmatrix}1.25\\3.8\end{bmatrix}=5.05 y=W2H=[11][1.253.8]=5.05

上述的过程就是前向传播过程,前向传播得到输出,反向传播得到梯度

反向传播

首先考虑我们的梯度下降过程:

θ j = θ j − α ⋅ ∂ L ( θ 0 , θ 1 , ⋯   , θ n ) ∂ θ j \theta_j=\theta_j-\alpha\cdot \frac{\partial L(\theta_0,\theta_1,\cdots,\theta_n)}{\partial \theta_j} θj=θjαθjL(θ0,θ1,,θn)

最核心部分就是计算 ∂ L ( θ ) ∂ θ \frac{\partial L(\theta)}{\partial \theta} θL(θ),其中的 L ( θ ) L(\theta) L(θ)是利用一组样本计算出的损失(如果单独使用一个样本则可能出现噪声影响,因此用一组来尽量得到梯度的正确方向),那么上面这个公式就意味着,我们需要登所有样本都跑出预测结果,才能求梯度对参数进行更新,这显然是不能接受的

而在之前的内容中有提到过,我们使用 C ( y , y ^ ) C(y,\hat y) C(y,y^)衡量预测结果和真实结果之间的差距,注意, C C C是针对一个样本的。那么当我们用包含 m m m个样本的训练集去进行梯度下降时,实际就是:

∂ L ( θ ) ∂ θ = ∑ i = 1 m ∂ C ( y i , y ^ i ) ∂ θ \frac{\partial L(\theta)}{\partial \theta}=\sum_{i=1}^m\frac{\partial C(y_i,\hat y_i)}{\partial\theta} θL(θ)=i=1mθC(yi,y^i)

这样我们就把针对整体的梯度转化为了针对每个样本的梯度之和,进一步的,也对梯度下降的过程针对每个样本进行分解:

  • 每有一个样本通过网络得到预测结果,我们都可以计算出 ∂ C ( y i , y ^ i ) ∂ θ \frac{\partial C(y_i,\hat y_i)}{\partial\theta} θC(yi,y^i),然后直接对所有参数都进行一次更新: θ j = θ j − α ⋅ ∂ C ( y i , y ^ i ) ∂ θ j \theta_j=\theta_j-\alpha\cdot \frac{\partial C(y_i,\hat y_i)}{\partial\theta_j} θj=θjαθjC(yi,y^i),称为 “一步”更新
  • 当所有样本都结束后视作 “一轮”迭代 完成,然后再进行下一轮的迭代

至此,我们就不需要保存所有样本的预测值直到最后才计算梯度更新参数了,而是每通过一个样本就更新一次,节约了存储空间

有了以上的铺垫,我们的主角反向传播就可以出场了

我们知道,在深度学习中往往 C ( y i , y ^ i ) C(y_i,\hat y_i) C(yi,y^i)的表达式十分复杂,甚至有可能中间经过多个激活函数后并不连续可微,这样就无法利用代数方法简单的求出 ∂ C ( y i , y ^ i ) ∂ θ j \frac{\partial C(y_i,\hat y_i)}{\partial\theta_j} θjC(yi,y^i)

而反向传播就是用来计算“一步更新”中的梯度的,它将求导的繁重任务分发给一步更新中的各个计算单元,让我们可以很方便的求出复杂函数针对某个变量的梯度,其核心是链式法则

考虑一个最简单的情况, y = g ( x ) , z = h ( y ) y=g(x),z=h(y) y=g(x),z=h(y),那么 x x x变化会导致 y y y变化进而也会导致 z z z变化,那么我们在计算 z z z x x x y y y的梯度时,可以比较容易的计算出 d z d y , d y d x \frac{dz}{dy},\frac{dy}{dx} dydz,dxdy,因为它们是直接联系的,或者换种说法,他们的函数关系式是显式给出的,梯度可以直接用代数方法求导得出

而当我们想求 d z d x \frac{dz}{dx} dxdz时,我们就发现 z z z x x x之间的函数关系并没有显式给出,而是以复合函数 z = h ( g ( x ) ) z=h\bigl(g(x)\bigr) z=h(g(x))形式出现,当 g ( x ) g(x) g(x) h ( y ) h(y) h(y)的表达式都非常复杂时(例如经过了某个非线性激活函数),直接求 z z z x x x之间的函数关系再求导是非常困难的,此时就需要用到导数链式法则(高数内容):

d z d x = d z d y ⋅ d y d x \frac{dz}{dx}=\frac{dz}{dy}\cdot\frac{dy}{dx} dxdz=dydzdxdy

所以我们只需要在每一步中关注每个计算单元的求梯度过程,就能在利用链式法则求出所有参数在一步中的梯度,从而进行参数更新

再以一开始的前向传播结果为例,反向传播就是利用链式法则得到各个参数的梯度值:

在这里插入图片描述

通过前向传播从input layer到output layer方向得到各层的输出值后,再从output layer返回input layer进行反向传播,具体步骤为:

  1. 通过前向传播得到的输出 y y y和output layer的输入 w 5 , w 6 , h 1 , h 2 w_5,w_6,h_1,h_2 w5,w6,h1,h2可以分别求出 ∂ y ∂ w 5 , ∂ y ∂ w 6 , ∂ y ∂ h 1 , ∂ y ∂ h 2 \frac{\partial y}{\partial w_5},\frac{\partial y}{\partial w_6},\frac{\partial y}{\partial h_1},\frac{\partial y}{\partial h_2} w5y,w6y,h1y,h2y,更新参数 w 5 , w 6 w_5,w_6 w5,w6后,将这些梯度值作为输入传给hidden layer

    对于某层来说,输入、输出和参数都是已知量,配合pytorch代码理解更佳

  2. hidden layer接收输入 ∂ y ∂ w 5 , ∂ y ∂ w 6 , ∂ y ∂ h 1 , ∂ y ∂ h 2 \frac{\partial y}{\partial w_5},\frac{\partial y}{\partial w_6},\frac{\partial y}{\partial h_1},\frac{\partial y}{\partial h_2} w5y,w6y,h1y,h2y,再配合其前向传播时得到的 w 1 , w 2 , w 3 , w 4 , x 1 , x 2 w_1,w_2,w_3,w_4,x_1,x_2 w1,w2,w3,w4,x1,x2,可以分别求出 ∂ y ∂ w 1 , ∂ y ∂ w 2 , ∂ y ∂ w 3 , ∂ y ∂ w 4 \frac{\partial y}{\partial w_1},\frac{\partial y}{\partial w_2},\frac{\partial y}{\partial w_3},\frac{\partial y}{\partial w_4} w1y,w2y,w3y,w4y,更新参数 w 1 , w 2 , w 3 , w 4 w_1,w_2,w_3,w_4 w1,w2,w3,w4后,将这些梯度作为输入传给input layer

    这里其实也可以求出 ∂ y ∂ x 1 , ∂ y ∂ x 2 \frac{\partial y}{\partial x_1},\frac{\partial y}{\partial x_2} x1y,x2y,因为这两个值并没有用(不需要对输入进行更新),所以没写上去

  3. input layer不需要求梯度和更新参数,反向传播结束

可以看出,有了反向传播后,每有一个样本经过网络,就可以对网络的参数进行一次更新,而不需将所有样本都经过网络后再更新了

更复杂的例子可以参考:反向传播详解,这里不详细展开,这个过程其实并不难,重点是要清楚各个激活函数进行反向传播时计算的梯度值,这一内容在后面的内容展开讲

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值