SVM - 手写数字识别

来源:互联网 发布:java经纬度坐标范围内 编辑:程序博客网 时间:2024/04/28 10:49

1. 流程

  1. 收集数据:此处使用给定的文本文件
  2. 准备数据:基于二值图像构造数据
  3. 分析数据:对图像向量进行目测
  4. 训练算法:采用三种不同的方法,不同的参数
    1. 线性分类器
    2. 二次多项式核函数
    3. 径向基核函数
  5. 测试并计算错误率

2. 实验

本实验使用的训练数据如下图所示,为若干个手写的 0 和 9 的数字图像。

这里写图片描述

本实验使用的测试数据如下图所示,为若干个手写的 0 和 9 的数字图像。

这里写图片描述

实验的主函数如下所示:

% 功能:演示 Kernel SVM算法% 时间:2015-07-13clcclear allclose alladdpath('./data');%% 测试样本dataLength = 2;[xTrain1, yTrain1, xTrain2, yTrain2] = readDataFromFiles('./data/trainingDigits');[xTest1, yTest1, xTest2, yTest2] = readDataFromFiles('./data/testDigits');% 合并样本X = [xTrain1, xTrain2];       Y = [yTrain1, yTrain2];      % 打乱样本顺序index = randperm(size(X, 2));X(:, index) = X;Y(:, index) = Y;%% Kernel SVM 训练kernelType = 'liner';[alpha, b] = kernelSvmTrainMine(X, Y, kernelType);%% 提取 SVepsilon = 1e-5; indexSV = find(alpha > epsilon);%% 测试输出yTestResult1 = sign(sum(bsxfun(@times, alpha(indexSV) .* Y(indexSV)', kernel(X(:, indexSV), xTest1, kernelType))) + b);yTestResult2 = sign(sum(bsxfun(@times, alpha(indexSV) .* Y(indexSV)', kernel(X(:, indexSV), xTest2, kernelType))) + b);sum(yTestResult1 ~= yTest1)sum(yTestResult2 ~= yTest2)

训练数据和测试数据的个数为:

数字 0 9 训练 198 204 测试 97 89

线性分类器的结果如下所示:

类型 系数 测试错误数 支持向量数 线性 无 1 78

二次多项式核函数的结果如下所示,其中的系数是指Kernel(X,X)=(ξ+γXTX)Q中的 γ,并且ξ=1Q=2

类型 系数 测试错误数 支持向量数 二次多项式 0.01 2 79 二次多项式 0.1 2 84 二次多项式 0.25 1 85 二次多项式 0.5 94 48 二次多项式 1 148 14

径向基核函数的结果如下所示,其中的系数是指Kernel(X,X)=e(||XX||22σ2)中的 σ2

类型 系数 测试错误数 支持向量数 径向基 0.1 97 402 径向基 5 1 330 径向基 10 1 114 径向基 50 2 70

3. 总结

从上面的测试中可以看出:
1. 参数的不同对分类的效果影响很大
2. 并不是说最小的训练错误率对应于最小的支持向量数目。
3. 训练后的识别阶段并不需要所有训练样本,只需要支持向量
4. 线性核函数的训练效果并不糟糕,在某些情况下如果线性核函数就以满足要求就可不使用其他复杂核函数。

4. 完整代码和数据

我的GitHub

5. 参考

SVM 支持向量机

Dual SVM 对偶支持向量机

Kernel SVM

《机器学习实战》第六章

0 0
原创粉丝点击