神经网络中误差反向传播(back propagation)算法的工作原理

注意:版权所有,转载需注明出处。

clip_image001

神经网络,从大学时候就知道,后面上课的时候老师也讲过,但是感觉从来没有真正掌握,总是似是而非,比较模糊,好像懂,其实并不懂。

在开始推导之前,需要先做一些准备工作,推导中所使用的神经网络如上图所示。一个神经网络由多个层(layer)构成,每一层有若干个节点(node),最左边是输入层,中间的层被称为隐含层,最右边是输出层;上一层节点与下一层节点之间,都有边相连,代表上一层某个节点为下一层某个节点贡献的权值。

接下来对推导中使用的符号做一个详细的说明,使推导的过程清晰易懂。我们用ql_76557e54ab102d3fef79c1fe75aba90c_l3.png代表网络的层数,用ql_0d0c6039c52a63b277a584247a1fdecc_l3.png代表第ql_6d1b348a37139741785fae4946b9947e_l3.png层的节点的个数;用ql_6fc735f9aa604b197f1d93c3d85b01e4_l3.png/ql_fba21942b78a7255f69c6df735827ff7_l3.png表示第ql_6d1b348a37139741785fae4946b9947e_l3.png层经过激活函数前/后的节点向量(ql_2b3b9fef51354d7914e31515ac4798df_l3.png/ql_95fe42ddd282dd3d382d730ebb61689c_l3.png代表经过激活函数前/后某个节点的值),根据以上的表示,ql_80196de50d8eaaa423c80bf47ca4eec7_l3.png等于网络的输入ql_fb85ec598b5b2821293965c44ee93a41_l3.png,ql_6c0e32d48f1e92b3fbd08503d7458951_l3.png等于网络的输出ql_ed2cadb32b125d01f9cecf37b639ae5e_l3.png,也就是上图中的ql_c8a16baf3476c3e3a7be62d2c8c8f907_l3.png;用ql_ea67cf43820f75b55bcf2c48f825ace1_l3.png表示第ql_6d1b348a37139741785fae4946b9947e_l3.png层与第ql_4a70336db53713ccd35ecc4befeb430e_l3.png层之间的权值形成的矩阵,ql_1078cb20f48316ea3dc3cd2a32151e5b_l3.png代表ql_6d1b348a37139741785fae4946b9947e_l3.png层的节点ql_9820d9bbae1f6ca9edfdc4b0049beaed_l3.pngql_4a70336db53713ccd35ecc4befeb430e_l3.png层的节点ql_beaaf95fa968d6e4ea3e33acecab2620_l3.png之间的权重(注意这种表示方式),用ql_6db18e7b7713be16e32fd7bd00d090c0_l3.png代表ql_6d1b348a37139741785fae4946b9947e_l3.png层到ql_4a70336db53713ccd35ecc4befeb430e_l3.png层之间的偏置向量。另外,对于激活函数,可以选择不同的形式,这里使用sigmoid函数推导,表达式如下:

ql_3c2c91859e64a3b2546d9938c6b2c8aa_l3.png

之所以使用sigmoid函数,一个很重要的原因就是“mathematical convenience”:sigmoid函数的导数很好计算, ql_ecefc645c23fead66c2fc8d44a6156fe_l3.png

对于神经网络各层之间的关系,用简洁的向量矩阵形式来表达如下:

ql_8c911b7baccad69f741b1c4ae933a442_l3.png

(1)

ql_924403199dd73b5663d6866bb5731b19_l3.png

(2)

根据以上的式子,我们就可以求取网络中每一层各个节点的值了,上述的过程称为前向传播(forward propagation)过程。

通常,网络刚创建好时,我们随机初始化每两层之间的权值矩阵以及偏置向量,但是这样得到的网络,输出与实际的值差距太大,使用神经网络的目的当然是想要网络的输出与实际的值差距尽可能小。随机初始化网络,显然不能满足这个目的,但是如何调整各层之间的权值矩阵以及偏置呢,这并不是一个很简单的问题,下面要推导的反向传播(backward propagation)算法就是解决这个问题的利器。

正式开始推导

通常来说,如果想要得到一个较好的网络,需要有一批已知的训练数据,假设我们现在有一批总共ql_a38da7cfa8532c61dd4a5351f9027aca_l3.png个数据,即ql_685a6054c1eae236ff2bb945f1122d8d_l3.png。对于每一个样本来说,我们优化的目标为 :

