神经网络介绍
神经网络(Neural Network)是机器学习中一类实用的算法,来源于与人脑的类比,但是它并不新,最早出现在20世纪80年代,至今在许多领域得到广泛使用。
神经网络的作用是可以用线性运算表征变量之间复杂的非线性关系,可以理解成逻辑回归中使用的
x2,x3,x1x2
等高次项,从而减少所使用特征的数量。具体在计算机视觉中,对于物体识别问题,假如用图像像素点作为特征学习,那么对于50x50像素的图像,其特征数量是2500个,如果结果与这些变量之间存在非线性关系,则要用到的特征数量会更多。
神经网络的基本结构如图所示
每一个逻辑单元称为神经元(Neuron),其中 x0 和 a(2)0 称为偏置单元(bias unit),恒等于1,在大多数神经网络结构示意图中不画出来,但在计算中要用到。
神经网络的数学模型计算类似于逻辑回归的升级版,在上图中
这里,
a(j)i
表示第
j
层第
Θ(j)
表示从第
j
层到第
g(z)=11+e−z
即S型函数,在神经网络中也称为激励函数(activation function)。
图示的神经网络分为三层:输入层(input layer),隐含层(hidden layer)和输出层(output layer)。在其它更复杂神经网络中通常不止三层,实际上是隐含层不止一层。
从一个例子看看神经网络如何表示变量间的非线性关系,以同或关系为例,记作 x1 XNOR x2
先依次看看基本逻辑运算与或非在两层神经网络中的实现
取
Θ(1)=[−302020]
,可以得到
hΘ(x)=g(−30+20x1+20x2)
,对于
x1,x2∈{0,1}
,可以计算得到如图真值表,从而实现和运算
类似的,令
Θ(1)=[−102020]
,实现或运算
令
Θ(1)=[10−20]
,实现非运算
这样,理论上就可以通过组合实现任意逻辑运算。
如图,按以上选择权值,则实现了 a(2)1= x1 AND x2 , a(2)2= x1 NAND x2 , hΘ(x)= a(2)1 OR a(2)2 ,从而实现了 hΘ(x)= x1 XOR x2 。
另外,在多分类问题中,通常把 y∈{1,2,3,4} 改写成 y=⎡⎣⎢⎢⎢1000⎤⎦⎥⎥⎥,⎡⎣⎢⎢⎢0100⎤⎦⎥⎥⎥,⎡⎣⎢⎢⎢0010⎤⎦⎥⎥⎥,⎡⎣⎢⎢⎢0001⎤⎦⎥⎥⎥ ,这样表示就把多分类问题表示成输出层大于一个神经元的形式,可以进行一般化的运算。
反向传播算法(Backpropagation Algorithm)
反向传播算法是神经网络中用于优化代价函数,求得合适参数的算法,类似于逻辑回归中梯度下降法等方法。
神经网络中代价函数的表达式与逻辑回归中的比较:
显而易见其中每一项的意义,其中包含正规化。
明确一点,对于要调用训练算法去计算合适的参数 Θ ,需要计算代价函数的值 J(Θ) 和梯度值 ∂∂Θ(l)ijJ(Θ) ,代价函数的值由定义可以计算得出,梯度值则由反向传播算法计算得出,算法如下:
Backpropagation algorithm
Training set
{(x(1),y(1)),...,(x(m),y(m))}
Set
△(l)ij=0
(for all
l,i,j
).
For
i=1
to
m
Set
Perform forward propagation to compute
a(l)
for
l=2,3,...,L
Compute
δ(L)=a(L)−y(i)
δ(L−1)=(Θ(L−1))Tδ(4).∗g′(z(3))
, compute
δ(L−1),δ(L−2),...,δ(2)
△(l)ij:=△(l)ij+a(l)jδ(l+1)i
D(l)ij:=⎧⎩⎨1m△(l)ij+λΘ(l)ij1m△(l)ij if j≠0 if j=0
∂∂Θ(l)ijJ(Θ)=D(l)ij
其中,前向传播(forward propagation)是
a(1)=x
z(l)=Θ(l−1)a(l−1)l≥2
a(l)=g(z(2))(add a(l)0)l≥2
hΘ(x)=a(L)=g(z(L))
对于反向传播算法的理解,可以理解为每一个节点的当前值与最优值之间的偏差,即对
δ(l)j
,表示第
l
层第
梯度检查(Gradient Checking)
在实际算法实现过程中,往往很难做检验算法实现的对错,这里用一种叫梯度检查的方法用于检查梯度算得是否正确,直接来源于导数的极限定义。在一维中,导数的极限定义是
所以当检验梯度时,可以用
检验梯度的近似值。需要注意的是这种计算方法比起前面的反向传播算法要慢很多,所以只是用于检验,一旦确定算法实现没有问题,就要把这段检验的代码注释。另外,这种检查方法适合一切需要计算梯度的情况。
随机初始化(Random Initialization)
由于在神经网络中,对于每一层的各个节点进行相同的操作,因此,假如像逻辑回归时那样把全部参数初始化为0,则最后经过训练得到的每一层参数必然是相同的,这就减弱了神经网络的作用,带来误差。因此,初始化权值参数时需要随机初始化。随机初始化的操作和原因都很好理解,但在算法实现中是必要的细节步骤。
总结
综合来说,神经网络的训练算法如下:
1.随机初始化权值
Θ
2.实现前向传播算法对每一个输入的样本
x(i)
计算
hΘ(x(i))
,包括每一层每个节点的
a(l)j
,
z(l)j
3.实现代价函数
J(Θ)
4.实现反向传播算法计算梯度
∂∂Θ(l)jkJ(Θ)
5.用梯度检查方法比较反向传播算法得到
∂∂Θ(l)jkJ(Θ)
与
J(Θ)
梯度的数值估计
6.用梯度下降法或者其它优化方法,由
J(Θ)
和
∂∂Θ(l)jkJ(Θ)
计算得到最优参数
Θ
实现代码如下:(只给出核心部分,省略初始化等细节计算)
% 初始化权值,L_in、L_out分别为权值两端的节点个数,如L_in = input_layer_size, L_out = hidden_layer_size
epsilon_init = 0.12;
W = rand(L_out, 1 + L_in) * 2 * epsilon_init - epsilon_init;
% 前向传播算法计算假设函数
X = [ones(m,1) X];
a1 = X;
z2 = X * Theta1';
a2 = [ones(size(z2,1),1) sigmoid(z2)];
z3 = a2 * Theta2';
hyp = sigmoid(z3);
% 计算代价函数以及正规化
y_temp = zeros(m,num_labels);
for i = 1:m
y_temp(i,y(i)) = 1;
end
J = 1/m*sum(sum(-y_temp.*log(hyp) - (1-y_temp).*log(1-hyp)));
J = J + lambda/2/m*(sum(sum(Theta1(:,2:end).^2)) + sum(sum(Theta2(:,2:end).^2)));
% 反向传播算法计算梯度
sigma3 = hyp - y_temp;
sigma2 = sigma3 * Theta2(:,2:end) .* sigmoidGradient(z2);
delta1 = sigma2' * a1;
delta2 = sigma3' * a2;
Theta1_grad = 1/m*delta1 + lambda/m*[zeros(size(Theta1,1),1) Theta1(:,2:end)];
Theta2_grad = 1/m*delta2 + lambda/m*[zeros(size(Theta2,1),1) Theta2(:,2:end)];
% 梯度方法数值检查
numgrad = zeros(size(theta));
perturb = zeros(size(theta));
e = 1e-4;
for p = 1:numel(theta)
% Set perturbation vector
perturb(p) = e;
loss1 = J(theta - perturb);
loss2 = J(theta + perturb);
% Compute Numerical Gradient
numgrad(p) = (loss2 - loss1) / (2*e);
perturb(p) = 0;
end
% 优化计算得到权值
options = optimset('MaxIter', 50);
lambda = 1;
% Create "short hand" for the cost function to be minimized
costFunction = @(p) nnCostFunction(p, ...
input_layer_size, ...
hidden_layer_size, ...
num_labels, X, y, lambda);
% Now, costFunction is a function that takes in only one argument (the
% neural network parameters)
[nn_params, cost] = fmincg(costFunction, initial_nn_params, options);