caffe的反向传播的实现

1、反向传播的实现
反向传播算法理论
摘自“http://ufldl.stanford.edu/wiki/index.php/Backpropagation_Algorithm”

假定我们有一个固定的训练集,有m个训练样本。我们可以使用“batch gradient descent”来训练我们的神经网络。详细的,对一个单一的训练样本 (x,y),我们定义了它对应的损失函数如下:

这是“(one-half) squared-error ”损失函数。给定有m个样本的训练集,我们定义整体损失函数为:

J(W,b)的定义中的第一项是所有单个样本损失函数运算结果的平均。第二项是一个正则项(也称之为“weight decay term”),它有助于减少权重的幅度(magnitude),并帮助防止过拟合。

说明:“weight decay”并不像我们为J(W,b)定义的那样,它通常不应用于偏置项。应用“weight decay”到偏置单元通常只对最终网络产生很小的差异。如果采用了斯坦福的 CS229 (Machine Learning) 或在YouTube上观看了课程视频,你也可以认识到这个“weight decay”本质上是贝叶斯正则化(Bayesian regularization)的一个变体,在它之上我们放置一个高斯先验并做了MAP(替代了最大似然)估算。

“weight decay”的参数λ 控制着这两个项的相对重要性。说明: J(W,b;x,y)是一个单个样本的平方误差损失;J(W,b) 是包含“weight decay”项的整个误差损失函数。

上面的损失函数经常用于分类问题和回归问题。对于分类问题,我们使y=0或1来标识两个类型标记(通过回调激活函数sigmoid 来输出[0,1]的值;如果我们使用一个tanh激活函数,我们将使用-1和+1来标识标记)。对于回归问题,我们首先缩放我们的输出,来保证它们在 [0,1]的区间内(或者如果我们使用tanh激活函数,则在[ − 1,1]区间内)。

我们的目标是最小化J(W,b)函数。为了训练我们的神经网络,我们将使用一个很小的接近于0的随机值来初始化每个和每个(say according to a Normal(0,ε2) distribution for some small ε, say 0.01),然后应用优化算法(例如,batch gradient descent)。既然 J(W,b)是一个非凸函数,梯度下降容易导致局部最优化。然而,在实际应用中,梯度下降法工作的相当好。最后,说明一点,随机的初始化参数是非常重要的,而不能都设置为0.如果所有的参数以相同的值启动,所有的隐层单元将以学到相同的函数结束。随机初始化会打破这种对称性。

梯度下降的一次迭代更新参数W和b,如下所示:

扫描二维码关注公众号,回复: 12248914 查看本文章

这里,α是学习速率。上面公式的关键步骤是计算偏导数。我们描述反向传播算法,它给出了一个非常有效的方法来计算这些偏导数。

我们首先描述反向传播是如何用于计算的,损失函数 J(W,b;x,y)的偏导数是对应于单个样本(x,y)定义的。一旦我们能计算出这些J(W,b;x,y)的偏导数,我们就会看到整体损失函数J(W,b)的偏导数可以通过如下公式计算:

上面的两个公式是有小的差别的,因为“weight decay”只使用了W没有使用b。

下面是反向传播算法的直觉认知。给定一个训练样本(x,y),我们先运行一个"forward pass"来计算所有穿过贯穿网络的激活,包含假设为hW,b(x)的输出值。然后,对于在层 l的每个节点i,我们要计算一个“error term”(误差项),它测量出这个节点应该对我们的输出结果的任何错误承担多大的责任。对于一个输出节点,我们直接测量网络的激活与实际目标值之间的差别,并使用它来定义(这里层就是输出层)。那隐层单元怎么办?对于那些隐层单元,我们基于使用作为输入的节点的“error term”的加权平均,来计算。详细的描述,这是反向传播算法:

Perform a feedforward pass, computing the activations for layers L2, L3, and so on up to the output layer.
For each output unit i in layer nl (the output layer), set

For each node i in layer l, set

Compute the desired partial derivatives, which are given as:

以全连接层为例,讲解反向传播算法的实现。

下面是caffe的InnerProduct层和convolution层的反向传播的实现

Caffe的InnerProduct层反向传播的实现
我们已知this layer的blobs_[0]和blobs_[1]分别保存的是weight和bias。如果bias设置的话,bias_multiplier_为全1。

前向传播的公式如下:

  1. 反向运算主要是完成对weight和bias的导数计算,及计算bottom_diff。

计算公式如下:

  1. 计算weight_diff和bias_diff

应该是对应下面的公式:

根据上面计算出来的weight_diff,我们更新该innerProduct 层的bottom_diff

对应于下面的公式:

更新weight_data和biase_data.在完成前向传播和反向传播后,由SGDSolver的ApplyUpdate操作完成。

基于solver的iter_size,对学到的diff进行归一化处理,如果是1,则不做处理,默认为1。
基于solve.prototxt内配置的weight_decay和train.prototxt对应layer的对应参数内配置的params_weight_decay(对应于layer的param内的decay_mult参数,按顺序依次是weight和bias)和solve.prototxt内配置的regularization_type(默认是L2)进行正则化处理。公式如下:

其中,diff标识weight或bias的导数,data标识weight或bias的当前数据。

基于solve.prototxt内配置的学习速率rate和train.prototxt对应layer的对应参数内配置的params_lr(对应于layer的param内的lr_mult参数,按顺序依次是weight和bias),和solve.prototxt内配置的momentum参数,更新导数值。公式如下:

对应于SGD的公式是:

调用SGDSolver->net_->Update(),更新weight和bias的blobs,最后调用的是blob的update函数,公式如下:

对应于SGD的公式是:

结束。

猜你喜欢

转载自blog.csdn.net/sunlin972913894/article/details/106273479