1.多类别分类
本文将使用逻辑回归和神经网络来识别手写数字( 0-9 )。以下代码皆为matlab实现。
1.1 数据集
% 从文件中加载已保存的矩阵
load('ex3data1.mat');
% 矩阵X和y将已经存在MATLAB环境中
数据集中一共有5000个训练样本,每个训练样本是2020像素的数字灰度图像。每个像素为一个浮点数,代表在当前位置的灰度值。将2020的像素展开成一个400的向量。则整个数据集X则是5000*400的矩阵。每一行都是一个训练样本。
训练集的第二个部分是5000维的向量y,y包含训练集的标签,为了使其余MATLAB indexing更加兼容。y中没有0标签,将其替换为10。因此,‘0’数字被标记为’10’,‘1’到‘9’被标记为’1’到’9’。
1.2 可视化数据
从X中随机选择100行,并将它们传送给displayData函数。整个函数将每行映射为一个20*20像素的灰度图像并其它们一起打印出来。
m = size(X, 1);
% 随机选择100个数据点
rand_indices = randperm(m);
sel = X(rand_indices(1:100),:);
displayData(sel);
dispalyData(sel)代码如下:
function [h, display_array] = display(X, example_width)
% 在网格中显示2D数字。返回手写图形数字h,如果需要则还返回显示的数组
% 如果没有传入自动设置example_width
if ~exist('example_width', 'var') || isempty(example_width)
example_width = round(sqrt(size(X, 2));
% 灰度图
colormap(gray);
% 计算每个样本的行,列的像素数量。
[m, n] = size(X); %在本例中,X为100*400
example_height = (n / example_width);
% 计算要显示的元素的个数
display_rows = floor(sqrt(m));
display_cols = ceil(m / display_rows);
% 图像之间填充
pad = 1;
% 设置显示背景为黑色
display_array = -ones(pad + display_rows * (example_height + pad), pad + display * (example_height + pad));
% 将每个样本复制到显示阵列的patch中。
curr_ex = 1;
for j = 1:display_rows
for i = 1:display_cols
if curr_ex > m,
break;
end
% 复制 patch
% 获取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;
end
end
% 显示图像
h = imagesc(display_array, [-1 1]);
% 不显示轴
axis image off
1.3 向量化逻辑回归
我们将使用One-vs-all逻辑回归模型来构建一个分类表分类器。因为我们有10中类别,所有将需要训练10中不同的逻辑回归分类器。为了使训练有效,确保代码可向量化非常重要。
1.3.1 向量化损失函数
J ( θ ) = 1 m ∑ i = 1 m [ − y ( i ) l o g ( h θ ( x ( i ) ) ) − ( 1 − y ( i ) ) l o g ( 1 − h θ ( x ( i ) ) ) ] J(θ) = \frac{1}{m}\sum_{i=1}^m[-y^{(i)}log(h_θ(x^{(i)}))-(1-y^{(i)})log(1-h_θ(x^{(i)}))] J(θ)=m