zoukankan      html  css  js  c++  java
  • 反向传播算法

    反向传播算法, Backpropagation, BP


    1986年, Hinton, 深度学习之父, 和他的合作者发表了论文"Learning Representations by Back-propagating errors", 首次系统地描述了如何利用BP算法有训练神经网络. 从这一年开始, BP在有监督的神经网络算法中占着核心地位. 它描述了如何利用错误信息, 从最后一层(输出层)开始到第一个隐层, 逐步调整权值参数, 达到学习的目的.

    以MLP为例说明BP的详细过程. 假设这个多层神经网络共有L层, 输入层为layer 1, 输出层为layer L, 中间的(L-2)层为隐层. 第(l)层第(i)个神经元的净输出(过激活函数之前的输出)为(net^l_i), 它的(激活)输出为(a^l_i). 同一层神经元使用相同的激活函数(f^{l}(net_l))

    BP算法从整体上来说分为两步: 前向反馈(feedforward)与反向传播(Backpropagate).

    Feedforward

    feedforward 的过程是指信息从输入层开始单向向前传播, 经过隐层, 最后到输出层, 得到整个网络的输出. 一句话概括就是第(l-1)层的输出作为第(l)层的输入.

    输入层:

    [a^1 = x ]

    其中, (x)为输入的样本, 一个(c^1)维列向量.

    隐层:

    [a^l = f^{l-1}(W^la^{l-1} + b^l) ]

    (f^{l-1})为第(l-1)层的激活函数. (W^l, b^l)分别为第(l)层的权值矩阵与bias. (W^l: c^l imes c^{l-1}), (b: c^l imes 1)

    输出层:

    [output = a^L ]

    Backpropagation

    输出层的梯度计算

    错误信息指的是网络的输出与目标值的差异. 差异的大小用损失函数表示. 先考虑在单个样本(x)上的损失:

    [J = J(x, y, W^L, W^{L-1}, dots, W^1, b^L, b^{L-1}, dots, b^1) ]

    它是一个关于输入样本(x), 目标值(y), 和神经网络参数(W,b)的多变量函数.

    然后根据(J)调整输出层layer (L)的参数(W^L, b^l). 先从单个参数开始, 一步步地从实数计算到矩阵计算. 第(L)层第(i)个神经元的权值参数为(w^L_i), 它的第(j)个值为(w^L_{ij}). 利用chain rule求(J)关于它的偏导:
    egin{equation}label{wholechain}
    frac {partial J}{partial w^L_{ij}} = frac {partial J}{partial net^L_{i}} frac {partial net^L}{partial w^L_{ij}}
    end{equation}

    (frac {partial J}{partial net^L_{i}})这部分用(delta^L_i)表示, 称为这个神经元的敏感度, 什么对什么的敏感度呢? 错误程度对净输出(net)的敏感度.
    egin{equation}label{sensitivityOfLi}
    delta^L_i = frac {partial J}{partial net^L_i} = frac {partial J}{partial a^L_i} frac{partial a^L_i}{partial net^L_i} = frac {partial J}{partial a^L_i} f^{L'}(net^L_i)
    end{equation}

    (L-1)层的输出传入(L)层的时候, 与(w^L_{ij})相乘的值为(a^{L-1}_j)
    egin{equation}label{weightOutput}
    frac {partial net^L}{partial w^L_{ij}} = a^{L-1}-j
    end{equation}

    (( ef{weightOutput}))(( ef{sensitivityOfLi}))代入(( ef{wholechain}))得:
    egin{equation}label{wholechain2}
    Delta w^L_{ij} = frac {partial J}{partial w^L{ij}} = delta^L_i a^{L-1}_j
    end{equation}

    然后算(b^L_i)的偏导:

    [Delta b^L_i = frac {partial J}{partial b^L_i} = frac {partial J}{partial net^L_{i}} frac {partial net^L}{partial b^L_i} = delta^L_i ]

    也就是说神经元的(bias)偏导值等于它的敏感度(delta).

    接下来看整个神经元的权值梯度:

    [Delta w^L_i = left[egin{matrix} Delta w^L_{i1}\ Delta w^L_{i2}\ vdots \ Delta w^L_{ic^{L-1}} end{matrix} ight] = delta^L_i a^{L-1} ]

    然后是整个第(L)层的权值梯度:

    [Delta w^L = left[egin{matrix} Delta {w^L_{1}}^T\ Delta {w^L_{2}}^T\ vdots \ Delta {w^L_{c^L}}^T end{matrix} ight] = delta^L {a^{L-1}}^T ]

    隐层的梯度计算

    隐层的计算比输出层要复杂一些. 先计算第(l)层第(j)个神经元的敏感度.

    [delta^{l}_j = frac {partial J}{partial net^l_j} = frac {partial J}{partial a^l_j} frac {partial a^l_j}{partial net^l_j} = frac {partial J}{partial a^l_j} f^{l'}(net^l_j) ]

    麻烦的一部分就是(frac {partial J}{partial a^l_j}). 因为(a^l_j)会作为输入的一部分传入到下一层与它相连的所有神经元里. 因为这里是以全连接的MLP为例, 所以是(l+1)层的所有神经元, 若不是全连接层, 如conv层, 就不是(l+1)层的所有神经元.

    [frac {partial J}{partial a^l_j} = sum_{i = 1}^{c^{l+1}} frac {partial J} {partial net^{l+1}_i} frac {partial net^{l+1}_i}{partial a^{l}_j} = sum_{i = 1}^{c^{l+1}} delta^{l+1}_i w^{l+1}_{ij} ]

    代入上一个式子得:

    [delta^{l}_j = frac {partial J}{partial net^l_j} = sum_{i = 1}^{c^{l+1}} delta^{l+1}_i w^{l+1}_{ij} f^{l'}(net^l_j) ]

    这是一个很重要的式子, 因为它说明(l)层的神经元敏感度与第(l+1)层中跟它连接的神经元敏感度的加权和成正比.

    (l)层的敏感度为:

    [delta^{l} = W^{l + 1} delta^{l + 1} circ f^{l'}(net^l_j) ]

    (circ)代表element-wise向量乘法, 例如((a_1, a_2)circ(b_1, b_2) = (a_1b_1, a_2b_2)).

    根据之前推导过的输出层的形式, 可以直接写出第(l)层的权值梯度

    [Delta w^l = delta^l {a^{l-1}}^T ]

    bias的梯度值就是当前层的敏感度:

    [Delta b^l = delta^l ]

    更新参数

    [W^l gets W^l - Delta W^l ]

    [b^l gets b^l - Delta b^l ]


    以上就是BP算法的核心推导过程了. # 需要记住的要点 可以看出**它的关键就在于各层神经元敏感度的计算**. 需要记住**第$l$层的神经元敏感度与第$l+1$层与之连接的神经元敏感度的加权和成正比. 比例因子为各自激活函数的导数值**, 即 $$ delta^l = W^{l+1} delta^{l+1} circ {f^l}'(net^l) $$ 得到敏感度后就可以得到梯度值: $$ Delta W^l = delta^l {a^{l-1}}^T $$ $$ Delta b^l = delta^l $$
  • 相关阅读:
    Ubuntu 服务器默认的root账号是没有激活的,需要用初装的用户账号给root设置管理密码
    MySQL忘记root密码重置密码(5.7版本)
    SpringMvc与前台ajax数据传递
    将http://localhost:8080设置为项目主页
    javaweb项目主页设置
    Redis在java开发中使用
    eclipse基于git上传项目到码云上
    spring配置tomcat jdbc pool数据库连接池
    run as maven build时报错
    Tomcat-Jdbc-Pool连接池参数说明
  • 原文地址:https://www.cnblogs.com/dengdan890730/p/5537451.html
Copyright © 2011-2022 走看看