SVM matlab 代碼詳解說明


x=[0 1 0 1 2 -1];y=[0 0 1 1 2 -1];z=[-1 1 1 -1 1 1];
%其中,(x,y)代表二維的數據點,z 表示相應點的類型屬性。

data=[1,0;0,1;2,2;-1,-1;0,0;1,1];% (x,y)構成的數據點
groups=[1;1;1;1;-1;-1];%各個數據點的標簽
figure;
subplot(2,2,1);
Struct1 = svmtrain(data,groups,'Kernel_Function','quadratic', 'showplot',true);%data數據,標簽,核函數,訓練
classes1=svmclassify(Struct1,data,'showplot',true);%data數據分類,並顯示圖形
title('二次核函數');
CorrectRate1=sum(groups==classes1)/6  
subplot(2,2,2);
Struct2 = svmtrain(data,groups,'Kernel_Function','rbf', 'RBF_Sigma',0.41,'showplot',true);
classes2=svmclassify(Struct2,data,'showplot',true);
title('高斯徑向基核函數(核寬0.41)');
CorrectRate2=sum(groups==classes2)/6
subplot(2,2,3);
Struct3 = svmtrain(data,groups,'Kernel_Function','polynomial', 'showplot',true);
classes3=svmclassify(Struct3,data,'showplot',true);
title('多項式核函數');
CorrectRate3=sum(groups==classes3)/6
subplot(2,2,4);
Struct4 = svmtrain(data,groups,'Kernel_Function','mlp', 'showplot',true);
classes4=svmclassify(Struct4,data,'showplot',true);
title('多層感知機核函數');
CorrectRate4=sum(groups==classes4)/6

  




svmtrain代碼分析:
if plotflag   %畫出訓練數據的點
[hAxis,hLines] = svmplotdata(training,groupIndex);
legend(hLines,cellstr(groupString));
end

scaleData = [];
if autoScale   %訓練數據標准化
scaleData.shift = - mean(training);
stdVals = std(training);
scaleData.scaleFactor = 1./stdVals;
% leave zero-variance data unscaled:
scaleData.scaleFactor(~isfinite(scaleData.scaleFactor)) = 1;

% shift and scale columns of data matrix:
for c = 1:size(training, 2)
training(:,c) = scaleData.scaleFactor(c) * ...
(training(:,c) + scaleData.shift(c));
end
end

  

if strcmpi(optimMethod, 'SMO')%選擇最優化算法
else % QP and LS both need the kernel matrix:
%求解出超平面的參數 (w,b):     wX+b

  

 

if plotflag  %畫出超平面在二維空間中的投影
    hSV = svmplotsvs(hAxis,hLines,groupString,svm_struct);
    svm_struct.FigureHandles = {hAxis,hLines,hSV};
end

  

svmplotsvs.m文件

hSV = plot(sv(:,1),sv(:,2),'ko');%從訓練數據中選出支持向量,加上圈標記出來

lims = axis(hAxis);%獲取子圖的坐標空間
[X,Y] = meshgrid(linspace(lims(1),lims(2)),linspace(lims(3),lims(4)));%根據x和y的范圍,切分成網格,默認100份
Xorig = X; Yorig = Y;

% need to scale the mesh    將這些隔點標准化
if ~isempty(scaleData)
    X = scaleData.scaleFactor(1) * (X + scaleData.shift(1));
    Y = scaleData.scaleFactor(2) * (Y + scaleData.shift(2));
end

[dummy, Z] = svmdecision([X(:),Y(:)],svm_struct); %計算這些隔點[標簽,離超平面的距離]
contour(Xorig,Yorig,reshape(Z,size(X)),[0 0],'k');%畫出等高線圖,這個距離投影到二維空間的等高線

  

svmdecision.m文件
function [out,f] = svmdecision(Xnew,svm_struct)
%SVMDECISION evaluates the SVM decision function

%   Copyright 2004-2006 The MathWorks, Inc.
%   $Revision: 1.1.12.4 $  $Date: 2006/06/16 20:07:18 $

sv = svm_struct.SupportVectors;
alphaHat = svm_struct.Alpha;
bias = svm_struct.Bias;
kfun = svm_struct.KernelFunction;
kfunargs = svm_struct.KernelFunctionArgs;

