神经网络之反向传播算法(BP)公式推导

反向传播算法详细推导

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。 在神经网络上执行梯度下降法的主要算法。该算法会先按前向传播方式计算(并缓存)每个节点的输出值,然后再按反向传播遍历图的方式计算损失函数值相对于每个参数的偏导数。

我们将以全连接层,激活函数采用 Sigmoid 函数,误差函数为 Softmax+MSE 损失函数的神经网络为例,推导其梯度传播方式。

准备工作

1、Sigmoid 函数的导数

回顾 sigmoid 函数的表达式:
σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1+e^{-x}} σ(x)=1+ex1
其导数为:
d d x σ ( x ) = d d x ( 1 1 + e − x ) \frac{d}{dx}\sigma(x) = \frac{d}{dx} \left(\frac{1}{1+e^{-x}} \right) dxdσ(x)=dxd(1+ex1)

= e − x ( 1 + e − x ) 2 = \frac{e^{-x}}{(1+e^{-x})^2} =(1+ex)2ex

= ( 1 + e − x ) − 1 ( 1 + e − x ) 2 = \frac{(1 + e^{-x})-1}{(1+e^{-x})^2} =(1+ex)2(1+ex)1

= 1 + e − x ( 1 + e − x ) 2 − ( 1 1 + e − x ) 2 =\frac{1+e^{-x}}{(1+e^{-x})^2} - \left(\frac{1}{1+e^{-x}}\right)^2 =(1+ex)21+ex(1+ex1)2

= σ ( x ) − σ ( x ) 2 = \sigma(x) - \sigma(x)^2 =σ(x)σ(x)2

= σ ( 1 − σ ) = \sigma(1-\sigma) =σ(1σ)

可以看到,Sigmoid 函数的导数表达式最终可以表达为激活函数的输出值的简单运算,利
用这一性质,在神经网络的梯度计算中,通过缓存每层的 Sigmoid 函数输出值,即可在需
要的时候计算出其导数。Sigmoid 函数导数的实现:

import numpy as np # 导入 numpy

def sigmoid(x): # sigmoid 函数
	return 1 / (1 + np.exp(-x))

def derivative(x): # sigmoid 导数的计算
	return sigmoid(x)*(1-sigmoid(x))
2、均方差函数梯度

均方差损失函数表达式为:
L = 1 2 ∑ k = 1 K ( y k − o k ) 2 L = \frac{1}{2}\sum_{k=1}^{K}(y_k-o_k)^2 L=21k=1K(ykok)2
其中 y k y_k yk为真实值, o k o_k ok为输出值。则它的偏导数 ∂ L ∂ o i \frac{\partial L}{\partial o_i} oiL 可以展开为:
∂ L ∂ o i = 1 2 ∑ k = 1 K ∂ ∂ o i ( y k − o k ) 2 \frac{\partial L}{\partial o_i} = \frac{1}{2}\sum_{k=1}^{K}\frac{\partial}{\partial o_i}(y_k - o_k)^2 oiL=21k=1Koi(ykok)2
利用链式法则分解为
∂ L ∂ o i = 1 2 ∑ k = 1 K ⋅ 2 ⋅ ( y k − o k ) ⋅ ∂ ( y k − o k ) ∂ o i \frac{\partial L}{\partial o_i} = \frac{1}{2}\sum_{k=1}^{K}\cdot2\cdot(y_k-o_k)\cdot\frac{\partial(y_k-o_k)}{\partial o_i} oiL=21k=1K2(ykok)oi(ykok)

∂ L ∂ o i = ∑ k = 1 K ( y k − o k ) ⋅ ( − 1 ) ⋅ ∂ o k ∂ o i \frac{\partial L}{\partial o_i} = \sum_{k=1}^{K}(y_k-o_k)\cdot(-1)\cdot\frac{\partial o_k}{\partial o_i} oiL=k=1K(ykok)(1)oiok

∂ o k ∂ o i \frac{\partial o_k}{\partial o_i} oiok仅当 k = i 时才为 1,其他点都为0, 也就是说 ∂ o k ∂ o i \frac{\partial o_k}{\partial o_i} oiok只与第 i号节点相关,与其他节点无关,因此上式中的求和符号可以去掉,均方差的导数可以推导为
∂ L ∂ o i = ( o i − y i ) \frac{\partial L}{\partial o_i} = (o_i - y_i) oiL=(oiyi)