ql_5ebdd96d4b8ff070519d5458f7b921e6_l3.png

(3)

对于所有样本来说我们的优化目标为:

ql_b8984f73efe2d135b91877ab8c7eec2f_l3.png

(4)

上述优化目标函数,第一项为误差项,第二项称为正则项(也称为weight decay term),用来控制各层权值矩阵的元素大小,防止权值矩阵过大,网络出现过拟合,这和曲线拟合中对参数使用正则道理是一样的,只不过曲线拟合中,参数是向量,这里的参数是一个一个的矩阵,我们使用F范数的平方来约束权重矩阵元素的大小,正则项前面的系数ql_1577f6cf232220b0260832335e5556dc_l3.png(称为weight decay parameter)用来控制正则项与误差项之间的一个权重。另外,一般来说,不对偏置进行正则。

关于F范数的一点小知识

假设矩阵A是实数矩阵,大小为ql_64a080e13cc25b5d2705f03b08f712a1_l3.png,其F范数是所有元素的平方和开根号,用公式表示为:

ql_f639caef9c78bf51e5fd7b1b5fa926c0_l3.png

另外关于F范数如何求导,有如下公式:

ql_79243f49f9e886e2fc3836cdbc8ea831_l3.png

抽丝剥茧,不断深入

我们目标是求出各层的权值矩阵以及偏置向量,使得优化目标函数取得最小值。根据梯度下降算法,可以求取目标函数对各个参数的偏导,迭代更新参数的值,最终得到最优的参数值(事实上,上述函数是非凸函数,梯度下降并不一定能够得到global optimum,有可能只能得到local optimum,但是实际中得到的结果一般都是比较接近最优结果,在可以接受的范围之内;另外还有更加复杂的方法,譬如加入momentum项,使得目标函数能够跳出local optimum点,从而得到global optimum,这里仅讨论最基本情况,对增加momentum项的情况不予讨论)。

参数的更新公式如下:

ql_dec75d6dd6b77bcd2cffb2dadeb137d7_l3.png

(5)

ql_557d2722076350df0a475b88bde2f708_l3.png

(6)

以上的式子中,ql_39d41e6ab4b1d818b79ba25e038bd860_l3.png称为学习率(learning rate),用来控制权重和偏置变化的幅度,如果ql_39d41e6ab4b1d818b79ba25e038bd860_l3.png太大,网络的参数收敛速度快,但是可能出现来回震荡的情况,如果ql_39d41e6ab4b1d818b79ba25e038bd860_l3.png太小,网络收敛速度太慢,训练时间长。需要说明,权重矩阵以及偏置向量的学习率可以不一样,根据需要分别设置,实际上,caffe就是这么做的,可以在prototxt里面指定每层的权重以及偏置的学习率。

从上面的公式可以看出,现在的关键变成计算目标函数对权重矩阵以及偏置项各个元素的偏导,结合公式(4),把公式(5)和(6)中的偏导项展开,得到如下形式:

ql_625e36172b4cc8b2256ef6abb0658e5f_l3.png

(7)

ql_1e4366ec40f195dd6c5c205c9192b53d_l3.png

(8)

上述公式中,公式(7)后半部分可以参考前面对于矩阵范数求导的公式得到。那么接下的问题就是对于每一个具体的样本ql_fb4f92c1e8b011b8c6682891bd99a42f_l3.png,如何求取他们对于权重矩阵以及偏置向量的偏导,也就是如何求ql_ff04be67959988558d69625ae56dd73b_l3.png以及ql_5589f9664f3616e8368a110e3857af54_l3.png?这个就要用到我们前面所说的back-propagation的思想了,当我们把一个样本输入到网络,通过前向传播,得到最终的输出,最终输出与实际的值之间有误差,然后我们通过某种有组织有规律的方式把误差一层一层向前传播,这是求解该问题的核心思想。

为了便于推导,再引入变量ql_df05dcfacc4787cdd2ba4a1664bf7034_l3.png, 即最终的误差对每一层节点经过激活函数前的变量的偏导数,用它来衡量某一层某个节点对最终误差的一个贡献量。

计算辅助变量的值

对于最后一层(第ql_129203808519009fe929a29e7cd3a970_l3.png层),我们可以很方便的计算该量,详细推导如下:

ql_ef7ae56e43d0d0f1bbe3755ea19b3559_l3.png

(9)

上述公式中,ql_633f6f759560fb07bd0bff252d0e4b1a_l3.png,对于其他层也是如此计算,不再赘述。

