本文主要记录了神经网络的代价函数,神经网络中梯度下降的用法,反向传播,梯度检验,随机初始化等理论,并附上课程作业中相关部分的matlab代码及注释。
有关神经网络的概念,模型,以及利用前向传播预测分类的计算可参看Andrew Ng机器学习入门学习笔记(四)之神经网络(一)
一.神经网络解决分类问题模型参数
神经网络总的层数
第
输出层的单元数
①对于两类分类问题
②对于多类分类问题
二.神经网络的代价函数
1.正则化逻辑回归的代价函数
2.正则化神经网络的代价函数(以多类别分类为例)
定义
逻辑回归中正则化的目的是让
神经网络中正则化则是让从输入层到输出层之间每两层的映射权重矩阵
对于上面的
3.作业中代价函数求解代码
%为输入层添加偏置项
X = [ones(m,1) X];
%前向传播
z_2 = X*Theta1'; %m*25
a_2 = sigmoid(X*Theta1'); %m*25
a_2_new = [ones(m,1) a_2]; %为隐藏层添加偏置单元,m*26
h_x = sigmoid(a_2_new*Theta2');%m*10
%将y提供的1-10数字转化为神经网络输出的向量形式
Vec_y = zeros(m,num_labels);
for i = 1:m
Vec_y(i,y(i)) = 1;
end
%normal cost function(无正则化的代价函数)
J = -1/m*sum(sum(Vec_y.*log(h_x)+(1-Vec_y).*log(1-h_x)));
%regularized cost function(带有正则化的代价函数)
J = -1/m*sum(sum(Vec_y.*log(h_x)+(1-Vec_y).*log(1-h_x)))+lambda/2/m*(sum(sum(Theta1(:,2:end).^2))+sum(sum(Theta2(:,2:end).^2)));
作业中要实现的是数字识别,将20*20的图片展开成400个元素的向量,输入层带上偏置单元一共有401个单元,隐藏层带上偏置单元一共有26个单元,输出层10个单元。
计算代价函数之前,进行了一些处理,包括添加偏置单元,转换y的形式等等。为了计算代价函数需要使用的假设函数的输出,还进行了前向传播的计算。
三.神经网络中使用梯度下降
有了代价函数,接下来的目标就是
为了计算
1.前向传播
给定一个输入,可以利用前向传播计算假设函数的输出。如下图:
具体过程如下:
2.反向传播
对于每一个结点,需要计算
例如:
故
至于
这样由输出层的误差,反向传播,可以向前计算每一个隐藏层的误差。
最终我们可以得到代价函数偏导数项的表达(忽略正则化项,即
①首先对于所有的
②for i = 1 to m
{
令
利用前向传播计算
计算第
利用反向传播计算
}
③
④
其中for循环中的
3.作业中利用前向传播和后向传播求解梯度的代码及注释
%初始化Delta
Delta2 = zeros(num_labels,size(a_2_new,2));
Delta1 = zeros(size(a_2_new,2)-1,size(X,2));
%利用前向传播和后向传播计算梯度
for i = 1:m
delta_3 = h_x(i,:)-Vec_y(i,:); %1*10
delta_3 = delta_3'; %10*1
delta_2 = Theta2'*delta_3.*sigmoidGradient([1;z_2(i,:)']); %26*1
delta_2 = delta_2(2:end); %25*1
Delta2 = Delta2+delta_3*a_2_new(i,:); %10*26
Delta1 = Delta1+delta_2*X(i,:); %25*401
end
D2 = 1/m*Delta2; %无正则化的梯度
D2(:,2:end) = D2(:,2:end)+lambda/m*Theta2(:,2:end); %带有正则化的梯度,10*26
D1 = 1/m*Delta1;%无正则化的梯度
D1(:,2:end) = D1(:,2:end)+lambda/m*Theta1(:,2:end); %带有正则化的梯度,25*401
Theta1_grad = D1;
Theta2_grad = D2;
四.反向传播
反向传播到底在做什么呢?
考虑只有一个输出单元的情况,忽略正则化(
更正式一些说,对于
如上图,反向传播也可解释为,由更深一层的误差和相关的权值可以计算出前一层的误差。
若已知输出层的误差为
五.梯度检验
利用前面所说的前向传播和后向传播计算梯度时容易出现一些小错误而不被发现,这时候就需要进行梯度检验来检验我们计算的梯度是否是我们所需要的。
这里需要提出梯度的数值估计这个概念。
①
②
梯度数值估计实现代码如下:
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
梯度检验代码如下:
% Evaluate the norm of the difference between two solutions.
% If you have a correct implementation, and assuming you used EPSILON = 0.0001
% in computeNumericalGradient.m, then diff below should be less than 1e-9
diff = norm(numgrad-grad)/norm(numgrad+grad);
fprintf(['If your backpropagation implementation is correct, then \n' ...
'the relative difference will be small (less than 1e-9). \n' ...
'\nRelative Difference: %g\n'], diff);
梯度检验的实现要点(步骤):
1.使用后向传播计算DVec(偏导数向量)
2.计算数值梯度的估计值gradApprox
3.确保DVec和gradApprox值相近
4.关闭梯度检验,再使用后向传播进行学习
注意:在训练分类器之前一定要关闭梯度检验,如果没有关闭,则在梯度下降的每次迭代中都进行数值梯度的计算,代码运行将十分缓慢。梯度的数值估计相对于后向传播计算梯度来说是较大的工作量,我们使用数值估计的初衷仅仅是为了检验后向传播的实现是否正确。
六.随机初始化
运用梯度下降或者其他高级优化算法来求解
在逻辑回归中,我们可以将所有的
如果对于所有的
即,每次更新之后,从每个输入分别指向两个隐藏单元的权重是相同的,而且
当有多个隐藏单元时,这种情况相当于所有的隐藏单元只表示同一种特征,其他完全是多余的(实际上,只要初始的
故神经网络对权重采用随机初始化,来破坏这种对称性。让每一个
具体实现:
若
作业中有关随机初始化的代码:
W = zeros(L_out, 1 + L_in); %权重矩阵的维数
% ====================== YOUR CODE HERE ======================
% Instructions: Initialize W randomly so that we break the symmetry while
% training the neural network.
%
% Note: The first row of W corresponds to the parameters for the bias units
%
epsilon_init = 0.12;
W = rand(L_out, 1 + L_in) * 2 * epsilon_init - epsilon_init;
七.神经网络总结
1.选择一个网络结构
输入层单元数:特征
输出层单元数:分类的类别数。
(多类别分类问题输出层有多个单元,输出的
隐藏层数目:默认使用1个隐藏层,如果隐藏层数目多于1个,则每个隐藏层应该有相同的单元个数。
(隐藏层单元数越多,效果越好,通常取稍大于输入特征的数目)
2.训练神经网络
①构建以恶搞神经网络,对权重随机初始化
②对训练数据中任意
③计算代价函数
④利用反向传播计算偏导项
可以使用for循环遍历每一个训练数据
{
利用前向传播得到激励
利用反向传播得到误差项
}
⑤使用梯度检验比较后向传播计算得到的
⑥使用梯度下降或其他高级优化算法和反向传播相结合去求解
对于神经网络来说,
3.神经网络对新的输入分类
对于新的输入