SVM 手寫數字識別


初次是根據“支持向量機通俗導論(理解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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM