为了更好地理解反向传播,先进一步地研究一下前向传播的过程:
这是一个含2个输入单元的神经网络结构(没有把偏置单元算进去),第二层有2个隐藏单元,再下一层也有2个,最后只有一个输出单元。
在进行前向传播时,我们的样本,比如(x^ (i),y^ (i)),把这个x^ (i)传到输入层中。
z(2)_1和 z(2) _2是输入单元的加权和。
然后将sigmoid逻辑函数,还有sigmoid激活函数应用到z值上,得到激活值a(2)_1和a(2)_2,以此类推,得到网络中最后的输出值a^(4)_1。
注意一下这里的计算过程,比如这个隐藏单元:
Θ是权值(参数)
所以计算z(3)_1的方法就是:
(权重乘以前面单元的值)
这就是前向传播。
事实上,后面我们会发现,反向传播的过程和前向传播非常相似,只是这两个算法计算的方向不一样而已。
为了更好地理解反向传播算法的过程,先看看其代价函数:
这个代价函数一般应用于只有一个输出单元的情况。
如果有不止一个输出单元,只需用k作为输出单元的下标,然后对它们进行求和即可。
(反向传播计算的就是代价函数的偏导数)
同一组样本中同时使用了前向传播和反向传播算法。
对于这组单独的样本(x^ (i),y^ (i)),在只有一个输出单元的情况下,y^ (i)就是一个实数。
忽略正则化,即λ=0。
观察括号中这个求和项:
会发现这项代价函数对应第i个训练样本,即代价函数对应的训练样本(x^ (i),y^ (i))是由这个式子给出的:
所以第i个样本的代价函数可以写成这个形式:
这个代价函数扮演了一个类似方差的角色。
可以把cost(i)近似地当成是神经网络输出值与实际值的方差:
就像逻辑回归中,实际中会偏向于选择比较复杂的、带对数形式的代价函数。
但为了方便理解,可以把这个代价函数看作是某种方差函数。
因此cost(i)表示了神经网络预测样本值的准确程度,也就是网络的输出值和实际观测值y(i)的接近程度。
现在再看看反向传播的过程:
一种直观的理解是,反向传播算法就是在计算这些δ^ (l)_j项,我们可以把它看作是我们在第l层中、第j个单元中得到的激活项的“误差”。
更正式地说,δ项实际上是代价函数cost(i)关于z^(l) _j的偏导数,也就是计算出的z项的加权和,或者说代价函数关于z项的偏导数:
具体来说,这个代价函数
是一个关于标签y和神经网络中h(x)的输出值的函数。
如果分析网络的内部,稍微把z^(l)_ j改一下,就会影响到神经网络的值h_θ^(x ^(i)) ,最终将改变代价函数的值。
(z是中间项)
δ项衡量的是,为了影响这些中间值,我们想要改变神经网络中的权重的程度,进而影响整个神经网络的输出h(x),并影响所有的代价函数。
让我们继续深入下去了解反向传播的过程:
对于输出层而言,如果我们设
当我们对训练样本i做前向传播和反向传播的时候,这是一个误差值,也就是y的实际值与预测值的差,这样我们就可以算出δ(4)_1的值:
然后对这些值进行反向传播,最后可以计算出前一层的这些δ项:
然后继续进行传播,最后计算出
反向传播的计算过程和前向传播非常地相似,只是方向反了过来。
如何计算出δ的值?
例如要计算δ(2)_2,与前向传播相似,先标出一对权重:
然后再来看δ(2) _2是怎么计算的,我们要做的是用δ(3) _1和对应的权重相乘,再加上δ(3) _2乘以对应权重:
实际上就等于后一层中δ项的加权和(由对应边的强度来进行加权)。
再举一个例子:
顺带一提,这些δ值都只关于隐藏单元,并不包括偏置单元,这取决于你对反向传播的定义以及你实现算法的方式。
当然也可以用其他方式来计算包含偏置单元的δ值,偏置单位的输出总是“+1”,并且它们一直都是这样,我们无法改变它:
我经常使用的方法是,最后会计算出它们的值,但我会丢掉它们,不使用这些值。因为它们最后并不会影响偏导数的计算。
至此,我们对反向传播的过程有了一个更加直观的理解。
这是一个非常有效的学习算法。
(虽然这是一种很难进行可视化的、很难理解它到底做了什么的算法,其内部原理以及过程都很难展现出来。)
参考资料:吴恩达机器学习系列课程