Andrew NG 机器学习 练习3-Multiclass Classification and Neural Networks

来源:互联网 发布:c语言字符串最前面是0 编辑:程序博客网 时间:2024/05/29 16:56

In this exercise, you will implement one-vs-all logistic regression and neural networks to recognize hand-written digits.

1 Multi-class Classification

In the first part of the exercise, you will extend your previous implemention of logistic regression and apply it to one-vs-all classification.

1.1 Dataset

ex3data1.mat 文件中有5000 个训练样例。
.mat 文件能在本地存储矩阵形式,可以直接读到程序程序内存中,矩阵已经定义了名字。

% Load saved matrices from fileload('ex3data1.mat');% The matrices X and y will now be in your Octave environment

每个训练样例,是一个20*20像素的图片灰度数值。每个像素通过一个浮点类型的值来表示灰度值。20*20像素的数值被展开成一个400*1的向量。每一个训练数据占数据矩阵X 的一行。所以X 为 5000*400 的矩阵。

训练数据的第二部分是一个 5000 维的向量 y ,他是 训练数据的标签。

为了适配Octave和MATLAB 的indexing , 由于没有 0 索引,所以用数字 10 表示 0 ,因此数字 0 被标记为 10,数字 1 到 9,被标记为 1 到 9.

1.2 Visualizing the data

随机抽出100行数据,展示

%% Setup the parameters you will use for this part of the exerciseinput_layer_size  = 400;  % 20x20 Input Images of Digitsnum_labels = 10;          % 10 labels, from 1 to 10                          % (note that we have mapped "0" to label 10)%% =========== Part 1: Loading and Visualizing Data =============%  We start the exercise by first loading and visualizing the dataset.%  You will be working with a dataset that contains handwritten digits.%% Load Training Datafprintf('Loading and Visualizing Data ...\n')load('ex3data1.mat'); % training data stored in arrays X, ym = size(X, 1);% Randomly select 100 data points to displayrand_indices = randperm(m);sel = X(rand_indices(1:100), :);%随机抽出100行数据displayData(sel);%将每一行的数据映射为20*20的灰度图像,并一起显示fprintf('Program paused. Press enter to continue.\n');pause;

displayData.m

function [h, display_array] = displayData(X, example_width)%DISPLAYDATA Display 2D data in a nice grid%   [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data%   stored in X in a nice grid. It returns the figure handle h and the %   displayed array if requested.% Set example_width automatically if not passed inif ~exist('example_width', 'var') || isempty(example_width)     example_width = round(sqrt(size(X, 2)));end% Gray Imagecolormap(gray);% Compute rows, cols[m n] = size(X);example_height = (n / example_width);% Compute number of items to displaydisplay_rows = floor(sqrt(m));display_cols = ceil(m / display_rows);% Between images paddingpad = 1;% Setup blank displaydisplay_array = - ones(pad + display_rows * (example_height + pad), ...                       pad + display_cols * (example_width + pad));% Copy each example into a patch on the display arraycurr_ex = 1;for j = 1:display_rows    for i = 1:display_cols        if curr_ex > m,             break;         end        % Copy the patch        % Get the max value of the patch        max_val = max(abs(X(curr_ex, :)));        display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ...                      pad + (i - 1) * (example_width + pad) + (1:example_width)) = ...                        reshape(X(curr_ex, :), example_height, example_width) / max_val;        curr_ex = curr_ex + 1;    end    if curr_ex > m,         break;     endend% Display Imageh = imagesc(display_array, [-1 1]);% Do not show axisaxis image offdrawnow;end

这里写图片描述

1.3 Vectorizing Logistic Regression

你讲使用多重的一对多逻辑回归模型来建立一个多类别分类器。因为有10种类别,你需要训练10种分开的逻辑回归分类器。

1.3.1 Vectorizing the cost function

Recall that in (unregularized) logistic regression, the cost function is :
J(θ)=1mi=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]

这里写图片描述

向量方式的实现是:
h=g(Xθ)J(θ)=1m(yTlog(h)(1y)Tlog(1h))

h=sigmoid(X*theta);J=1/m*(-y'*log(h)-(1-y)'*log(1-h));grad = (X' * (sigmoid(X*theta) - y)) ./ m;

1.3.2 Vectorizing the gradient

Recall that the gradient of the (unregularized) logistic regression cost is a vector where the j th element is defined as

θjJ(θ)=1mi=1m(hθ(x(i))y(i))x(i)j

向量方式的实现是:
1mXT(g(Xθ)y⃗ )

To vectorize this operation over the dataset, we start by writing out all the partial derivatives explicitly for all θj,
这里写图片描述

1.3.3 Vectorizing regularized logistic regression

J(θ)=1mi=1m[y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i)))]+λ2mj=1nθ2j