单个神经元梯度

对于采用 Sigmoid 激活函数的神经元模型,它的数学模型可以写为
o 1 = σ ( w 1 x + b 1 ) o^1 = \sigma(w^1x+b^1) o1=σ(w1x+b1)
其中

  • 变量的上标表示层数,如 o 1 o^1 o1 表示第一个隐藏层的输出
  • x 表示网络的输入

单个神经元模型如下图所示

  • 输入节点数为 J
    • 其中输入第 j j j 个节点到输出 o 1 o^1 o1 的权值连接记为 w j 1 1 w^1_{j1} wj11
  • 上标表示权值属于的层数,下标表示当前连接的起始节点号和终止节点号
    • 如下标 j 1 j1 j1 表示上一层的第 j j j 号节点到当前层的 1 号节点
  • 未经过激活函数的输出变量为 z 1 1 z_1^1 z11,经过激活函数之后的输出为 o 1 1 o_1^1 o11
  • 由于只有一个输出节点,故 o 1 1 = o 1 o_1^1 = o^1 o11=o1

在这里插入图片描述

下面我们来计算均方差算是函数的梯度

由于单个神经元只有一个输出,那么损失函数可以表示为
L = 1 2 ( o 1 1 − t ) 2 L = \frac{1}{2}(o_1^1 - t)^2 L=21(o11t)2
添加 1 2 \frac{1}{2} 21 是为了计算方便,我们以权值连接的第 j ∈ [ 1 , J ] j\in[1,J] j[1,J] 号节点的权值 w j 1 w_{j1} wj1 为例,考虑损失函数 L L L 对其的偏导数 ∂ L ∂ w j 1 \frac{\partial L}{\partial w_{j1}} wj1L
∂ L ∂ w j 1 = ( o 1 − t ) ∂ o 1 ∂ w j 1 \frac{\partial L}{\partial w_{j1}} = (o_1 - t)\frac{\partial o_1}{\partial w_{j1}} wj1L=(o1t)wj1o1
由于 o 1 = σ ( z 1 ) o_1 = \sigma(z_1) o1=σ(z1) ,由上面的推导可知 Sigmoid 函数的导数 σ ′ = σ ( 1 − σ ) \sigma' = \sigma(1-\sigma) σ=σ(1σ)
∂ L ∂ w j 1 = ( o 1 − t ) ∂ σ ( z 1 ) ∂ w j 1 \frac{\partial L}{\partial w_{j1}} = (o_1 - t)\frac{\partial \sigma(z_1)}{\partial w_{j1}} wj1L=(o1t)wj1σ(z1)

= ( o 1 − t ) σ ( z 1 ) ( 1 − σ ( z 1 ) ) ∂ z 1 ∂ w j 1 = (o_1-t)\sigma(z_1)(1-\sigma(z_1))\frac{\partial z_1}{\partial w_{j1}} =(o1t)σ(z1)(1σ(z1))wj1z1

σ ( z 1 ) \sigma(z_1) σ(z1) 写成 o 1 o_1 o1
= ( o 1 − t ) o 1 ( 1 − o 1 ) ∂ z 1 ∂ w j 1 = (o_1-t)o_1(1-o_1)\frac{\partial z_1}{\partial w_{j1}} =(o1t)o1(1o1)wj1z1
由于 ∂ z 1 ∂ w j 1 = x j \frac{\partial z_1}{\partial w_{j1}} = x_j wj1z1=xj
∂ L ∂ w j 1 = ( o 1 − t ) o 1 ( 1 − o 1 ) x j \frac{\partial L}{\partial w_{j1}} = (o_1-t)o_1(1-o_1)x_j wj1L=(o1t)o1(1o1)xj
从上式可以看到,误差对权值 w j 1 w_{j1} wj1 的偏导数只与输出值 o 1 o_1 o1 、真实值 t 以及当前权值连接的输 x j x_j xj 有关

全链接层梯度

我们把单个神经元模型推广到单层全连接层的网络上,如下图所示。输入层通过一个全连接层得到输出向量 o 1 o^1 o1 ,与真实标签向量 t 计算均方差。输入节点数为 J J J ,输出节点数为 K

在这里插入图片描述

与单个神经元不同,全链接层有多个输出节点 o 1 1 , o 2 1 , o 3 1 , . . . , o K 1 o_1^1, o_2^1, o_3^1,...,o_K^1 o11,o21,o31,...,oK1 ,每个输出节点对应不同真实标签 t 1 , t 2 , t 3 , . . . , t K t_1, t_2, t_3,..., t_K t1,t2,t3,...,tK ,均方误差可以表示为
L = 1 2 ∑ i = 1 K ( o i 1 − t i ) 2 L = \frac{1}{2}\sum_{i=1}^K(o_i^1-t_i)^2 L=21i=1K(oi1ti)2
由于 ∂ L ∂ w j k \frac{\partial L}{\partial w_{jk}} wjkL 只与 o k 1 o_k^1 ok1 有关联,上式中的求和符号可以去掉,即 i = k i = k i=k
∂ L ∂ w j k = ( o k − t k ) ∂ o k ∂ w j k \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)\frac{\partial o_k}{\partial w_{jk}} wjkL=(oktk)wjkok
o k = σ ( z k ) o_k=\sigma(z_k) ok=σ(zk) 带入
∂ L ∂ w j k = ( o k − t k ) ∂ σ ( z k ) ∂ w j k \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)\frac{\partial \sigma(z_k)}{\partial w_{jk}} wjkL=(oktk)wjkσ(zk)
考虑 S i g m o i d Sigmoid Sigmoid 函数的导数 σ ′ = σ ( 1 − σ ) \sigma' = \sigma(1-\sigma) σ=σ(1σ)
∂ L ∂ w j k = ( o k − t k ) σ ( z k ) ( 1 − σ ( z k ) ) ∂ z k 1 ∂ w j k \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)\sigma(z_k)(1-\sigma(z_k))\frac{\partial z_k^1}{\partial w_{jk}} wjkL=(oktk)σ(zk)(1σ(zk))wjkzk1
σ ( z k ) \sigma(z_k) σ(zk) 记为 o k o_k ok
∂ L ∂ w j k = ( o k − t k ) o k ( 1 − o k ) ∂ z k 1 ∂ w j k \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)o_k(1-o_k)\frac{\partial z_k^1}{\partial w_{jk}} wjkL=(oktk)ok(1ok)wjkzk1
最终可得
∂ L ∂ w j k = ( o k − t k ) o k ( 1 − o k ) ⋅ x j \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)o_k(1-o_k)\cdot x_j wjkL=(oktk)ok(1ok)xj
由此可以看到,某条连接 w j k w_{jk} wjk 上面的连接,只与当前连接的输出节点 o k 1 o_k^1 ok1 ,对应的真实值节点的标签 t k 1 t_k^1 tk1 ,以及对应的输入节点 x 有关。

我们令 δ k = ( o k − t k ) o k ( 1 − o k ) \delta_k = (o_k-t_k)o_k(1-o_k) δk=(oktk)ok(1ok) ,则 ∂ L ∂ w j k \frac{\partial L}{\partial w_{jk}} wjkL 可以表达为
∂ L ∂ w j k = δ k ⋅ x j \frac{\partial L}{\partial w_{jk}}=\delta_k\cdot x_j wjkL=δkxj
其中 δ k \delta _k δk 变量表征连接线的终止节点的梯度传播的某种特性,使用 δ k \delta_k δk 表示后, ∂ L ∂ w j k \frac{\partial L}{\partial w_{jk}} wjkL 偏导数只与当前连接的起始节点 x j x_j xj,终止节点处 δ k \delta_k δk 有关,理解起来比较直观。

反向传播算法

看到这里大家也不容易,毕竟这么多公式哈哈哈,不过激动的时刻到了

先回顾下输出层的偏导数公式
∂ L ∂ w j k = ( o k − t k ) o k ( 1 − o k ) ⋅ x j = δ k ⋅ x j \frac{\partial L}{\partial w_{jk}} = (o_k-t_k)o_k(1-o_k)\cdot x_j = \delta_k \cdot x_j wjkL=(oktk)ok(1ok)xj=δkxj
多层全连接层如下图所示

  • 输出节点数为 K ,输出 o k = [ o 1 k , o 2 k , o 3 k , . . . , o k k ] o^k = [o_1^k, o_2^k, o_3^k,..., o_k^k] ok=[o1k,o2k,o3k,...,okk]
  • 倒数的二层的节点数为 J ,输出为 o J = [ o 1 J , o 2 J , . . . , o J J ] o^J=[o_1^J, o_2^J,..., o_J^J] oJ=[o1J,o2J,...,oJJ]
  • 倒数第三层的节点数为 I ,输出为 o I = [ o 1 I , o 2 I , . . . , o I I ] o^I = [o_1^I, o_2^I,..., o_I^I] oI=[o1I,o2I,...,oII]

