ML - Coursera Andrew Ng - Week5 & Ex4 - Neural Network 2 - 笔记与代码

Week 5主要讲了神经网络的反向传播算法(Backpropagation Algorithm)。如上一节所讲,前馈传播算法是根据输入层向量x,各层权重矩阵 Θ \Theta Θ ,以及激活函数逐层从左向右计算,最终得到输出层结果。反向传播算法则是为了找出使损失函数 J ( Θ ) J(\Theta) J(Θ)最小化的最佳 Θ \Theta Θ ,BP为优化函数(如梯度下降、其它高级优化算法)提供梯度值,通过从右向左来逐层求偏导,得到每层的参数梯度,用 δ ( l ) δ^{(l)} δ(l)来保存每一层求偏导的部分结果,以便后面可以接着借用这部分结果来求下一层的结果,用 D i , j ( l ) D_{i, j}^{(l)} Di,j(l)来保存偏导结果。

选择神经网络的结构。

训练神经网络的时候,需要先随机化权重 Θ \Theta Θ,不能初始化为0,不然BP的时候所有节点会重复地更新为同一个值。还要注意用gradient checking来保证梯度下降算法或其它高级算法的正确性,因为算法的复杂性,有时候一些bug会导致表面上梯度是下降的,但是结果会有很大误差。

Cost Function

正则化逻辑回归的损失函数为

神经网络的损失函数为

其中L为神经网络的总层数, s l s_l sl为第l层不包括bias unit的单元数量,K为输出层的units/classes数量。

  • 前一项的两个求和表示计算输出层每个单元的逻辑回归损失之和
  • 后一项的三个求和表示计算整个神经网络中的 Θ \Theta Θ的各项平方之和。在第l层中 s l + 1 s_{l+1} sl+1是当前 Θ \Theta Θ的行数(不包括bias unit), s l s_l sl是当前 Θ \Theta Θ的列数(包括bias unit)。
Backpropagation Algorithm

反向传播算法是为了得到
m i n Θ J ( Θ ) min_{\Theta}J(\Theta) minΘJ(Θ)

所以我们用损失函数对 Θ \Theta Θ求偏导(partial derivative)
∂ ∂ Θ i , j ( l ) J ( Θ ) \frac{∂}{∂\Theta_{i,j}^{(l)}}J(\Theta) Θi,j(l)J(Θ)

考虑只有一个分类(K=1)的简单情况, J ( Θ ) J(\Theta) J(Θ)可以简化为
J ( Θ ) = c o s t ( t ) = y ( t ) l o g ( h Θ ( x ( t ) ) ) + ( 1 − y ( t ) ) l o g ( 1 − h Θ ( x ( t ) ) ) J(\Theta) = cost(t) = y^{(t)}log(h_\Theta(x^{(t)})) + (1-y^{(t)})log(1-h_\Theta(x^{(t)})) J(Θ)=cost(t)=y(t)log(hΘ(x(t)))+(1y(t))log(1hΘ(x(t)))

δ j ( l ) δ_j^{(l)} δj(l)可以看做是 a j ( l ) a_j^{(l)} aj(l)处的误差"error",具体推导可见link,定义 δ ( l ) δ^{(l)} δ(l)
δ j ( l ) = ∂ ∂ z j ( l ) J ( Θ ) δ_j^{(l)} = \frac{∂}{∂z_j^{(l)}}J(\Theta) δj(l)=zj(l)J(Θ)

δ ( l ) δ^{(l)} δ(l)的大小与对应那一层的 a ( l ) a^{(l)} a(l)的大小一样, Δ ( l ) Δ^{(l)} Δ(l)的大小与对应那一层的 Θ ( l ) \Theta^{(l)} Θ(l)的大小一样,通过 Δ ( l ) Δ^{(l)} Δ(l)来更新 Θ ( l ) \Theta^{(l)} Θ(l),找到使损失函数最小的 Θ \Theta Θ。BP算法的计算过程:

训练集{( x ( 1 ) x^{(1)} x(1), y ( 1 ) y^{(1)} y(1))…( x ( m ) x^{(m)} x(m), y ( m ) y^{(m)} y(m))},初始化 Δ i , j ( l ) : = 0 Δ_{i,j}^{(l)}:=0 Δi,j(l):=0
对训练样本t = 1 to m:

  1. Set a ( 1 ) : = x ( t ) a^{(1)} := x^{(t)} a(1):=x(t)
  2. 使用前馈算法计算后面每层的结果 a ( l ) a^{(l)} a(l)
  3. 计算 δ ( l ) δ^{(l)} δ(l):
    δ ( L ) = a ( L ) − y ( t ) δ^{(L)} = a^{(L)} - y^{(t)} δ(L)=a(L)y(t) l = L l = L l=L
    δ ( l ) = ( ( Θ ( l ) ) T δ ( l + 1 ) . ∗ a ( l ) . ∗ ( 1 − a ( l ) ) δ^{(l)} = ((\Theta^{(l)})^Tδ^{(l + 1)} .* a^{(l)} .* (1 - a^{(l)}) δ(l)=((Θ(l))Tδ(l+1).a(l).(1a(l)) l = L − 1 , L − 2 , . . . , 2 l = L - 1, L - 2, ..., 2 l=L1,L2,...,2
  4. 计算 Δ i , j ( l ) Δ_{i,j}^{(l)} Δi,j(l)
    Δ i , j ( l ) : = Δ i , j ( l ) + a j ( l ) δ ( l + 1 ) Δ_{i,j}^{(l)}:=Δ_{i,j}^{(l)} + a_j^{(l)}δ^{(l + 1)} Δi,j(l):=Δi,j(l)+aj(l)δ(l+1)
    vectorization Δ ( l ) : = Δ ( l ) + δ ( l + 1 ) ( a j ( l ) ) T Δ^{(l)}:=Δ^{(l)} + δ^{(l + 1)}(a_j^{(l)})^T Δ(l):=Δ(l)+δ(l+1)(aj(l))T
  5. 计算 D i , j ( l ) D_{i,j}^{(l)} Di,j(l):
    D i , j ( l ) : = 1 m ( Δ i , j ( l ) + λ Θ i , j ( l ) ) D_{i,j}^{(l)}:=\frac{1}{m}(Δ_{i,j}^{(l)} + λ\Theta_{i,j}^{(l)}) Di,j(l):=m1(Δi,j(l)+λΘi,j(l)) j ≠ 0 j ≠ 0 j̸=0
    D i , j ( l ) : = 1 m Δ i , j ( l ) D_{i,j}^{(l)}:=\frac{1}{m}Δ_{i,j}^{(l)} Di,j(l):=m1Δi,j(l) j = 0 j = 0 j=0
Unrolling Parameters

为了能使用优化函数,如fminunc(),需要将unroll所有元素将它们放进一个vector中。如Theta1是个25x401的矩阵,Theta2是个10x26的矩阵,unroll后是一个10285x1的vector。

thetaVector = [ Theta1(:); Theta2(:); Theta3(:); ]
deltaVector = [ D1(:); D2(:); D3(:) ]

// if the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11
Theta1 = reshape(thetaVector(1:110),10,11)
Theta2 = reshape(thetaVector(111:220),10,11)
Theta3 = reshape(thetaVector(221:231),1,11)
Gradient Checking

Gradient checking可以保证算法的正确性,通过检查gradApprox ≈ deltaVector来确认算法是否正确。一旦确认BP算法的正确性,就不需要继续计算gradApprox了,因为gradient checking远比BP耗时。

epsilon = 1e-4;
for i = 1:n,
  thetaPlus = theta;
  thetaPlus(i) += epsilon;
  thetaMinus = theta;
  thetaMinus(i) -= epsilon;
  gradApprox(i) = (J(thetaPlus) - J(thetaMinus))/(2*epsilon)
end;
Random Initialization

将每个 Θ i , j ( l ) \Theta_{i,j}^{(l)} Θi,j(l)初始化为 [ − ϵ , ϵ ] [−ϵ,ϵ] [ϵ,ϵ]之间的随机值,此处代码中的epsilon与gradient checking中的epsilon无关。

// If the dimensions of Theta1 is 10x11, Theta2 is 10x11 and Theta3 is 1x11.
// rand(x,y) is just a function in octave that will initialize a matrix of random real numbers between 0 and 1.
Theta1 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta2 = rand(10,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Theta3 = rand(1,11) * (2 * INIT_EPSILON) - INIT_EPSILON;
Exercise 4: 实现反向传播的神经网络 - Matlab

用反向传播算法实现神经网络,来识别手写数字。

1. Neural Networks

构建的神经网络结构与ex3中一致,3层神经网络,输入层特征数量为400(不包括bias unit),输出层类别数量为10,隐藏层单元数为25。注意unroll parameters。

1.1 Feedforward and Cost Function

非正则化的神经网络损失函数为

在nnCostFunction.m文件中,实现非正则化的损失函数。因为没有正则化,lambda设为0。对ex3中给出的Theta1和Theta2,我们可以测试这个损失函数的正确性。eye(num_labels)(:,y)的解释参考link。sum(x)表示列求和,sum(x,2)表示行求和,sum(x( : : :))表示矩阵求和。

% feedforward propagation
X = [ones(m, 1), X]; % 5000x401
a_super_2 = sigmoid(Theta1 * X'); % 25x5000=(25x401)*(401x5000)
a_super_2 = [ones(1, m); a_super_2]; % 26x5000
a_super_3 = sigmoid(Theta2 * a_super_2); % 10x5000=(10x26)*(26*5000)

% non-regularized cost function
I = eye(num_labels); % 10x10
y = I(:,y); % y:5000x1 -> 10x5000
tempJ = (y .* log(a_super_3) - (y - 1) .* log(1 - a_super_3)) / (-m);
J = sum(tempJ(:));
1.2 Regularized Cost Function

正则化的神经网络损失函数为

在nnCostFunction.m文件中,基于上面非正则化的损失函数基础上,加上正则化的项,即可得到正则化的损失函数。

% regularized cost function
tempTheta1 = Theta1.^2;
tempTheta1 = tempTheta1(:,2:end);
tempTheta2 = Theta2.^2;
tempTheta2 = tempTheta2(:,2:end);
J = J + lambda / (2 * m) * (sum(tempTheta1(:)) + sum(tempTheta2(:)));
2. Backpropagation
2.1 Sigmoid Gradient

sigmoid函数求导有如下特征,在sigmoidGradient.m文件中完成对sigmoid的求导。

function g = sigmoidGradient(z)
%SIGMOIDGRADIENT returns the gradient of the sigmoid function
%evaluated at z
%   g = SIGMOIDGRADIENT(z) computes the gradient of the sigmoid function
%   evaluated at z. This should work regardless if z is a matrix or a
%   vector. In particular, if z is a vector or matrix, you should return
%   the gradient for each element.

g = zeros(size(z));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the gradient of the sigmoid function evaluated at
%               each value of z (z can be a matrix, vector or scalar).

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

% =============================================================

end
2.2 Random Initialization

在randInitializeWeights.m文件中,完成对参数的随机初始化。

function W = randInitializeWeights(L_in, L_out)
%RANDINITIALIZEWEIGHTS Randomly initialize the weights of a layer with L_in
%incoming connections and L_out outgoing connections
%   W = RANDINITIALIZEWEIGHTS(L_in, L_out) randomly initializes the weights 
%   of a layer with L_in incoming connections and L_out outgoing 
%   connections. 
%
%   Note that W should be set to a matrix of size(L_out, 1 + L_in) as
%   the first column of W handles the "bias" terms
%

% You need to return the following variables correctly 
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 column of W corresponds to the parameters for the bias unit
%

epsilon_init = 0.12;
W = rand(L_out, 1 + L_in) * 2 * epsilon_init - epsilon_init;

% =========================================================================

end
2.3 Backpropagation

BP需要从右到左计算输出层和隐藏层的"error term" δ j ( l ) δ_j^{(l)} δj(l),计算方式如下图所示。一共有m=5000个样本,对每个样本,都要进行1-4的操作,最后将得到的gradients的和除以m就是整个神经网络损失函数的gradients。 δ ( l ) δ^{(l)} δ(l)的大小与对应那一层的 a ( l ) a^{(l)} a(l)的大小一样, Δ ( l ) Δ^{(l)} Δ(l)的大小与对应那一层的 Θ ( l ) \Theta^{(l)} Θ(l)的大小一样。

delta_super_3 = a_super_3 - y; % 10x5000
delta_super_2 = Theta2(:,2:end)' * delta_super_3 .* sigmoidGradient(Theta1 * X'); % 25x5000

Delta_super_2 = delta_super_3 * a_super_2'; % 10x26=(10x5000)*(5000x26)
Delta_super_1 = delta_super_2 * X; % 25x401=(25x5000)*(5000x401)

% gradient for non-regularized BP
Theta1_grad = Delta_super_1 / m;
Theta2_grad = Delta_super_2 / m;
2.4 Gradient checking

Gradient checking可以用于各种算法的检验。此处不需要自己填写代码,比较numerical gradient和我们得到的gradient是否在一个很小的误差内,此处的 ϵ = 1 0 − 4 ϵ = 10^{-4} ϵ=104。在确认了算法正确性后,训练参数前记得关闭gradient checking。

2.5 Regularized Neural Network

在2.3的基础上,给gradient增加上正则化项,就可以得到正则化的gradient,注意不能正则化 Θ ( l ) \Theta^{(l)} Θ(l)的第一列,因为那部分是用于bias unit的,也就是说 Θ i , j ( l ) \Theta_{i,j}^{(l)} Θi,j(l)中,我们需要用到的部分i从1开始,j从0开始。在nnCostFunction.m文件中加上正则化后的gradients。

% regularized gradients
Theta1(:,1) = 0;
Theta2(:,1) = 0;
Theta1_grad = Theta1_grad + lambda / m * Theta1;
Theta2_grad = Theta2_grad + lambda / m * Theta2;

在nnCostFunction.m文件中,我们间断地补充了几次代码,主要进行了三步操作,完整的代码如下。

function [J grad] = nnCostFunction(nn_params, ...
                                   input_layer_size, ...
                                   hidden_layer_size, ...
                                   num_labels, ...
                                   X, y, lambda)
%NNCOSTFUNCTION Implements the neural network cost function for a two layer
%neural network which performs classification
%   [J grad] = NNCOSTFUNCTON(nn_params, hidden_layer_size, num_labels, ...
%   X, y, lambda) computes the cost and gradient of the neural network. The
%   parameters for the neural network are "unrolled" into the vector
%   nn_params and need to be converted back into the weight matrices. 
% 
%   The returned parameter grad should be a "unrolled" vector of the
%   partial derivatives of the neural network.
%

% 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));

% ====================== YOUR CODE HERE ======================
% Instructions: You should complete the code by working through the
%               following parts.
%
% Part 1: Feedforward the neural network and return the cost in the
%         variable J. After implementing Part 1, you can verify that your
%         cost function computation is correct by verifying the cost
%         computed in ex4.m

% feedforward propagation
X = [ones(m, 1), X]; % 5000x401
a_super_2 = sigmoid(Theta1 * X'); % 25x5000=(25x401)*(401x5000)
a_super_2 = [ones(1, m); a_super_2]; % 26x5000
a_super_3 = sigmoid(Theta2 * a_super_2); % 10x5000=(10x26)*(26*5000)

% non-regularized cost function
I = eye(num_labels); % 10x10
y = I(:,y); % y:5000x1 -> 10x5000
tempJ = (y .* log(a_super_3) - (y - 1) .* log(1 - a_super_3)) / (-m);
J = sum(tempJ(:));

% regularized cost function
tempTheta1 = Theta1.^2;
tempTheta1 = tempTheta1(:,2:end);
tempTheta2 = Theta2.^2;
tempTheta2 = tempTheta2(:,2:end);
J = J + lambda / (2 * m) * (sum(tempTheta1(:)) + sum(tempTheta2(:)));

% Part 2: Implement the backpropagation algorithm to compute the gradients
%         Theta1_grad and Theta2_grad. You should return the partial derivatives of
%         the cost function with respect to Theta1 and Theta2 in Theta1_grad and
%         Theta2_grad, respectively. After implementing Part 2, you can check
%         that your implementation is correct by running checkNNGradients
%
%         Note: The vector y passed into the function is a vector of labels
%               containing values from 1..K. You need to map this vector into a 
%               binary vector of 1's and 0's to be used with the neural network
%               cost function.
%
%         Hint: We recommend implementing backpropagation using a for-loop
%               over the training examples if you are implementing it for the 
%               first time.

delta_super_3 = a_super_3 - y; % 10x5000
delta_super_2 = Theta2(:,2:end)' * delta_super_3 .* sigmoidGradient(Theta1 * X'); % 25x5000

Delta_super_2 = delta_super_3 * a_super_2'; % 10x26=(10x5000)*(5000x26)
Delta_super_1 = delta_super_2 * X; % 25x401=(25x5000)*(5000x401)

% gradient for non-regularized BP
Theta1_grad = Delta_super_1 / m;
Theta2_grad = Delta_super_2 / m;

% Part 3: Implement regularization with the cost function and gradients.
%
%         Hint: You can implement this around the code for
%               backpropagation. That is, you can compute the gradients for
%               the regularization separately and then add them to Theta1_grad
%               and Theta2_grad from Part 2.
%

% regularized gradients
Theta1(:,1) = 0;
Theta2(:,1) = 0;
Theta1_grad = Theta1_grad + lambda / m * Theta1;
Theta2_grad = Theta2_grad + lambda / m * Theta2;

% -------------------------------------------------------------

% =========================================================================

% Unroll gradients
grad = [Theta1_grad(:) ; Theta2_grad(:)];

end
2.6 Learning Parameters Using fmincg

用fmincg训练参数,注意参数是unroll了的。

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, ~] = fmincg(costFunction, initial_nn_params, options);

% Obtain Theta1 and Theta2 back from nn_params
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));
 
pred = predict(Theta1, Theta2, X);
fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);
3. Visualizing the Hidden Layer

我们可以通过可视化隐藏层来看神经网络学习的是什么东西。

Ex4全部代码已上传Github

### 回答1: Coursera-ml-andrewng-notes-master.zip是一个包含Andrew Ng机器学习课程笔记代码的压缩包。这门课程是由斯坦福大学提供的计算机科学和人工智能实验室(CSAIL)的教授Andrew Ng教授开设的,旨在通过深入浅出的方式介绍机器学习的基础概念,包括监督学习、无监督学习、逻辑回归、神经网络等等。 这个压缩包中的笔记代码可以帮助机器学习初学者更好地理解和应用所学的知识。笔记中包含了课程中涉及到的各种公式、算法和概念的详细解释,同时也包括了编程作业的指导和解答。而代码部分包含了课程中使用的MATLAB代码,以及Python代码的实现。 这个压缩包对机器学习爱好者和学生来说是一个非常有用的资源,能够让他们深入了解机器学习的基础,并掌握如何运用这些知识去解决实际问题。此外,这个压缩包还可以作为教师和讲师的教学资源,帮助他们更好地传授机器学习的知识和技能。 ### 回答2: coursera-ml-andrewng-notes-master.zip 是一个 Coursera Machine Learning 课程的笔记和教材的压缩包,由学生或者讲师编写。这个压缩包中包括了 Andrew Ng 教授在 Coursera 上发布的 Machine Learning 课程的全部讲义、练习题和答案等相关学习材料。 Machine Learning 课程是一个介绍机器学习的课程,它包括了许多重要的机器学习算法和理论,例如线性回归、神经网络、决策树、支持向量机等。这个课程的目标是让学生了解机器学习的方法,学习如何使用机器学习来解决实际问题,并最终构建自己的机器学习系统。 这个压缩包中包含的所有学习材料都是免费的,每个人都可以从 Coursera 的网站上免费获取。通过学习这个课程,你将学习到机器学习的基础知识和核心算法,掌握机器学习的实际应用技巧,以及学会如何处理不同种类的数据和问题。 总之,coursera-ml-andrewng-notes-master.zip 是一个非常有用的学习资源,它可以帮助人们更好地学习、理解和掌握机器学习的知识和技能。无论你是机器学习初学者还是资深的机器学习专家,它都将是一个重要的参考工具。 ### 回答3: coursera-ml-andrewng-notes-master.zip是一份具有高价值的文件,其中包含了Andrew NgCoursera上开授的机器学习课程的笔记。这份课程笔记可以帮助学习者更好地理解掌握机器学习技术和方法,提高在机器学习领域的实践能力。通过这份文件,学习者可以学习到机器学习的算法、原理和应用,其中包括线性回归、逻辑回归、神经网络、支持向量机、聚类、降维等多个内容。同时,这份笔记还提供了很多代码实现和模板,学习者可以通过这些实例来理解、运用和进一步深入研究机器学习技术。 总的来说,coursera-ml-andrewng-notes-master.zip对于想要深入学习和掌握机器学习技术和方法的学习者来说是一份不可多得的资料,对于企业中从事机器学习相关工作的从业人员来说也是进行技能提升或者知识更新的重要资料。因此,对于机器学习领域的学习者和从业人员来说,学习并掌握coursera-ml-andrewng-notes-master.zip所提供的知识和技能是非常有价值的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值