f = (feval(kfun,sv,Xnew,kfunargs{:})'*alphaHat(:)) + bias;%計算出距離
out = sign(f);%距離轉化成標簽
% points on the boundary are assigned to class 1
out(out==0) = 1;

  

function K = quadratic_kernel(u,v,varargin)%核函數計算
%QUADRATIC_KERNEL quadratic kernel for SVM functions

% Copyright 2004-2008 The MathWorks, Inc.

dotproduct = (u*v');
K = dotproduct.*(1 + dotproduct);

  

維度分析:假設輸入的訓練數據為m個,維度為d,記作X(m,d);顯然w為w(m,1);    wT*x+b

核函數計算:k(x,y)->上公式改寫成  wT*@(x)+b

假設支持的向量跟訓練數據保持一致,沒有篩選掉一個,則支撐的數據就是歸一化后的X,記作:Xst;

測試數據為T(n,d);

則核函數計算后為:(m,d)*(n,d)'=m*n;與權重和偏移中以后為: (1,m)*(m*n)=1*n;如果是訓練數據作核函數處理,則m*d變成為m*m

這n個測試點的距離。

將這些隔點和其對應的超平面距離,畫成等高線,得到現有圖形。

 

 

第二批測試數據:

clc;
clear;
close all;
%rng(1); % For reproducibility
r = sqrt(rand(100,1)); % Radius 0~1
t = 2*pi*rand(100,1); % Angle 0~2pi
data1 = [r.*cos(t), r.*sin(t)]; % Points

r2 = sqrt(3*rand(100,1)+1); % Radius 1~4
t2 = 2*pi*rand(100,1); % Angle 0~2pi
data2 = [r2.*cos(t2), r2.*sin(t2)]; % points

figure;
plot(data1(:,1),data1(:,2),'r.','MarkerSize',15)
hold on
plot(data2(:,1),data2(:,2),'b.','MarkerSize',15)
ezpolar(@(x)1);ezpolar(@(x)2);
axis equal
hold off

%Put the data in one matrix, and make a vector of classifications.
data3 = [data1;data2];%標簽 +1 -1
theclass = ones(200,1);
theclass(1:100) = -1;

  

 

 

% r^2(r的平方) KMatrix = exp(-gamma*r2);
function KMatrix = getKRBF(X, Y, gamma)%rbf核函數
r2 =  repmat( sum(X.^2,2), 1, size(Y,1) ) ...
    + repmat( sum(Y.^2,2), 1, size(X,1) )'- 2*X*Y' 
%K(x,y)     m*n
%sum(X.^2,2)   m*d  ->   m*1  ->   repmat ->  m*n
%              n*d  ->   n*1  ->   n*m    ->  m*n
%m*n

% XVec表示X向量。||XVec||表示向量長度。 r表示兩點距離。r^2表示r的平方。 
% k(XVec,YVec) = exp(-1/(2*sigma^2)*(r^2)) = exp(-gamma*r^2)	
% 公式-1 這里, gamma=1/(2*sigma^2)是參數, r=||XVec-YVec|| 實際上,可看作是計算2個點X與Y的相似性。

  

核函數理論:參考:http://www.cnblogs.com/jerrylead/archive/2011/03/18/1988406.html

考慮我們最初在“線性回歸”中提出的問題,特征是房子的面積x,這里的x是實數,結果y是房子的價格。假設我們從樣本點的分布中看到x和y符合3次曲線,那么我們希望使用x的三次多項式來逼近這些樣本點。那么首先需要將特征x擴展到三維clip_image002[6],然后尋找特征和結果之間的模型。我們將這種特征變換稱作特征映射(feature mapping)。映射函數稱作clip_image004[10],在這個例子中

clip_image006[6]

我們希望將得到的特征映射后的特征應用於SVM分類,而不是最初的特征。這樣,我們需要將前面clip_image008[4]公式中的內積從clip_image010[16],映射到clip_image012[42]

至於為什么需要映射后的特征而不是最初的特征來參與計算,上面提到的(為了更好地擬合)是其中一個原因,另外的一個重要原因是樣例可能存在線性不可分的情況,而將特征映射到高維空間后,往往就可分了。(在《數據挖掘導論》Pang-Ning Tan等人著的《支持向量機》那一章有個很好的例子說明)

將核函數形式化定義,如果原始特征內積是clip_image014[4],映射后為clip_image016[6],那么定義核函數(Kernel)為

clip_image018[8]

到這里,我們可以得出結論,如果要實現該節開頭的效果,只需先計算clip_image020[10],然后計算clip_image022[10]即可,然而這種計算方式是非常低效的。比如最初的特征是n維的,我們將其映射到clip_image024[6]維,然后再計算,這樣需要clip_image026[6]的時間。那么我們能不能想辦法減少計算時間呢?

先看一個例子,假設x和z都是n維的,

clip_image028[4] 

展開后,得

clip_image030[4]

這個時候發現我們可以只計算原始特征x和z內積的平方(時間復雜度是O(n)),就等價與計算映射后特征的內積。也就是說我們不需要花clip_image026[7]時間了。

現在看一下映射函數(n=3時),根據上面的公式,得到

clip_image031[4]

也就是說核函數clip_image033[4]只能在選擇這樣的clip_image004[11]作為映射函數時才能夠等價於映射后特征的內積。

再看一個核函數

clip_image034[4]

對應的映射函數(n=3時)是

clip_image035[4]輪換對稱

更一般地,核函數clip_image037[4]對應的映射后特征維度為clip_image039[4]。(求解方法參見http://zhidao.baidu.com/question/16706714.html)。

由於計算的是內積,我們可以想到IR中的余弦相似度,如果x和z向量夾角越小,那么核函數值越大,反之,越小。因此,核函數值是clip_image020[11]clip_image041[4]的相似度。

再看另外一個核函數

clip_image042[6]

這時,如果x和z很相近(clip_image044[6]),那么核函數值為1,如果x和z相差很大(clip_image046[6]),那么核函數值約等於0。由於這個函數類似於高斯分布,因此稱為高斯核函數,也叫做徑向基函數(Radial Basis Function 簡稱RBF)。它能夠把原始特征映射到無窮維。

既然高斯核函數能夠比較x和z的相似度,並映射到0到1,回想logistic回歸,sigmoid函數可以,因此還有sigmoid核函數等等。

下面有張圖說明在低維線性不可分時,映射到高維后就可分了,使用高斯核函數。

clip_image048[6]

來自Eric Xing的slides

注意,使用核函數后,怎么分類新來的樣本呢?線性的時候我們使用SVM學習出w和b,新來樣本x的話,我們使用clip_image050[8]來判斷,如果值大於等於1,那么是正類,小於等於是負類。在兩者之間,認為無法確定。如果使用了核函數后,clip_image050[9]就變成了clip_image052[6],是否先要找到clip_image054[8],然后再預測?答案肯定不是了,找clip_image054[9]很麻煩,回想我們之前說過的

clip_image055[4]

只需將clip_image057[4]替換成clip_image059[6],然后值的判斷同上。

核函數不僅僅用在SVM上,但凡在一個模型后算法中出現了clip_image090[4],我們都可以常使用clip_image073[12]去替換,這可能能夠很好地改善我們的算法。

 

 

參考:http://blog.csdn.net/shijing_0214/article/details/51000845

由之前對核函數的定義(見統計學習方法定義7.6): 
設χ是輸入空間(歐氏空間或離散集合),Η為特征空間(希爾伯特空間),如果存在一個從χ到Η的映射 

φ(x): χ→Η

使得對所有的x,z∈χ,函數Κ(x,z)=φ(x)∙φ(z), 
則稱Κ(x,z)為核函數,φ(x)為映射函數,φ(x)∙φ(z)為x,z映射到特征空間上的內積。 
由於映射函數十分復雜難以計算,在實際中,通常都是使用核函數來求解內積,計算復雜度並沒有增加,映射函數僅僅作為一種邏輯映射,表征着輸入空間到特征空間的映射關系。例如: 
設輸入空間χ:^3

X=(x_(1,) x_2,x_3) , z=(z_(1,) z_2,z_3),

映射函數φ(x)= < X,X > =這里寫圖片描述 
核函數Κ(x,z)=〖(<x,z>)〗^2 
那么,取兩個樣例x=(1,2,3),z=(4,5,6)分別通過映射函數和核函數計算內積過程如下: 
φ(x)=(1,2,3,2,4,6,3,6,9) 
φ(z)=(16,20,24,20,25,30,24,30,36) 
φ(x)∙φ(z)=16+40+72+40+100+180+72+180+324=1024 
而直接通過Κ(x,z)計算得[(4+10+18)]^2=1024 
兩者相比,核函數的計算量顯然要比映射函數小太多了。


免責聲明!

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



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