这里写图片描述

要最小化该代价函数,通过求导,得出梯度下降算法为:
Repeat {    θ0:=θ0α 1m i=1m(hθ(x(i))y(i))x(i)0    θj:=θjα [(1m i=1m(hθ(x(i))y(i))x(i)j)+λmθj]}          j{1,2...n}

θ0 不参与其中的任何一个正则化。

lrCostFunction.m

function [J, grad] = lrCostFunction(theta, X, y, lambda)%LRCOSTFUNCTION Compute cost and gradient for logistic regression with %regularization%   J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using%   theta as the parameter for regularized logistic regression and the%   gradient of the cost w.r.t. to the parameters. % Initialize some useful valuesm = length(y); % number of training examples% You need to return the following variables correctly J = 0;grad = zeros(size(theta));% ====================== YOUR CODE HERE ======================% Instructions: Compute the cost of a particular choice of theta.%               You should set J to the cost.%               Compute the partial derivatives and set grad to the partial%               derivatives of the cost w.r.t. each parameter in theta%% Hint: The computation of the cost function and gradients can be%       efficiently vectorized. For example, consider the computation%%           sigmoid(X * theta)%%       Each row of the resulting matrix will contain the value of the%       prediction for that example. You can make use of this to vectorize%       the cost function and gradient computations. %% Hint: When computing the gradient of the regularized cost function, %       there're many possible vectorized solutions, but one solution%       looks like:%           grad = (unregularized gradient for logistic regression)%           temp = theta; %           temp(1) = 0;   % because we don't add anything for j = 0  %           grad = grad + YOUR_CODE_HERE (using the temp variable)%h=sigmoid(X*theta);J=1/m*(-y'*log(h)-(1-y)'*log(1-h))+lambda/(2*m)*(sum(theta.^2) - theta(1)^2);grad(1)=(X(:,1)' * (h - y)) ./ m;for i = 2:size(theta)    grad(i) = (X(:,i)' * (h - y)) ./ m+lambda/m*theta(i);% =============================================================end
%% ============ Part 2a: Vectorize Logistic Regression ============%  In this part of the exercise, you will reuse your logistic regression%  code from the last exercise. You task here is to make sure that your%  regularized logistic regression implementation is vectorized. After%  that, you will implement one-vs-all classification for the handwritten%  digit dataset.%% Test case for lrCostFunctionfprintf('\nTesting lrCostFunction() with regularization');theta_t = [-2; -1; 1; 2];X_t = [ones(5,1) reshape(1:15,5,3)/10];y_t = ([1;0;1;0;1] >= 0.5);lambda_t = 3;[J grad] = lrCostFunction(theta_t, X_t, y_t, lambda_t);fprintf('\nCost: %f\n', J);fprintf('Expected cost: 2.534819\n');fprintf('Gradients:\n');fprintf(' %f \n', grad);fprintf('Expected gradients:\n');fprintf(' 0.146561\n -0.548558\n 0.724722\n 1.398003\n');fprintf('Program paused. Press enter to continue.\n');pause;

1.4 One-vs-all Classification

fmincg works similarly to fminunc, but is more more efficient for dealing with a large number of parameters.

所谓多分类问题,是指分类的结果为三类以上。比如,预测明天的天气结果为三类:晴(用y==1表示)、阴(用y==2表示)、雨(用y==3表示)

分类的思想,其实与逻辑回归分类(默认是指二分类,binary classification)很相似,对“晴天”进行分类时,将另外两类(阴天和下雨)视为一类:(非晴天),这样,就把一个多分类问题转化成了二分类问题。

对于N分类问题(N>=3),就需要N个假设函数(预测模型),也即需要N组模型参数θ(θ一般是一个向量)

然后,对于每个样本实例,依次使用每个模型预测输出,选取输出值最大的那组模型所对应的预测结果作为最终结果。

因为模型的输出值,在sigmoid函数作用下,其实是一个概率值。注意:h(1)θ(x)h(2)θ(x)h(3)θ(x)三组 模型参数θ 一般是不同的。比如:

h(1)θ(x),输出 预测为晴天(y==1)的概率
h(2)θ(x),输出 预测为阴天(y==2)的概率
h(3)θ(x),输出 预测为雨天(y==3)的概率

对于上面的识别阿拉伯数字的问题,一共需要训练出10个逻辑回归模型,每个逻辑回归模型对应着识别其中一个数字。

我们一共有5000个样本,样本的预测结果值就是:y={1,2,3,4,5,6,7,8,9,10},其中 10 代表 数字0

我们使用Matlab fmincg库函数 来求解使得代价函数取最小值的 模型参数θ

%% ============ Part 2b: One-vs-All Training ============fprintf('\nTraining One-vs-All Logistic Regression...\n')lambda = 0.1;[all_theta] = oneVsAll(X, y, num_labels, lambda);fprintf('Program paused. Press enter to continue.\n');pause;

oneVsAll.m

function [all_theta] = oneVsAll(X, y, num_labels, lambda)%ONEVSALL trains multiple logistic regression classifiers and returns all%the classifiers in a matrix all_theta, where the i-th row of all_theta %corresponds to the classifier for label i%   [all_theta] = ONEVSALL(X, y, num_labels, lambda) trains num_labels%   logistic regression classifiers and returns each of these classifiers%   in a matrix all_theta, where the i-th row of all_theta corresponds %   to the classifier for label i% Some useful variablesm = size(X, 1); %样本数 5000n = size(X, 2); %特征数 400% You need to return the following variables correctly all_theta = zeros(num_labels, n + 1);% Add ones to the X data matrixX = [ones(m, 1) X];% ====================== YOUR CODE HERE ======================% Instructions: You should complete the following code to train num_labels%               logistic regression classifiers with regularization%               parameter lambda. %% Hint: theta(:) will return a column vector.%% Hint: You can use y == c to obtain a vector of 1's and 0's that tell you%       whether the ground truth is true/false for this class.%% Note: For this assignment, we recommend using fmincg to optimize the cost%       function. It is okay to use a for-loop (for c = 1:num_labels) to%       loop over the different classes.%%       fmincg works similarly to fminunc, but is more efficient when we%       are dealing with large number of parameters.%% Example Code for fmincg:%%     % Set Initial theta%     initial_theta = zeros(n + 1, 1);%     %     % Set options for fminunc%     options = optimset('GradObj', 'on', 'MaxIter', 50);% %     % Run fmincg to obtain the optimal theta%     % This function will return theta and the cost %     [theta] = ...%         fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ...%                 initial_theta, options);%initial_theta = zeros(n + 1, 1); % 模型参数θ的初始值(n == 400),所以initial_theta 向量有401个元素options = optimset('GradObj','on','MaxIter',50);for c = 1:num_labels      %num_labels 为逻辑回归训练器的个数,分10类,所以为 10    all_theta(c, :) = fmincg(@(t)(lrCostFunction(t, X, (y == c),lambda)), initial_theta,options );% all_theta是一个10*401的矩阵,每一行存储着一个分类器(模型)的模型参数的θ向量end% =========================================================================end

下面来解释一下 for循环:

num_labels 为分类器个数,共10个,每个分类器(模型)用来识别10个数字中的某一个。

我们一共有5000个样本,每个样本有400中特征变量,因此:模型参数θ 向量有401个元素。

initial_theta = zeros(n + 1, 1); % 模型参数θ的初始值(n == 400)

all_theta是一个10*401的矩阵,每一行存储着一个分类器(模型)的模型参数θ 向量,执行上面for循环,就调用fmincg库函数 求出了 所有模型的参数θ 向量了。

1.4.1 One-vs-all Prediction

求出了每个模型的参数向量θ,就可以用 训练好的模型来识别数字了。对于一个给定的数字输入(400个 feature variables) input instance,每个模型的假设函数 h(i)θ(x) 输出一个值(i = 1,2,…10)。取这10个值中最大值那个值,作为最终的识别结果。比如g(h(8)θ(x))==0.96 比其它所有的 g(h(i)θ(x)) (i = 1,2,…10,但 i 不等于8) 都大,则识别的结果为 数字 8

%% ================ Part 3: Predict for One-Vs-All ================pred = predictOneVsAll(all_theta, X);fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);

predictOneVsAll.m

function p = predictOneVsAll(all_theta, X)%PREDICT Predict the label for a trained one-vs-all classifier. The labels %are in the range 1..K, where K = size(all_theta, 1). %  p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions%  for each example in the matrix X. Note that X contains the examples in%  rows. all_theta is a matrix where the i-th row is a trained logistic%  regression theta vector for the i-th class. You should set p to a vector%  of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2%  for 4 examples) m = size(X, 1);num_labels = size(all_theta, 1);% You need to return the following variables correctly p = zeros(size(X, 1), 1);% Add ones to the X data matrixX = [ones(m, 1) X];  %给 X 增加一个全为1的列% ====================== YOUR CODE HERE ======================% Instructions: Complete the following code to make predictions using%               your learned logistic regression parameters (one-vs-all).%               You should set p to a vector of predictions (from 1 to%               num_labels).%% Hint: This code can be done all vectorized using the max function.%       In particular, the max function can also return the index of the %       max element, for more information see 'help max'. If your examples %       are in rows, then, you can use max(A, [], 2) to obtain the max %       for each row.%       [~,p] = max( X * all_theta',[],2); % 求矩阵(X*all_theta')每行的最大值,p 记录矩阵每行的最大值的索引% =========================================================================end

