LibSVM for Python 使用

發表於2016-03-28

經歷手寫SVM的慘烈教訓(還是太年輕)之後,我決定使用工具箱/第三方庫

Python

libsvm的GitHub倉庫

LibSVM是開源的SVM實現,支援C, C++, Java,Python , R 和 Matlab 等, 這裡選擇使用Python版本。

安裝LibSVM

將LibSVM倉庫的所有內容放入Python的包目錄\Lib\site-packages或者工程目錄中。

在libsvm根目錄和python子目錄下中分別新建名為__init__.py的空檔案,這兩個空檔案將標識所在的目錄為python包可以直接匯入。

允許草民吐槽一下各種Blog裡切換根目錄的奇怪的解決方案:這個這個

因為經常使用svm,所以草民將libsvm包放入\Lib\site-packages目錄下。在Python互動環境或在任意指令碼中都可以使用import libsvm.python來使用libsvm的python介面。

使用LibSVM

LibSVM的使用非常簡單,只需呼叫有限的介面

示例1:

from libsvm.python.svmutil import *
from libsvm.python.svm import *
    
y, x = [1,-1], [{1:1, 2:1}, {1:-1,2:-1}]
prob  = svm_problem(y, x)
param = svm_parameter('-t 0 -c 4 -b 1')
model = svm_train(prob, param)
yt = [1]
xt = [{1:1, 2:1}]
p_label, p_acc, p_val = svm_predict(yt, xt, model)
print(p_label)

輸出結果:

optimization finished, #iter = 1
nu = 0.062500
obj = -0.250000, rho = 0.000000
nSV = 2, nBSV = 0
Total nSV = 2
test:
Model supports probability estimates, but disabled in predicton.
Accuracy = 100% (1/1) (classification)
[1.0]

SVM資料中下載train1.txt和test1.txt。

LibSVM可以在檔案中讀取訓練資料,這樣便於大規模資料的使用。

示例:

from libsvm.python.svmutil import *
from libsvm.python.svm import *

y, x = svm_read_problem('train1.txt')
yt, xt = svm_read_problem('test1.txt')
model = svm_train(y, x )
print('test:')
p_label, p_acc, p_val = svm_predict(yt[200:202], xt[200:202], model)
print(p_label)

可以看到輸出:

optimization finished, #iter = 5371
nu = 0.606150
obj = -1061.528918, rho = -0.495266
nSV = 3053, nBSV = 722
Total nSV = 3053
test:
Accuracy = 40.809% (907/2225) (classification)

LibSVM介面

訓練資料格式

libsvm的訓練資料格式如下:

<label> <index1>:<value1> <index2>:<value2> ...

示例:

1 1:2.927699e+01 2:1.072510e+02 3:1.149632e-01 4:1.077885e+02

主要型別

  • svm_problem

儲存定義SVM模型的訓練資料

  • svm_parameter

儲存訓練SVM模型所需的各種引數

  • svm_model

完成訓練的SVM模型

  • svm_node

模型中一個特徵的值,只包含一個整數索引和一個浮點值屬性。

主要介面:

-svm_problem(y, x)

由訓練資料y,x建立svm_problem物件

  • svm_train()

svm_train有3個過載:

model = svm_train(y, x [, 'training_options'])
model = svm_train(prob [, 'training_options'])
model = svm_train(prob, param)

