此系列文章主要为记录作业过程,也为卡在某处提供些许思路,所以还是建议独立完成,这样对知识的理解最为深刻。
plotData
这部分内容是已经写好的,但还是应该认真读一遍代码,看看究竟是如何绘图的。核心的代码如下:
% 设置灰色图谱,这样就可以使用小数数值来
colormap(gray);
% 计算example(一个数字可以看做一个example)的个数和每个example的像素高度(等于像素总数/像素宽度)
[m n] = size(X);
example_height = (n / example_width);
% 计算展示多少行的example,每行展示多少个example
display_rows = floor(sqrt(m));
display_cols = ceil(m / display_rows);
% 每个example上下左右的padding(参考CSS的盒模型)
pad = 1;
% 初始化数组,初始值都是-1
display_array = - ones(pad + display_rows * (example_height + pad), ...
pad + display_cols * (example_width + pad));
% 将X中的值赋给display中对应的位置
curr_ex = 1;
for j = 1:display_rows
...
% 先取example列最大值,再使用reshape将行向量转为数组,除以最大值后赋给display_array的对应位置
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;
end
end
% 展示图片
h = imagesc(display_array, [-1 1]);
lrCostFunction
直接套用线性回归的公式即可,需要注意的是第一个变量是不需要正规化的。参考代码如下:
tmp = theta;
tmp(1) = 0;
J = -1 / m * (y' * log(sigmoid(X * theta)) + (1 - y') * log(1 - sigmoid(X * theta))) + lambda / 2 / m * (tmp' * tmp);
grad = 1 / m * (X' * (sigmoid(X * theta) -y)) + (lambda / m) * tmp;
oneVsAll
根据提示很好写,我这里使用了for循环,应该可以直接用向量化来做的:
for c = 1:num_labels
% Set Initial theta
initial_theta = zeros(n + 1, 1);
% Set options for fminunc
options = optimset('GradObj', 'on', 'MaxIter', 50);
[all_theta(c,:), fX, i] = fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), initial_theta, options);
endfor
predictOneVsAll
这部分比较困难,主要还是对线性回归和Octave中的数组运算不熟悉。首先线性回归的预测计算的结果需要sigmoid,得到predictH
;再使用max(predictH, [], 2)
求出每一行的最大值;接着使用predictH == max(predictH, [], 2)
使得最大值的位置得到1,其他位置都为0;然后使用find(tmp)
来得到每一行最大值的列号;最后因为1 ~ 9的位置对应1 ~ 9的预测,10的位置对应0,所以直接使用p(i) = j
就可以得到最终的预测结果,参考代码如下:
predictH = sigmoid(X * all_theta');
tmp = predictH == max(predictH, [], 2);
[i, j] = find(tmp);
p(i) = j;
predict
使用现成的参数,和上面一部分基本一致,只不过计算过程变成了后向传播算法,别忘加bias就行,参考代码如下:
X = [ones(m, 1), X];
a2 = sigmoid(X * Theta1');
a2 = [ones(size(a2, 1), 1), a2];
a3 = sigmoid(a2 * Theta2');
tmp = a3 == max(a3, [], 2);
[i, j] = find(tmp);
p(i) = j;