其他层(ql_eeea32c07c19fd12e3c803bfd6b9ac87_l3.png)的辅助变量,计算就不那么容易了,因为输出误差并不直接和这些层的节点相关,所以我们需要构造关系,利用微积分里面的链式法则(chain rule),具体计算过程如下:

ql_dade21c168c9bf12bcb3ac0733ffca09_l3.png

(10)

为了便于书写,公式(10)中,ql_8bff49bc7f75021e8e8fcfff015acf3d_l3.png。关于如何由第一行得到第二行,我起初并没有正确得到,后来结合网上给的参考结果,逐渐想通如何计算。求误差对clip_image094层某个节点的偏导,无法直接求解,因为误差只和最后一层的节点有直接关系,但是如果我们已经知道了误差相对于下一层节点的偏导,而下一层节点和本层直接相关,那么整个链条就可以打通了。通过分配率(譬如我们的目标函数是三个中间函数P,Q,R的函数,而这三个中间函数是自变量x的函数,那么很容易证明下面的式子:ql_c329659594da3357ca8e27dcc39ca430_l3.png,上述公式中第二行的求和符号就是这么来的,起初推导时少了求和符号,只求了误差相对于下一层clip_image098节点的偏导,没有意识到下一层的每个节点其实与上一层的每个节点都有关系)再加上链式法则,我们就可以很容易求得误差相对于本层的偏导,这就是误差反传的思想。

根据我们前面的定义,公式(10)第二行求和符号里面的第一项,就是ql_6d44751b591bb5adf05f3d2637276b09_l3.png。第二项如何显式表达出来呢?这需要利用我们前面说过的关系,具体如下:

ql_f4d923b00c6421479d191bb0877be378_l3.png

(11)

公式(11)中第一个等号与第二个等号后面的式子的推导,参考公式(2)。

有了公式(11),求解公式(10)第二行第二项偏导就很容易了:

ql_dea77193892b77e374b6cb1d89266857_l3.png

(12)

计算误差相对于矩阵元素和偏置向量元素的偏导

有了以上的铺垫,我们现在可以计算误差相对于矩阵元素以及偏置向量元素的偏导了。

ql_829e5071b51184782ca50ae60f03b59e_l3.png

(13)

ql_dda11f36125a565631d60f25a0f54670_l3.png

(14)

向量化表示

对于输出层:

ql_a334fa3ba8fcc5d617213643609201b3_l3.png

(15)

对于其他层(ql_eeea32c07c19fd12e3c803bfd6b9ac87_l3.png):

ql_66a45e0d25f89826e3a4ec5a7abbc75d_l3.png

(16)

权重以及偏置更新公式:

ql_7f1cd62f465d10c13dbf7b59c5d6bcc4_l3.png

(17)

ql_7c0ea37faa6ae5c38f82245bced80f82_l3.png

(18)

把所有公式整合在一起

现在我们可以把所有的公式结合在一起,得出最终的参数更新公式了。

step 1. 初始化,对于所有层(ql_cfe59447e16db646197036a2fbf30b90_l3.png),令ql_23de15ec2fe4a068d61e669d30dd123e_l3.png,ql_a263411608ab041d720362c77a81af69_l3.png,前一项是一个矩阵,后一项是一个向量,分别代表对权重矩阵以及偏置向量的更新量

step 2. 对于一个batch的所有训练样本(for i=1 to m)

a. 使用误差反传计算ql_179a3572d70b5bf1debb4616a185e44f_l3.pngql_1d3491be6806f257424b9f50b300ac2a_l3.png

b. ql_d559b27454d52d7cc1b08696c02ff899_l3.png

c. ql_e9587f167c76f70e32da57cd4fc4721b_l3.png

step 3. 更新参数

ql_edcab1dabab027ac875a58c7fc8cc38e_l3.png

ql_3c0ef2b2c8779933ecef3e23aac52627_l3.png

至此,误差反传以及参数更新的全部内容完成!

参考链接

1,斯坦福Andrew Ng的教程,非常清楚易懂,但是省略了具体推导过程

http://ufldl.stanford.edu/wiki/index.php/Backpropagation_Algorithm

2,维基百科,https://en.wikipedia.org/wiki/Backpropagation

3,另外一个很详细清楚的推导,

http://neuralnetworksanddeeplearning.com/chap2.html

转载于:https://www.cnblogs.com/csucat/p/5142595.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值