吴恩达ML笔记-ex.4-反向传播算法

Exercise 4: Back-propagation

任务列表

Part 1: Compute Feed-forward Cost
Part 2: Sigmoid Gradient
Part 3: Implement Back-propagation & Regularization

具体实现

1.Compute Feed-forward Cost (nnCostFunction.m)

这个练习的工作基本都是在这个nnCostFunction.m里完成的,首先要做的是代价函数以及正则化的计算:

X = [ones(m, 1) X];
for i =1:m
    yk = zeros(num_labels,1);
    yk(y(i)) = 1;
    z2 = Theta1*X(i,:)';
    a2 = [1;sigmoid(z2)];
    z3 = Theta2*a2;
    a3 = sigmoid(z3);
    J = J - sum(yk.*log(a3)+(1-yk).*log(1-a3))/m;
end

以上是代价函数的计算,首先给X增加了一列全1的向量作为偏置单元,然后在循环中,定义一个10*1的全0列向量,并对其某个位置赋值为1,这就是公式中的yk,其数学表达可按下图理解:

而后进行公式中的计算,是按照神经网络的传递方式进行的计算,而不是按着公式的格式一行完成的,其中需要注意的是,X即为a1,而在a1,a2向下传递的时候,都需要增加一个偏置单元。

接下来是加入正则项的计算:

Theta1_t = Theta1;
Theta2_t = Theta2;
Theta1_t(:,1) = 0;
Theta2_t(:,1) = 0;
J = J + (0.5*lambda/m)*(sum(sum(Theta1_t.^2))+sum(sum(Theta2_t.^2)));

这里需要注意的是两个Theta在加和计算之前,需要把第0项置为0,不参与计算,剩下的按元素进行平方加和就可以。

2. Sigmoid Gradient (sigmoidGradient.m)

这里的计算比较简单,所需的公式如下所示:

转换成代码如下所示:

g = sigmoid(z).*(1 - sigmoid(z));

3. Implement Back-propagation & Regularization (nnCostFunction.m)

这里是整个练习最核心的部分了,首先是加入反向传播算法,文档中一共给出了5个步骤,其中1-4步要在循环中完成,步骤及代码如下:

DT1=0;
DT2=0;
for i =1:m
    % Step1
    yt = zeros(num_labels,1);
    yt(y(i)) = 1;
    z2 = Theta1*X(i,:)';
    a2 = [1;sigmoid(z2)];
    z3 = Theta2*a2;
    a3 = sigmoid(z3);
    % Step2
    dt3 = a3 - yt;
    % Step3
    dt2 = Theta2_t(:,2:end)'*dt3.*sigmoidGradient(z2);
    % Step4
    DT1 = DT1 + dt2*X(i,:);
    DT2 = DT2 + dt3*a2';
end
% Step5
Theta1_grad = DT1/m;
Theta2_grad = DT2/m;

在完成上述步骤后,就加入了反向传播算法,接下来是在反向传播中加入正则项,所涉及公式及代码如下:

theta1 = Theta1;
theta2 = Theta2;
theta1(:,1) = 0;
theta2(:,1) = 0;
Theta1_grad = Theta1_grad + lambda*theta1/m;
Theta2_grad = Theta2_grad + lambda*theta2/m;

同样需要注意的是要把第一列项置0。

Gradient checking函数学习

这个是完成反向传播算法之后,在加入正则项之前要进行的一个步骤,称为Gradient checking,即梯度检查,目的是避免神经网络与梯度下降等算法共用时出现的微小bug,实现方式是构建了一个微小的神经网络,用这个网络分别运行反向传播和正常的梯度下降,然后核对一下两个算法之间的误差,以下是代码以及我的理解:

debugInitializeWeights.m:

function W = debugInitializeWeights(fan_out, fan_in)
W = zeros(fan_out, 1 + fan_in);
W = reshape(sin(1:numel(W)), size(W)) / 10;

这是在checkNNGradients.m中被调用到的第一个函数,作用是根据输入的两个数值,构建一个随机的矩阵,这里的随机并不是完全随机,其实现方式是:
1.按输入数据生成一个全0矩阵;
2.读入该矩阵总的元素个数(numel函数),并对1到这个数中的每个整数取sin值;
3.用reshape函数将刚才sin生成的数据变形成矩阵,再除以10。

computeNumericalGradient.m:

function numgrad = computeNumericalGradient(J, theta)

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
end

以上是进行数值的梯度检验的方法,方法是求J相对于theta的近似偏导数(该点的左右两个十分相近的点,连线的斜率作为该点的近似偏导数),用来表示数值计算的梯度。

checkNNGradients.m

在介绍完调用到的小函数之后,这个就是整个梯度检查的函数了:

function checkNNGradients(lambda)
if ~exist('lambda', 'var') || isempty(lambda)
    lambda = 0;
end

input_layer_size = 3;
hidden_layer_size = 5;
num_labels = 3;
m = 5;

以上声明了新建的神经网络所需的一些参数的初值

Theta1 = debugInitializeWeights(hidden_layer_size, input_layer_size);
Theta2 = debugInitializeWeights(num_labels, hidden_layer_size);

以上调用了debugInitializeWeights函数,对Theta1和Theta2随机初始化。

X  = debugInitializeWeights(m, input_layer_size - 1);
y  = 1 + mod(1:m, num_labels)';

以上完成了对X,y的初始化,X的初始化方式与Theta相同,而y则是使用了另一个方式:mod函数是取余函数,在这里的使用方式是将1到m的每个数都对num_labels取余,将结果的行向量转置成列向量再加1。

nn_params = [Theta1(:) ; Theta2(:)];


costFunc = @(p) nnCostFunction(p, input_layer_size, hidden_layer_size, ...
                               num_labels, X, y, lambda);

[cost, grad] = costFunc(nn_params);
numgrad = computeNumericalGradient(costFunc, nn_params);
disp([numgrad grad]);
diff = norm(numgrad-grad)/norm(numgrad+grad);

以上就是分别用BP和数值梯度进行计算了,其中numgrad和grad就分别是数值梯度和BP所得的梯度值,这两者应该十分接近,diff中涉及到的norm函数是计算矩阵范数的,所得的diff值就表示为两者的相差程度,只要很小,就表示BP没有做错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值