在这里插入图片描述

均方误差函数
∂ L ∂ w i j = ∂ ∂ w i j 1 2 ∑ k ( o k − t k ) 2 \frac{\partial L}{\partial w_{ij}}=\frac{\partial}{\partial w_{ij}}\frac{1}{2}\sum_{k}(o_k-t_k)2 wijL=wij21k(oktk)2
由于 L L L 通过每个输出节点 o k o_k ok w i w_i wi 相关联,故此处不能去掉求和符号
∂ L ∂ w i j = ∑ k ( o k − t k ) ∂ o k ∂ w i j \frac{\partial L}{\partial w_{ij}}=\sum_k(o_k-t_k)\frac{\partial o_k}{\partial w_{ij}} wijL=k(oktk)wijok
o k = σ ( z k ) o_k=\sigma(z_k) ok=σ(zk) 带入
∂ L ∂ w i j = ∑ k ( o k − t k ) ∂ σ ( z k ) ∂ w i j \frac{\partial L}{\partial w_{ij}}=\sum_k(o_k-t_k)\frac{\partial \sigma(z_k)}{\partial w_{ij}} wijL=k(oktk)wijσ(zk)
S i g m o i d Sigmoid Sigmoid 函数的导数 σ ′ = σ ( 1 − σ ) \sigma' = \sigma(1-\sigma) σ=σ(1σ) ,继续求导,并将 σ ( z k ) \sigma(z_k) σ(zk) 写回 o k o_k ok
∂ L ∂ w i j = ∑ k ( o k − t k ) o k ( 1 − o k ) ∂ z k ∂ w i j \frac{\partial L}{\partial w_{ij}}=\sum_k(o_k-t_k)o_k(1-o_k)\frac{\partial z_k}{\partial w_{ij}} wijL=k(oktk)ok(1ok)wijzk
对于 ∂ z k ∂ w i j \frac{\partial z_k}{\partial w_{ij}} wijzk 可以应用链式法则分解为
∂ z k ∂ w i j = ∂ z k o j ⋅ ∂ o j ∂ w i j \frac{\partial z_k}{\partial w_{ij}} = \frac{\partial z_k}{o_j}\cdot \frac{\partial o_j}{\partial w_{ij}} wijzk=ojzkwijoj
由图可知 ( z k = o j ⋅ w j k + b k ) \left(z_k = o_j \cdot w_{jk} + b_k\right) (zk=ojwjk+bk) ,故有
∂ z k o j = w j k \frac{\partial z_k}{o_j} = w_{jk} ojzk=wjk
所以
∂ L ∂ w i j = ∑ k ( o k − t k ) o k ( 1 − o k ) w j k ⋅ ∂ o j ∂ w i j \frac{\partial L}{\partial w_{ij}}=\sum_k(o_k-t_k)o_k(1-o_k)w_{jk}\cdot\frac{\partial o_j}{\partial w_{ij}} wijL=k(oktk)ok(1ok)wjkwijoj
考虑到 ∂ o j ∂ w i j \frac{\partial o_j}{\partial w_{ij}} wijojk 无关,可将其提取出来
∂ L ∂ w i j = ∂ o j ∂ w i j ⋅ ∑ k ( o k − t k ) o k ( 1 − o k ) w j k \frac{\partial L}{\partial w_{ij}}=\frac{\partial o_j}{\partial w_{ij}}\cdot\sum_k(o_k-t_k)o_k(1-o_k)w_{jk} wijL=wijojk(oktk)ok(1ok)wjk
再一次有 o k = σ ( z k ) o_k=\sigma(z_k) ok=σ(zk) ,并利用 S i g m o i d Sigmoid Sigmoid 函数的导数 σ ′ = σ ( 1 − σ ) \sigma' = \sigma(1-\sigma) σ=σ(1σ)
∂ L ∂ w i j = o j ( 1 − o j ) ∂ z j ∂ w i j ⋅ ∑ k ( o k − t k ) o k ( 1 − o k ) w j k \frac{\partial L}{\partial w_{ij}}= o_j(1-o_j)\frac{\partial z_j}{\partial w_{ij}} \cdot\sum_k(o_k-t_k)o_k(1-o_k)w_{jk} wijL=oj(1oj)wijzjk(oktk)ok(1ok)wjk
由于 ∂ z j ∂ w i j = o i ( z j = o i ⋅ w i j + b j ) \frac{\partial z_j}{\partial w_{ij}} = o_i \left(z_j = o_i\cdot w_{ij} + b_j\right) wijzj=oi(zj=oiwij+bj)
∂ L ∂ w i j = o j ( 1 − o j ) o i ⋅ ∑ k ( o k − t k ) o k ( 1 − o k ) w j k \frac{\partial L}{\partial w_{ij}}= o_j(1-o_j)o_i \cdot\sum_k(o_k-t_k)o_k(1-o_k)w_{jk} wijL=oj(1oj)oik(oktk)ok(1ok)wjk
其中 δ k K = ( o k − t k ) o k ( 1 − o k ) \delta _k^K = (o_k-t_k)o_k(1-o_k) δkK=(oktk)ok(1ok) ,则
∂ L ∂ w i j = o j ( 1 − o j ) o i ⋅ ∑ k δ k K ⋅ w j k \frac{\partial L}{\partial w_{ij}}= o_j(1-o_j)o_i \cdot\sum_k\delta _k^K\cdot w_{jk} wijL=oj(1oj)oikδkKwjk
仿照输出层的书写方式,定义
δ j J = o j ( 1 − o j ) ⋅ ∑ k δ k K ⋅ w j k \delta_j^J = o_j(1-o_j) \cdot \sum_k \delta _k^K\cdot w_{jk} δjJ=oj(1oj)kδkKwjk
此时 ∂ L ∂ w i j \frac{\partial L}{\partial w_{ij}} wijL 可以写为当前连接的起始节点的输出值 o i o_i oi 与终止节点 j j j 的梯度信息 δ j J \delta _j^J δjJ 的简单相乘运算:
∂ L ∂ w i j = δ j J ⋅ o i I \frac{\partial L}{\partial w_{ij}} = \delta_j^J\cdot o_i^I wijL=δjJoiI
通过定义 δ \delta δ 变量,每一层的梯度表达式变得更加清晰简洁,其中 $ \delta $ 可以简单理解为当前连接 w i j w_{ij} wij 对误差函数的贡献值。

