神经网络反向传播的数学原理(转)

若是能二秒内在脑壳里解出下面的问题,本文便结束了。php

已知:[公式],其中[公式]编程

求:[公式][公式][公式]网络



到这里,请耐心看完下面的公式推导,无需长久内心建设。数据结构

首先,反向传播的数学原理是“求导的链式法则” :函数

[公式][公式][公式]的可导函数,则[公式]优化

接下来介绍3d

  • 矩阵、向量求导的维数相容原则
  • 利用维数相容原则快速推导反向传播
  • 编程实现前向传播、反向传播
  • 卷积神经网络的反向传播

快速矩阵、向量求导

这一节展现如何使用链式法则、转置、组合等技巧来快速完成对矩阵、向量的求导orm

一个原则维数相容,实质是多元微分基本知识,没有在课本中找到下列内容,维数相容原则是我我的总结:教程

维数相容原则:经过先后换序、转置 使求导结果知足矩阵乘法且结果维数知足下式:ci

若是[公式], [公式],那么[公式]

利用维数相容原则解上例:

step1:把全部参数当作实数来求导,[公式]

依据链式法则有[公式][公式][公式]

能够看出除了[公式][公式][公式]的求导结果在维数上连矩阵乘法都不能知足。

step2:根据step1的求导结果,依据维数相容原则作调整:先后换序、转置

依据维数相容原则[公式],但[公式][公式][公式],天然得调整为[公式]

同理:[公式],但 [公式][公式][公式],那么经过换序、转置咱们能够获得维数相容的结果[公式]

对于矩阵、向量求导:

  • “当作一维实数使用链式法则求导,而后作维数相容调整,使之符合矩阵乘法原则且维数相容”是快速准确的策略;
  • “对单个元素求导、再整理成矩阵形式”这种方式整理是困难的、过程是缓慢的,结果是易出错的(不信你试试)。


如何证实通过维数相容原则调整后的结果是正确的呢?直觉!简单就是美...

快速反向传播

神经网络的反向传播求得“各层”参数[公式][公式]的导数,使用梯度降低(一阶GD、SGD,二阶LBFGS、共轭梯度等)优化目标函数。

接下来,展现不使用下标的记法([公式][公式]or[公式])直接对[公式][公式]求导,反向传播是链式法则和维数相容原则的完美体现,对每一层参数的求导利用上一层的中间结果完成。

这里的标号,参考UFLDL教程 - Ufldl

前向传播:

[公式] (公式1)

[公式] (公式2)

[公式]为第[公式]层的中间结果,[公式]为第[公式]层的激活值,其中第[公式]层包含元素:输入[公式],参数[公式][公式],激活函数[公式],中间结果[公式],输出[公式]

设神经网络的损失函数为[公式](这里不给出具体公式,能够是交叉熵、MSE等),根据链式法则有:

[公式][公式]

这里记 [公式],其中[公式] 、 [公式]可由 公式1 得出,[公式]加转置符号[公式]是根据维数相容原则做出的调整。

如何求 [公式]? 可以使用以下递推(需根据维数相容原则做出调整):

[公式]

其中[公式]、 [公式]

那么咱们能够从最顶层逐层往下,即可以递推求得每一层的[公式]

注意:[公式]是逐维求导,在公式中是点乘的形式。

反向传播整个流程以下:

1) 进行前向传播计算,利用前向传播公式,获得隐藏层和输出层 的激活值。

2) 对输出层(第[公式]层),计算残差:

[公式](不一样损失函数,结果不一样,这里不给出具体形式)

3) 对于[公式]的隐藏层,计算:

[公式]

4) 计算各层参数[公式][公式]偏导数:

[公式]
[公式]


编程实现

大部分开源library(如:caffe,Kaldi/src/{nnet1,nnet2})的实现一般把[公式][公式]做为一个layer,激活函数[公式]做为一个layer(如:sigmoid、relu、softplus、softmax)。

反向传播时分清楚该层的输入、输出即能正确编程实现,如:

[公式] (公式1)

[公式] (公式2)

 

(1)式AffineTransform/FullConnected层,如下是伪代码:

注: out_diff = [公式] 是上一层(Softmax 或 Sigmoid/ReLU的 in_diff)已经求得:

[公式] (公式 1-1)

[公式] (公式 1-2)

[公式] (公式 1-3)

 

(2)式激活函数层(以Sigmoid为例)

注:out_diff = [公式]是上一层AffineTransform的in_diff,已经求得,

[公式]

在实际编程实现时,in、out多是矩阵(一般以一行存储一个输入向量,矩阵的行数就是batch_size),那么上面的C++代码就要作出变化(改变先后顺序、转置,把函数参数的Vector换成Matrix,此时Matrix out_diff 每一行就要存储对应一个Vector的diff,在update的时候要作这个batch的加和,这个加和能够经过矩阵相乘out_diff*input(适当的转置)获得。

若是熟悉SVD分解的过程,经过SVD逆过程就能够轻松理解这种经过乘积来作加和的技巧。

丢掉那些下标记法吧!

 

卷积层求导

卷积怎么求导呢?实际上卷积能够经过矩阵乘法来实现(是否旋转无所谓的,对称处理,caffe里面是否是有image2col),固然也可使用FFT在频率域作加法。

那么既然经过矩阵乘法,维数相容原则仍然能够运用,CNN求导比DNN复杂一些,要作些累加的操做。具体怎么作还要看编程时选择怎样的策略、数据结构。

 

快速矩阵、向量求导之维数相容大法已成。

相关文章
相关标签/搜索