2 Neural Networks

本作业使用神经网络(neural networks)识别手写的阿拉伯数字(0-9)

由于逻辑回归是线性分类(它的假设函数是一个线性函数,就是划一条直线,把数据分成了两类。

对于一些复杂的类别,逻辑回归就解决不了了。比如下面这个图片中的分类。(无法通过 划直线 将 叉叉 和 圆圈 分开)

这里写图片描述

而神经网络,则能够实现很复杂的非线性分类问题。

对于神经网络而言,同样有一个训练样本矩阵 X,同时还有一个模型参数 Theta 矩阵,通过某种算法将 模型参数矩阵 训练好之后(求出 Theta 矩阵),再使用前向传播算法( feedforward propagation algorithm)(感觉就像是矩阵相乘嘛), 就可以对输入的测试样本进行预测了。

本作业中, 模型参数 Theta 矩阵是已经训练好了的,直接 load 到Matlab中即可。

%% ================ Part 2: Loading Pameters ================% In this part of the exercise, we load some pre-initialized % neural network parameters.fprintf('\nLoading Saved Neural Network Parameters ...\n')% Load the weights into variables Theta1 and Theta2load('ex3weights.mat');%% ================= Part 3: Implement Predict =================%  After training the neural network, we would like to use it to predict%  the labels. You will now implement the "predict" function to use the%  neural network to predict the labels of the training set. This lets%  you compute the training set accuracy.pred = predict(Theta1, Theta2, X);fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);fprintf('Program paused. Press enter to continue.\n');pause;%  To give you an idea of the network's output, you can also run%  through the examples one at the a time to see what it is predicting.%  Randomly permute examplesrp = randperm(m);for i = 1:m    % Display     fprintf('\nDisplaying Example Image\n');    displayData(X(rp(i), :));    pred = predict(Theta1, Theta2, X(rp(i),:));    fprintf('\nNeural Network Prediction: %d (digit %d)\n', pred, mod(pred, 10));    % Pause with quit option    s = input('Paused - press enter to continue, q to exit:','s');    if s == 'q'      break    endend

predict.m

function p = predict(Theta1, Theta2, X)%PREDICT Predict the label of an input given a trained neural network%   p = PREDICT(Theta1, Theta2, X) outputs the predicted label of X given the%   trained weights of a neural network (Theta1, Theta2)% Useful valuesm = size(X, 1);num_labels = size(Theta2, 1);% You need to return the following variables correctly p = zeros(size(X, 1), 1); % p 是 5000*1向量% ====================== YOUR CODE HERE ======================% Instructions: Complete the following code to make predictions using%               your learned neural network. You should set p to a %               vector containing labels between 1 to num_labels.%% Hint: The max function might come in useful. In particular, the max%       function can also return the index of the max element, for more%       information see 'help max'. If your examples are in rows, then, you%       can use max(A, [], 2) to obtain the max for each row.%% 模拟实现前向传播算法X = [ones(m, 1) X];a_super_2 = sigmoid(Theta1 * X');a_super_2 = [ones(1,m); a_super_2];% add bias unita_super_3 = sigmoid(Theta2 * a_super_2);% =========================================================================[~,p] = max( a_super_3' ,[], 2 ); % 对样本的结果进行预测,与逻辑回归的预测类似,选取输出的最大值 作为最终的预测结果end

注意:我们正是通过Matlab 的 max 函数,求得矩阵 a_super3′ 的每一行的最大值。将每一行的中的最大值 的索引 赋值给向量p。其中,a_super3′ 是一个5000行乘10列的矩阵

向量p就是预测的结果向量。而由于 a_super3′ 有10列,故 p 中每个元素的取值范围为[1,10],即分别代表了数字 0-9(其中10 表示 0)

Matlab 实现结果:

Loading Saved Neural Network Parameters …
Training Set Accuracy: 97.520000

对于图片,预测结果:
这里写图片描述

Displaying Example Image

Neural Network Prediction: 9 (digit 9)
Paused - press enter to continue, q to exit:

阅读全文
1 0
原创粉丝点击