总结

输出层:
∂ L ∂ w j k = δ k K ⋅ o j \frac{\partial L}{\partial w_{jk}} = \delta _k^K\cdot o_j wjkL=δkKoj

δ k K = ( o k − t k ) o k ( 1 − o k ) \delta _k^K = (o_k-t_k)o_k(1-o_k) δkK=(oktk)ok(1ok)

倒数第二层:
∂ L ∂ w i j = δ j J ⋅ o i \frac{\partial L}{\partial w_{ij}} = \delta _j^J\cdot o_i wijL=δjJoi

δ j J = o j ( 1 − o j ) ⋅ ∑ k δ k K ⋅ w j k \delta_j^J = o_j(1-o_j) \cdot \sum_k \delta _k^K\cdot w_{jk} δjJ=oj(1oj)kδkKwjk

倒数第三层:
∂ L ∂ w n i = δ i I ⋅ o n \frac{\partial L}{\partial w_{ni}} = \delta _i^I\cdot o_n wniL=δiIon

δ i I = o i ( 1 − o i ) ⋅ ∑ j δ j J ⋅ w i j \delta _i^I = o_i(1-o_i)\cdot \sum_j\delta_j^J\cdot w_{ij} δiI=oi(1oi)jδjJwij

其中 o n o_n on 为倒数第三层的输入,即倒数第四层的输出

依照此规律,只需要循环迭代计算每一层每个节点的 δ k K , δ j J , δ i I , . . . \delta _k^K, \delta_j^J, \delta_i^I,... δkK,δjJ,δiI,... 等值即可求得当前层的偏导数,从而得到每层权值矩阵 W W W 的梯度,再通过梯度下降算法迭代优化网络参数即可。

好了,反向传播算法推导完毕,代码实现可以参考另一篇博客神经网络之动手实现反向传播(BP)算法

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值