天天看點

SVM多分類問題 libsvm在matlab中的應用

對于支援向量機,其是一個二類分類器,但是對于多分類,SVM也可以實作。主要方法就是訓練多個二類分類器。

一、多分類方式

1、一對所有(One-Versus-All OVA)

給定m個類,需要訓練m個二類分類器。其中的分類器 i 是将 i 類資料設定為類1(正類),其它所有m-1個i類以外的類共同設定為類2(負類),這樣,針對每一個類都需要訓練一個二類分類器,最後,我們一共有 m 個分類器。對于一個需要分類的資料 x,将使用投票的方式來确定x的類别。比如分類器 i 對資料 x 進行預測,如果獲得的是正類結果,就說明用分類器 i 對 x 進行分類的結果是: x 屬于 i 類,那麼,類i獲得一票。如果獲得的是負類結果,那說明 x 屬于 i 類以外的其他類,那麼,除 i 以外的每個類都獲得一票。最後統計得票最多的類,将是x的類屬性。

2、所有對所有(All-Versus-All AVA)

給定m個類,對m個類中的每兩個類都訓練一個分類器,總共的二類分類器個數為 m(m-1)/2 .比如有三個類,1,2,3,那麼需要有三個分類器,分别是針對:1和2類,1和3類,2和3類。對于一個需要分類的資料x,它需要經過所有分類器的預測,也同樣使用投票的方式來決定x最終的類屬性。但是,此方法與”一對所有”方法相比,需要的分類器較多,并且因為在分類預測時,可能存在多個類票數相同的情況,進而使得資料x屬于多個類别,影響分類精度。

對于多分類在matlab中的實作來說,matlab自帶的svm分類函數隻能使用函數實作二分類,多分類問題不能直接解決,需要根據上面提到的多分類的方法,自己實作。雖然matlab自帶的函數不能直接解決多酚類問題,但是我們可以應用libsvm工具包。libsvm工具包采用第二種“多對多”的方法來直接實作多分類,可以解決的分類問題(包括C- SVC、n - SVC )、回歸問題(包括e - SVR、n - SVR )以及分布估計(one-class-SVM )等,并提供了線性、多項式、徑向基和S形函數四種常用的核函數供選擇。

二、用libsvm在matlab中實作多分類(訓練函數svmtrain+預測函數svmpredict)

對于libsvm中訓練模型的函數svmtrain來說,model = svmtrain(訓練資料類别, 訓練資料, ‘一系列參數’);其中參數的形式如‘-c 2 -g 0.02’在這當中,參數主要包括以下幾個方面:

(1) -s —— 其表示SVM的類型,包括上面提到的(預設值為0):

0 —— C-SVC

1—— v-SVC

2 —— 一類SVM

3 —— e -SVR

4 —— v-SVR

(2)-t—— 其表示核函數類型(預設值為2)

0 – 線性:u’v

1 – 多項式:(r*u’v + coef0)^degree

2 – RBF函數:exp(-gamma|u-v|^2)

3 –sigmoid:tanh(r*u’v + coef0)

(3)核函數參數設定

-d ——核函數中的degree設定(針對多項式核函數)(預設3)

-g ——核函數中的gamma函數設定(針對多項式/rbf/sigmoid 核函數)(預設1/ k,k為特征值個數)

