前言:前篇博文神经网络(一)中我们使用了神经网络模型来识别0-9十个数字。但是,模型参数都是教程已经给好的,我们还没有知道这些参数是怎么训练出来的。本文就会介绍神经网络的学习算法——反向传播算法(Back Propagation, BP)。
一、反向传播算法
反向传播算法是目前用来训练人工神经网络的最常用且最有效的算法。其主要思想是:
(1)将训练集数据输入到神经网络的输入层,经过隐藏层,最后达到输出层并输出结果,这是神经网络的前向传播过程;
(2)由于神经网络的输出结果与实际结果有误差,则计算估计值与实际值之间的误差,并将该误差从输出层向隐藏层反向传播,直至传播到输入层;
(3)在反向传播的过程中,根据误差调整各种参数的值;不断迭代上述过程,直至收敛。
二、算法推导
1.神经网络的代价函数(cost function):
2.前向传播(forward propagation)
其实也就是通过神经网络,从输入参数到输出结果的计算过程(只计算一次):
3.反向传播(backpropagation)
我们的目标是最小化cost function,于是使用梯度下降法对参数 Θ 进行更新:
function [J grad] = nnCostFunction(nn_params, ...
input_layer_size, ...
hidden_layer_size, ...
num_labels, ...
X, y, lambda)
% Reshape nn_params back into the parameters Theta1 and Theta2, the weight matrices
% for our 2 layer neural network
Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...
hidden_layer_size, (input_layer_size + 1));
Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...
num_labels, (hidden_layer_size + 1));
% Setup some useful variables
m = size(X, 1);
% You need to return the following variables correctly
J = 0;
Theta1_grad = zeros(size(Theta1));
Theta2_grad = zeros(size(Theta2));
% forward propogation
a1 = [ones(m,1), X];
z2 = a1 * Theta1';
a2 = [ones(m,1), sigmoid(z2)];
z3 = a2 * Theta2';
a3 = sigmoid(z3);
% back propogation
for i = 1:m
% cost for each sample
yVec = zeros(num_labels,1);
yVec(y(i)) = 1;
cost = log(a3(i,:)) * (-yVec) + log(1 - a3(i,:)) * (-(1 - yVec));
J = J + cost;
% partial derivative for each sample
delta3 = a3(i,:)' - yVec;
delta2 = Theta2(:,2:end)' * delta3 .* sigmoidGradient(z2(i,:)');
Delta2 = delta3 * a2(i,:);
Delta1 = delta2 * a1(i,:);
Theta2_grad = Theta2_grad + Delta2;
Theta1_grad = Theta1_grad + Delta1;
end
J = J / m;
Theta1_grad = Theta1_grad / m;
Theta2_grad = Theta2_grad / m;
% regularization
Theta1_r = [zeros(hidden_layer_size,1), Theta1(:, 2:end)];
Theta2_r = [zeros(num_labels,1), Theta2(:, 2:end)];
J = J + (sum(sum(Theta1_r.^2)) + sum(sum(Theta2_r.^2)))*lambda/2/m;
Theta1_grad = Theta1_grad + Theta1_r*lambda/m;
Theta2_grad = Theta2_grad + Theta2_r*lambda/m;
% Unroll gradients
grad = [Theta1_grad(:) ; Theta2_grad(:)];
end
4.梯度下降
Repeat {
compute forward propagation a(l) ;
compute back propagation δ(l)
compute gradient:
解决该问题的方法是: 梯度检查 (Gradient Checking)
梯度检查(Gradient Checking)的思想就是通过数值近似(numerically approximately)的方式计算导数近似值,从而检查导数计算是否正确。虽然数值计算方法速度很慢,但实现起来很容易,并且易于理解,所以它可以用来验证例如BP算法等快速求导算法的正确性。
如前所述,机器学习中大部分算法的核心就是代价值计算和梯度计算,因此,在实现神经网络或者其他比较复杂的模型时候,利用Gradient Checking可以检查算法是否正确实现。
梯度检查 (Gradient Checking)的核心是导数的数值计算 ,公式如下:
三、总结
神经网络是一个比较复杂的模型,也是深度学习的重要基础,以后还需继续深入学习。