初次是根据“支持向量机通俗导论(理解SVM的三层境界)”对SVM有了简单的了解。总的来说其主要的思想可以概括为以下两点(也是别人的总结)
1、SVM是对二分类问题在线性可分的情况下提出的,当样本线性不可分时,它通过非线性的映射算法,将在低维空间线性不可分的样本映射到高维的特征空间使其线性可分,从而使得对非线性可分样本进行线性分类。
2、SVM是建立在统计学习理论的 VC理论和结构风险最小化原理基础上的,在保证样本分类精度的前提下,建立最优的分割超平面,使得学习器有较好的全局性和推广性。
第一个能在“支持向量机通俗导论”中找到答案,但第二个就有点难理解(其实自己就理解一丢丢)。
统计学习理论:所谓的统计学习理论是研究统计估计和预测的理论,它在理论上系统的研究了结构风险的问题,即在经验风险最小化(保证训练样本的分类准确率)原则成立、有限样本下的经验风险(训练样本)与致信风险(测试样本)的关系。
VC理论:为了研究学习过程的一致收敛的速度和推广性,统计学习理论定义了一系列有关于函数集学习性能的指标,其中最重要的是VC维(Vapnik-Chervonenkis Dimesion) 。模式识别方法中对VC维的定义是直观的:对一个指示函数集,如果存在h个样本能够被函数集中的函数按所有的 种形式分开,则称函数集能够把h个样本打散;函数集的VC维就是它能打散的最大样本数目h。若对任意数目的样本都有函数能将它们打散,则函数集的VC维就是无穷大的。函数集的VC维反映了其学习的能力,VC维越大,则该函数集的学习能力越大,如一个三角函数的函数集,能将任意组合的样本进行分类,其VC维是无穷大的,相对的在n维空间下线性函数的VC维是n+1。学习能力越强也就意味着学习机器的复杂度越高,对新样本分类的置信度就越低,从而使实际风险较高。从而机器学习中在保证经验风险最小的前提下,应该尽量降低函数集的VC维,才能使实际风险较小,从而取得较好的推广性。(在线性可分的情况下容易体现这一点,超平面在保持样本线性可分的情况下(经验风险小),使两个支持向量的几何间距尽量大(实际风险小))。
多分类问题的解决方法:构造SVM多类分类器 的方法主要有两类:一类是直接法,直接在目标函数上进行修改,将多个分类面的参数求解合并到一个最优化问题中,通过求解该最优化问题“一次性”实现多类分类,但其计算复杂度比较高,训练时间长,适合用于小规模问题。另一类是间接法,主要是通过组合多个二分类器来实现多分类器的构造,如在有 10 类,那就要设计 10 个二类分类器,比如分类器 0 将 0与 数字分开,分类器1将1与 数字分开,依次类推。在林智仁先生的 Libsvm工具箱,是对任意两类样本建立了一个SVM,因此k个类别的样本就需要设计 k(k-1)/2 个SVM。当对一个未知样本进行分类时,将该样本的特征向量放到这 k(k-1)/2 个SVM中进行决策并投票,最后得票最多的类别即为该未知样本的类别。
参数选择:在参数选择中,主要是核函数的选择(选择核函数后,核函数会带有参数,该参数也要决定)和代价参数C(见支持向量机通俗导论),暂时就会一种方法,穷举法(也就是分别给核函数的参数和代价参数一组值,看看分类效果,决定选用那个)。
手写数字图像识别:其实就一个图像特征的提取(一种较简单的方法是将图像分成n*n的区域,统计每块区域中像素点所占的百分比),和SVM中参数的选择(上一篇文章)。不多说,上一波代码(Matlab)。运行有点久,因为参数选择很耗时间(相当于运行了100次),如果不需要参数选择,可以采用默认参数就好。每一次对应参数的分类准确率保存在R_train和R_test中。(使用的LibSVM工具箱,需下载,非MATLAB自带)
clc clear %载入数据。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 size_pic = 6; % 利用uigetfile函数交互式选取训练样本 [FileName,PathName,FilterIndex] = uigetfile( ... {'*.jpg';'*.bmp'},'请导入训练图片','*.png','MultiSelect','on'); if ~FilterIndex return; end num_train = length(FileName); TrainData = zeros(num_train,size_pic*size_pic); TrainLabel = zeros(num_train,1); for k = 1:num_train pic = imread([PathName,FileName{k}]); pic = pick_feature(pic);%提取图像特征 % 将标准化图像按列拉成一个向量并转置,生成6*6的训练样本矩阵 TrainData(k,:) = double(pic(:)'); % 样本标签为样本所对应的数字 TrainLabel(k) = str2double(FileName{k}(1)); end [FileName,PathName,FilterIndex] = uigetfile( ... {'*.jpg';'*.bmp'},'请导入测试图片','*.png','MultiSelect','on'); if ~FilterIndex return; end num_train = length(FileName); TestData = zeros(num_train,size_pic*size_pic); TestLabel = zeros(num_train,1); for k = 1:num_train pic = imread([PathName,FileName{k}]); pic = pick_feature(pic); TestData(k,:) = double(pic(:)'); TestLabel(k) = str2double(FileName{k}(1)); end %% %SVM识别。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 g = [2^0, 2^-1, 2^-2, 2^-3,2^-4,2^-5,2^-6,2^-7,2^-8,2^-9];%g参数 c = [2^7,2^6,2^5,2^4, 2^3 ,2^2, 2^1, 2^0,2^-1,2^-2];%C参数 R_train = zeros(10,10);%对应参数训练集的分类准确率 R_test = zeros(10,10);%对应参数测试集的分类准确率 for i=1:10 for j=1:10 cmd = ['-c ',num2str(c(i)),' -g ',num2str(g(j))];%模型参数 model = svmtrain(TrainLabel, TrainData, cmd); % 在训练集上查看识别能力 preTrainLabel = svmpredict(TrainLabel, TrainData, model);%样本集分类情况。。 preTestLabel = svmpredict(TestLabel, TestData, model);%测试集预测情况。。。。 size_train = size(preTrainLabel); size_test = size(preTestLabel); corretnum1 = 0; for m = 1:size_train(1); if preTrainLabel(m) == TrainLabel(m); corretnum1 = corretnum1 +1; end end R_train(i,j) = corretnum1/size_train(1); corretnum2 = 0; for n = 1:size_test(1) if preTestLabel(n) == TestLabel(n); corretnum2 = corretnum2 +1; end end R_test(i,j)=corretnum2/size_test(1); end end function [ A ] = pick_feature( pic ) %UNTITLED Summary of this function goes here % Detailed explanation goes here %pic = 255-pic; % 设定阈值,将反色图像转成二值图像 pic = im2bw(pic,0.4); % 查找数字上所有像素点的行标y和列标x [y,x] = find(pic == 1); % 截取包含完整数字的最小区域 pic_preprocess = pic(min(y):max(y), min(x):max(x)); [m, n] = size(pic_preprocess); b = 6;%将图像等分为10*10的区域; i = floor(m/b);%行列的等分大小 j = floor(n/b); s = i*j; A = zeros(b);%存取每个区域的特征(特征=像素/面积) T = 0.1;%阀值 for k=1:b for h=1:b arry_b = pic_preprocess(1+(k-1)*i:k*i,1+(h-1)*j:h*j); % if sum(sum(arry_b))/s > T A(k,h) = sum(sum(arry_b))/s; % end end end end