(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]

这次打算以代码为主线,适当补充。

问题:

手写数字识别。
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第1张图片

方法一:逻辑回归

for c = 1:num_labels
    initial_theta = zeros(n + 1, 1);
    % Set options for fminunc
    options = optimset('GradObj', 'on', 'MaxIter', 50);
    [theta] = fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ...
                initial_theta, options);            
    all_theta(c, :) = theta';
end

上面的意思就是采用梯度下降的方法,迭代50次(调用50次lrCostFunction计算 θnew ),那么这个lrCostFunction又是何方神圣呢?下面就是lrcostFunction的主要内容

h = sigmoid(X * theta);
J = 1/m * ( -y' * log(h) -(1-y)' * log(1-h)) + lambda/(2*m) * (theta(2:end)' * theta(2:end));

G = theta;
G(1) = 0;
grad = 1/m * X' * (h-y) + lambda/m .* G;

这里 XRm×(n+1),msamplenfeature `y == c`就是分别对这几个数进行逻辑回归,训练各自的 θ 。 写成数学公式就和之前单个的一样,不再赘述。

得到了 θall ,就能用来进行分类了,代码如下:

pre = X * all_theta';
[maxVal, p] = max(pre, [], 2);

在训练集上的准确率94.96%。

方法二:神经网络

什么是神经网络?
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第2张图片
像这个样子,有好几层,中间是隐藏层,输入层,输出层。
目前看到的例子是用于分类,那么它和逻辑回归有什么异同点呢?
我是这么理解的,可以认为是一群逻辑回归,一层一层的。比如对于逻辑回归,计算出 a(2)1 就完事了,但是神经网络的话这只是其中的一小步。 比如上图中a^{(2)}=g(x^T\Theta), 这里x=$$\begin{bmatrix} x_0 \ x_1\x_2\x_3\end{bmatrix}$, $\Theta=\begin{bmatrix} \vdots & \cdots & \vdots \\end{bmatrix}$不写了好麻烦,$\Theta$就是个大矩阵$\subset R^{{(l1+1)} \times {(l2)}}$。

下面按照算法步骤讲解,首先要做的就是随机初始化 Θ ,这里是 Θ(1),Θ(2) ,为什么要做随机初始化呢?因为初始化全0的话最后一层就是全0,所以就“都一样”了。下面的W就是我们的 Θ

function W = randInitializeWeights(L_in, L_out)

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

end

这里将 Θ(1),Θ(2) 都放到一个列向量里,方便传递参数,之后再“恢复原样”就行了。
initial_nn_params = [initial_Theta1(:) ; initial_Theta2(:)];

下面是核心步骤:

options = optimset('MaxIter', 50);

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

[nn_params, cost] = fmincg(costFunction, initial_nn_params, options);

首先设置终止条件,迭代50次,接着定义nnCostFunction这里面计算了 Θ 的梯度以及 J fmincg传入了三个参数,意思是利用初始的 Θ 迭代50次(调用costFunction50次,这里迭代次数为终止条件,所以 Θ 梯度的计算尤为重要)。接下来看看nnCostFunction里面究竟是什么,其实它的目的就是计算 Θ(Θ(1),Θ(1)J)

%% 首先把Theta1, Theta2还原
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));
%% 样本个数m
% 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));

%% 正向传播计算J
a1 = [ones(m, 1) X];
z2 = a1 * Theta1';
a2 = sigmoid(z2);
a2 = [ones(m, 1) a2];
z3 = a2 * Theta2';
a3 = sigmoid(z3);

Y = zeros(m, num_labels);
for i = 1:num_labels
    Y(find(y == i), i) = 1;
end

% 计算J
Jc = (-Y .* log(a3) - (1-Y) .* log(1-a3));
J = 1/m .* sum( Jc(:) );
% 加上正则项
theta1 = Theta1;theta1(:,1) = 0;t1 = theta1 .^ 2;
theta2 = Theta2;theta2(:,1) = 0;t2 = theta2 .^ 2;
Regu = lambda/(2*m) * (sum(t1(:)) + sum(t2(:)));
J = J + Regu;

%% 反向传播,为了计算Theta1, Theta2 的梯度
for t=1:m
    delta3 = a3(t,:) - Y(t,:);
    delta2 = delta3 * Theta2(:,2:end) .* sigmoidGradient(z2(t,:));
    Theta2_grad = Theta2_grad + delta3' * a2(t,:);
    Theta1_grad = Theta1_grad + delta2' * a1(t,:);
end
% 加上正则项
Theta1(:,1) = 0;Theta2(:,1) = 0;
Theta1_grad = 1/m .* Theta1_grad + lambda/m .* Theta1;
Theta2_grad = 1/m .* Theta2_grad + lambda/m .* Theta2;

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

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

end

下面附上对应的数学公式:
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第3张图片
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第4张图片
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第5张图片

至此,正向(计算 J )&反向传播(计算 gradΘ )就搞定了。

梯度检测Gradient checking

还剩下一点没说,梯度检测,梯度检测就是为了看看 Θ 对不对,比如先迭代一次,会算出一个 Θ,J ,然后利用 J 算出数值梯度,并与求导算出的梯度对比。
(三)Multi-class Classification and Neural Networks[多分类问题和神经网络]_第6张图片
贴上代码看看:
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]);

如果误差很小,那么就可以安心的training了!实际training的时候一般要注释掉check的步骤,减少不必要的计算时间。

至此,关于数字识别的逻辑回归&神经网络算梳理复习完了,还是看着代码有一种更踏实的感觉,嘿嘿。

你可能感兴趣的:(机器学习)