-r ——核函數中的coef0設定(針對多項式/sigmoid核函數)((預設0)

-c ——設定C-SVC,e -SVR和v-SVR的參數(損失函數)(預設1)

-n——設定nu-SVC,一類SVM和nu- SVR的參數(預設0.5)

-p ——設定e -SVR 中損失函數p的值(預設0.1)

-m ——設定cache記憶體大小,以MB為機關(預設40)

-e ——設定允許的終止判據(預設0.001)

-h ——是否使用啟發式,0或1(預設1)

-b ——是否訓練一個SVC或者SVR模型,0或1(預設0)

-wi ——設定第i類的參數C為weight*C(C-SVC中的C)(預設1)

-v——n-fold互動檢驗模式,n為fold的個數,必須大于等于2(訓練中使用了-v參數進行交叉驗證時,傳回的不是一個模型,而是交叉驗證的分類的正确率或者回歸的均方根誤差)

使用函數svmtrain訓練分類模型後,會傳回一個結構體,其中包括資料:

(1) parameters(一個5*1的數組)

第一個元素:-s,SVM的類型(int預設為0)

第二個元素:-t,核函數類型(預設為2)

第三個元素:-d,核函數中的degree設定(針對多項式核函數)(預設3);

     第四個元素:-g,核函數中的r(gamma)函數設定(針對多項式/rbf/sigmoid核函數) (預設為類别數目的倒數);

第五個元素:-r 核函數中的coef0設定(針對多項式/sigmoid核函數)((預設0)

(2)-nr_class: 表示資料集中有多少個類(int)

(3)-totalSV: 表示支援向量的總數。(int)

(4)-rho: 決策函數wx+b中的常數偏置的相反數(-b)。

(5)-Label: 表示資料集中類别的标簽

(6)ProbA: 使用-b參數時用于機率估計的數值,否則為空。

ProbB: 使用-b參數時用于機率估計的數值,否則為空。

(7)-nSV: 表示每類樣本的支援向量的數目,和Label的類别标簽對應。

(8)-sv_coef: 表示每個支援向量在決策函數中的系數。

(9)-SVs: 表示所有的支援向量,如果特征是n維的,支援向量一共有m個,則為m x n的稀疏矩陣。

(10)nu: -n參數的顯示

(11)iter: 疊代次數

(12)obj: 表示SVM檔案轉換的二次規劃求解的最小值

svmpredict函數根據測試資料類屬性,測試資料,以及通過svmtrain函數獲得的模型來進行分類預測并計算分類精度,[predict_label, accuracy, dec_values]=svmpredict(測試資料類屬性,測試資料,分類模型),傳回值介紹如下:

(1)predicted_label:存儲着分類後樣本所對應的類屬性。

(2)accuracy:一個3 * 1的數組,依次為:分類的正确率、回歸的均方根誤差、回歸的平方相關系數。

(3)decision_values/prob_estimates:是一個表示機率的數組,對于一個m個資料,n個類的情況,如果指定“-b 1”參數(使用,則n x k的矩陣,每一行表示這個樣本分别屬于每一個類别的機率;如果沒有指定“-b 1”參數,則為n * n×(n-1)/2的矩陣,每一行表示n(n-1)/2個二分類SVM的預測結果。

三、 使用libsvm進行分類的步驟

(1) 對資料做歸一化(simple scaling)

對資料進行簡單的縮放處理(scaling),縮放的最主要優點是能夠避免大數值區間的屬性過分支配了小數值區間的屬性。另一個優點能避免計算過程中數值複雜度。(在試驗中發現,歸一化過程,分别對訓練資料和測試資料進行歸一化處理,比對訓練資料和測試資料整體進行歸一化處理獲得的分類精度要高)

(2) 應用 RBF kernel

(3) 選擇得到最優的c和g

c是懲罰因子,是一個在訓練模型前需要自己設定的一個數值,它表示我們對類中的離群資料的重視程度,c的數值越大,表明我們越重視,越不想丢掉這些離群的資料;g是核函數中的gamma函數設定(針對多項式/rbf/sigmoid 核函數)(預設1/ k,k為特征值個數) 。c和g的選擇對分類精度影響很大,在本文的試驗中,用函數SVMcgForClass選擇完成c和g的選擇。

(4) 用得到的最優c和g訓練分類模型

使用libsvm中的svmtrain函數來訓練多分類模型

(5)測試

使用libsvm中的svmpredict函數來測試分類精度

四、實驗

使用libsvm提供的資料進行多分類實驗,下載下傳的wine資料,是關于葡萄酒種類,下載下傳的資料包括

SVM多分類問題 libsvm在matlab中的應用

三部分,分别是類數3,178個酒資料的13個屬性清單,178個酒資料對應的類屬性清單。代碼如下:

function [ classfication ] = test( train,test )

load chapter12_wine.mat                       %下載下傳資料

train=[wine(:,:);wine(:,:);wine(:,:)]; %選取訓練資料
train_group=[wine_labels(:);wine_labels(:); wine_labels(:)];%選取訓練資料類别辨別
test=[wine(:,:);wine(:,:);wine(:,:)];%選取測試資料
test_group=[wine_labels(:);wine_labels(:); wine_labels(:)]; %選取測試資料類别辨別

%資料預處理,用matlab自帶的mapminmax将訓練集和測試集歸一化處理[,]之間
%訓練資料處理
[train,pstrain] = mapminmax(train');
% 将映射函數的範圍參數分别置為0和1
pstrain.ymin = 0;
pstrain.ymax = 1;
% 對訓練集進行[0,1]歸一化
[train,pstrain] = mapminmax(train,pstrain);
% 測試資料處理
[test,pstest] = mapminmax(test');
% 将映射函數的範圍參數分别置為和
pstest.ymin = ;
pstest.ymax = ;
% 對測試集進行[,]歸一化
[test,pstest] = mapminmax(test,pstest);
% 對訓練集和測試集進行轉置,以符合libsvm工具箱的資料格式要求
train = train';
test = test';

%尋找最優c和g
%粗略選擇:c&g 的變化範圍是 ^(-),^(-),...,^()
[bestacc,bestc,bestg] = SVMcgForClass(train_group,train,-,,-,);
%精細選擇:c 的變化範圍是 ^(-),^(-),...,^(), g 的變化範圍是 ^(-),^(-),...,^()
[bestacc,bestc,bestg] = SVMcgForClass(train_group,train,-,,-,,,,,);

%訓練模型
cmd = ['-c ',num2str(bestc),' -g ',num2str(bestg)];
model=svmtrain(train_group,train,cmd);
disp(cmd);

%測試分類
[predict_label, accuracy, dec_values]=svmpredict(test_group,test,model);

%列印測試分類結果
figure;
hold on;
plot(test_group,'o');
plot(predict_label,'r*');
legend('實際測試集分類','預測測試集分類');
title('測試集的實際分類和預測分類圖','FontSize',);
end


           

五、實驗結果

SVM多分類問題 libsvm在matlab中的應用
SVM多分類問題 libsvm在matlab中的應用

六、問題

疑惑(1)!!!!!!!!!!!!!!!!!!!!!!!!!!!!

上面的實驗是參照libsvm 中的示例寫的,最開始按照示例思路,但是在歸一化時,自己是将訓練資料和測試資料一起歸一化的, 獲得的精度隻有61%,後來改為示例中的分别對訓練資料和測試資料進行歸一化後,精度就到了現在的88%,但是不了解造成此差異的原因,希望知道原因的朋友多多指教(代碼如下(1)和(2))

1、訓練資料和測試資料分别歸一化到[0,1]代碼(獲得分類精度88%):

%訓練資料處理
[train,pstrain] = mapminmax(train');
% 将映射函數的範圍參數分别置為0和1
pstrain.ymin = 0;
pstrain.ymax = 1;
% 對訓練集進行[0,1]歸一化
[train,pstrain] = mapminmax(train,pstrain);

% 測試資料處理
[test,pstest] = mapminmax(test');
% 将映射函數的範圍參數分别置為0和1
pstest.ymin = 0;
pstest.ymax = 1;
% 對測試集進行[0,1]歸一化
[test,pstest] = mapminmax(test,pstest);
% 對訓練集和測試集進行轉置,以符合libsvm工具箱的資料格式要求
train = train';
test = test';
           

2、訓練資料和測試資料整體歸一化到[0,1]代碼(獲得分類精度61%):

[mtrain,ntrain]=size(train);
[mtest,ntest]=size(test);
dataset=[train;test];
[dataset_scale,ps]=mapminmax(dataset',0,1);
dataset_scale=dataset_scale';
train=dataset_scale(1:mtrain,:);
test=dataset_scale((mtrain+1):(mtrain+mtest),:);
           

疑惑(2)!!!!!!!!!!!!!!!!!!!!!!!!!!!!

再有就是,對于c和g這兩個數值有函數可以自動調優,但是在歸一化時,如下面我要是把對訓練資料和測試資料分别歸一化的範圍從[0,1]變成[0,4],獲得的分類精度就從88%提高到了96%,這種歸一化的範圍又該怎麼确定呢?

訓練資料和測試資料分别歸一化到[0,4]代碼(獲得分類精度96%):

%訓練資料處理
[train,pstrain] = mapminmax(train');
% 将映射函數的範圍參數分别置為0和4
pstrain.ymin = 0;
pstrain.ymax = 4;
% 對訓練集進行[0,4]歸一化
[train,pstrain] = mapminmax(train,pstrain);

% 測試資料處理
[test,pstest] = mapminmax(test');
% 将映射函數的範圍參數分别置為0和4
pstest.ymin = 0;
pstest.ymax = 4;
% 對測試集進行[0,4]歸一化
[test,pstest] = mapminmax(test,pstest);
% 對訓練集和測試集進行轉置,以符合libsvm工具箱的資料格式要求
train = train';
test = test';
           

繼續閱讀