one-vs-all案例

简介: 使用one-vs-all初始手写字母识别数据特点每一个图片都是20 x 20的像素矩阵,但是在输入的样本中是一个1 x 400的向量,标签y在{0, 1, 2, ..., 9}之间取值共有5000个训练样本可视化数据从5000个样本中随机的挑选出100个训练样本进行可视化得到的10...

使用one-vs-all初始手写字母识别

数据特点

  • 每一个图片都是20 x 20的像素矩阵,但是在输入的样本中是一个1 x 400的向量,标签y在{0, 1, 2, ..., 9}之间取值
  • 共有5000个训练样本

可视化数据

  • 从5000个样本中随机的挑选出100个训练样本进行可视化
  • 得到的100个样本中,每一个样本都是一个向量,要想对其可视化,需要将其从向量还原为原始的矩阵
  • 首先确定矩阵的高和宽(单位是像素pixel)
  • 创建一个displayArray矩阵,用来保存100个样本转换为矩阵的像素数据,形象地讲,就是将100个图片放到一个大的面板上,这样才能做到可视化数据
  • 初始完毕displayArray矩阵之后,使用matlib中的imagesc函数将其显示出来
  • 代码如下:
  • myDisplayData.m
function [h, displayArray] = myDisplayData(X)

% 获取一张图片的高和宽
exampleHeight = round(sqrt(size(X(1, :), 2)));
exampleWidth = round(size(X(1, :), 2) / exampleHeight);

% 计算整个面板的高和宽(但是是图片的个数)
[m, n] = size(X);
displayRows = round(sqrt(m));
displayCols = round(m / displayRows);

% 先创建出displayRows * exampleHeight, displayCols * exampleWidth的面板
displayArray = ones(displayRows * exampleHeight, displayCols * exampleWidth);

% 将图片放到面板对应的位置上
% 下面的式子就和数学有一些关系,如何确定现在填充的矩阵在displayArray中的位置
currExample = 1;
for i = 1:displayRows
    for j = 1:displayCols
        displayArray(...
                     (i - 1) * exampleWidth + 1:exampleWidth + (i - 1) * exampleWidth, ...
                     (j - 1) * exampleHeight + 1:exampleHeight + (j - 1) * exampleHeight ...
                     ) = ...
                                                 reshape(X(currExample, :), ...
                                                 exampleHeight, exampleWidth);
        currExample = currExample + 1;
    end
end

colormap(gray);
h = imagesc(display_array);
axis image off;
end

数据预处理

  • 为X添加bias(偏移量): X = [ones(m, 1), X]; % m表示样本的数量
  • m: 训练样本的数量
  • n: 特征的数量,不包括bias(偏移)特征
  • y: 标签,{0, 1, 2, ..., 9}
  • numLabel: y可以取的值的个数,这里为10

确定假设函数

  • 由题目可知,这是一个典型的Multi-Class Logistic Regression问题,因此使用逻辑回归模型
  • 模型函数: \[h(\theta)=g(\theta^{T}x)={{1}\over{1+e^{-\theta^{T}x}}}\]
  • 因为这个一个10分类的问题,所以需要拟合出10个假设函数才行,也就是要最小化出10个\(\theta\)向量,我们调用oneVsAll函数返回的参数应该是一个矩阵,每一个行向量是一个类别的假设函数的参数

计算损失函数(cost function)和梯度

  • 损失函数公式: \[J(\theta)={{1}\over{m}}\sum_{i=1}^m(-y^{(i)}log(h_{\theta}(x^{(i)})) - (1-y^{(i)})log(1-h_{\theta}(x^{(i)})))+{{\lambda}\over{2m}}\sum_{j=1}^m{\theta_{j}^2}\]其中\(\theta\), \(y^{(i)}\), \(x^{(i)}\)为向量或者矩阵,后一项是对非偏差项的正则化
  • 梯度公式: j >= 1 \[{{\partial}\over{\partial}\theta_{j}}J(\theta)={{1}\over{m}}\sum_{i=1}^m{(h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}} + {{\lambda}\over{m}}\theta_{j}\] j = 0 \[{{\partial}\over{\partial}\theta_{0}}J(\theta)={{1}\over{m}}\sum_{i=1}^m{(h_{\theta}(x^{(i)})-y^{(i)})x^{(i)}}\]
  • 注意,上面的\(h_{\theta}(x^{(i)})\)是sigmoid函数,自己在实现的时候总是将其写成线性回归函数

在oneVsAll.m文件中实现\(minimize_{\theta}J(\theta)\)

  • 每一个类都进行梯度下降,计算出这一类的参数,也就是写一个循环,在每一个循环中都有可以得到最终的这个类别对应的参数,循环的次数为numLabels
  • 核心代码

    for index = 1:numLabels 
      initialTheta = zeros(n + 1, 1);
      options = optimset('GradObj', 'on', 'MaxIter', 50);
      % fmincg会自动选择最优的学习率alpha
      allTheta(index, :) = fmincg(@(t)(lrCostFunction(t, X, (y == index), lambda)), ...
                              initialTheta, options);
    end

预测

  • 输入的一个样本,需要为其添加bias值,在将样本分别输入到10个假设函数中,计算出最大的值,那个值对应的就是类别。
  • 核心代码
tmp = zeros(m, num_labels);
for i = 1:num_labels
    tmp(:, i) = sigmoid(X * allTheta(i, :)');
end
[val, p] = max(tmp, [], 2);
目录
相关文章
|
2月前
|
存储 数据库 对象存储
Seeion 和案例
Seeion 和案例
|
7月前
|
数据安全/隐私保护
基础项目实用案例
基础项目实用案例
188 2
|
9月前
|
SQL 消息中间件 缓存
|
9月前
|
JavaScript 前端开发 Java
案例综合题。
案例综合题。
39 0
|
10月前
|
前端开发 JavaScript
全选反选案例
全选反选案例
65 0
|
NoSQL Redis
StringRedisTemplate的一个小案例(三)
StringRedisTemplate的一个小案例(三)
95 0
|
前端开发
使用案例
使用案例
118 0
|
搜索推荐 索引 Python
特殊案例,为什么a, b = b, a结果跟你想的不一样?
特殊案例,为什么a, b = b, a结果跟你想的不一样?
143 0
特殊案例,为什么a, b = b, a结果跟你想的不一样?
html+css实战63-综合案例2-内容完成
html+css实战63-综合案例2-内容完成
263 0
html+css实战63-综合案例2-内容完成