用於訓練svm_model模型

  • `svm_parameter(cmd)

建立svm_parameter物件,引數為字串。

示例:

param = svm_parameter('-t 0 -c 4 -b 1')
  • svm_predict()

呼叫語法:

p_labs, p_acc, p_vals = svm_predict(y, x, model [,'predicting_options'])

引數:

y 測試資料的標籤

x 測試資料的輸入向量

model為訓練好的SVM模型。

返回值:

p_labs是儲存預測標籤的列表。

p_acc儲存了預測的精確度,均值和迴歸的平方相關係數。

p_vals在指定引數'-b 1'時將返回判定係數(判定的可靠程度)。

這個函式不僅是測試用的介面,也是應用狀態下進行分類的介面。比較奇葩的是需要輸入測試標籤y才能進行預測,因為y不影響預測結果可以用0向量代替。

  • svm_read_problem

讀取LibSVM格式的訓練資料:

y, x = svm_read_problem('data.txt')
  • svm_save_model

將訓練好的svm_model儲存到檔案中:

svm_save_model('model_file', model)

model_file的內容:

svm_type c_svc
kernel_type linear
nr_class 2
total_sv 2
rho 0
label 1 -1
probA 0.693147
probB 2.3919e-16
nr_sv 1 1
SV
0.25 1:1 2:1 
-0.25 1:-1 2:-1 
  • svm_load_model

讀取儲存在檔案中的svm_model:

 model = svm_load_model('model_file')

調整SVM引數

LibSVM在訓練和預測過程中需要一系列引數來調整控制。

svm_train的引數:

  • -s SVM的型別(svm_type)

    • 0 -- C-SVC(預設)

      使用懲罰因子(Cost)的處理噪聲的多分類器

    • 1 -- nu-SVC(多分類器)

      按照錯誤樣本比例處理噪聲的多分類器

    • 2 -- one-class SVM

      一類支援向量機,可參見"SVDD"的相關內容

    • 3 -- epsilon-SVR(迴歸)

      epsilon支援向量迴歸

    • 4 -- nu-SVR(迴歸)

  • -t 核函式型別(kernel_type)

    • 0 -- linear(線性核):

      u'*v

    • 1 -- polynomial(多項式核):

      (gamma*u'*v + coef0)^degree

    • 2 -- radial basis function(RBF,徑向基核/高斯核):

      exp(-gamma*|u-v|^2)

    • 3 -- sigmoid(S型核):

      tanh(gamma*u'*v + coef0)

    • 4 -- precomputed kernel(預計算核):

      核矩陣儲存在training_set_file

下面是調整SVM或核函式中引數的選項:

  • -d 調整核函式的degree引數,預設為3

  • -g 調整核函式的gamma引數,預設為1/num_features

  • -r 調整核函式的coef0引數,預設為0

  • -c 調整C-SVC, epsilon-SVR 和 nu-SVR中的Cost引數,預設為1

  • -n 調整nu-SVC, one-class SVM 和 nu-SVR中的錯誤率nu引數,預設為0.5

  • -p 調整epsilon-SVR的loss function中的epsilon引數,預設0.1

  • -m 調整內緩衝區大小,以MB為單位,預設100

  • -e 調整終止判據,預設0.001

  • -wi調整C-SVC中第i個特徵的Cost引數

調整演算法功能的選項:

  • -b 是否估算正確概率,取值0 - 1,預設為0

  • -h 是否使用收縮啟發式演算法(shrinking heuristics),取值0 - 1,預設為0

  • -v 交叉校驗

  • -q 靜默模式

Matlab

LibSVM的Matlab介面用法類似,Matlab豐富的標準工具箱提供了各種方便。

Statistic Tools工具箱提供了svmtrain和svmclassify函式進行SVM分類。

traindata = [0 1; -1 0; 2 2; 3 3; -2 -1;-4.5 -4; 2 -1; -1 -3];
group = [1 1 -1 -1 1 1 -1 -1]';
testdata = [5 2;3 1;-4 -3];
svm_struct = svmtrain(traindata,group);    
Group = svmclassify(svm_struct,testdata);

svmtrain接受traindata和group兩個引數,traindata以一行表示一個樣本,group是與traindata中樣本對應的分類結果,用1和-1表示。

svmtrain返回一個儲存了訓練好的svm所需的引數的結構體svm_struct。

svmclassify接受svm_struct和以一行表示一個樣本的testdata,並以1和-1列向量的形式返回分類結果。

相關文章