在CNN卷积网络中,从输入前向传播到误差反向传播,如下图所示:
其中,在反向传播过程中,还需要把网络的输出经过一个目标函数(Objective function),通常也称为损失函数(Loss function),把网络的输出映射为一个实数,反向传播就是去优化这个损失函数,具体如下图所示:
在上图中,f 表示网络的计算模块,y 为网络输出,g 表示损失函数,网络的输出 y 经 g 映射为一个实数 z 。反向传播需要将误差 z 反向传播,那么就需要计算 z 关于 x 和 w 的偏导和
,但是根据链式求导法则需要先求得
。
下面设 f 为卷积模块, p 用正态分布随机数填充,则前向传播与反向传播求导如下代码:
% Read an example image
x = im2single(imread('peppers.png')) ;
% Create a bank of linear filters and apply them to the image
w = randn(5,5,3,10,'single') ;
y = vl_nnconv(x, w, []) ;
% Create the derivative dz/dy
dzdy = randn(size(y), 'single') ;
% Back-propagation
[dzdx, dzdw] = vl_nnconv(x, w, [], dzdy) ;
通过上述代码,已经熟悉了CNN卷积网络的前向传导与反向传播求导的基本操作,下面自定义一个目标函数,对其求导,并反向传播。
目标函数定义如下:
在上式中,f(x;w,b) 为网络的输出,也即上文中的 y 。因此,在对 w 与 b 求导前需要对 f(x;w,b) 先求导。下面分析这个目标函数以便进行求导。由上式可得:
现将网络输出 f(x;w,b) 设为res.x3(这里定义了一个三层的网络,且为了与MatConvNet定义的网络输出保持一致),E(3,1)即为上式中的目标函数, 也表示输出 z ,P—>pos, N—>neg, Matlab代码实现如下:
E(1,1) = ...
mean(max(0, 1 - res.x3(pos))) + ...
mean(max(0, res.x3(neg))) ;
E(2,1) = 0.5 * shrinkRate * sum(w(:).^2) ;
E(3,1) = E(1,1) + E(2,1) ;
dzdx3 = ...
- single(res.x3 < 1 & pos) / sum(pos(:)) + ...
+ single(res.x3 > 0 & neg) / sum(neg(:)) ;
完整代码如下:
% Forward pass
res = tinycnn(im, w, b) ;
% Loss
E(1,1) = ...
mean(max(0, 1 - res.x3(pos))) + ...
mean(max(0, res.x3(neg))) ;
E(2,1) = 0.5 * shrinkRate * sum(w(:).^2) ;
E(3,1) = E(1,1) + E(2,1) ;
dzdx3 = ...
- single(res.x3 < 1 & pos) / sum(pos(:)) + ...
+ single(res.x3 > 0 & neg) / sum(neg(:)) ;
% Backward pass
res = tinycnn(im, w, b, dzdx3) ;