svm-train用來從樣本數據中訓練出用來判定的規則,其中的參數設置如下:
options: -s svm_type : set type of SVM (default 0) 0 -- C-SVC 1 -- nu-SVC 2 -- one-class SVM 3 -- epsilon-SVR 4 -- nu-SVR -t kernel_type : set type of kernel function (default 2) 0 -- linear: u'*v 1 -- polynomial: (gamma*u'*v + coef0)^degree 2 -- radial basis function: exp(-gamma*|u-v|^2) 3 -- sigmoid: tanh(gamma*u'*v + coef0) -d degree : set degree in kernel function (default 3) -g gamma : set gamma in kernel function (default 1/num_features) -r coef0 : set coef0 in kernel function (default 0) -c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1) -n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5) -p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1) -m cachesize : set cache memory size in MB (default 100) -e epsilon : set tolerance of termination criterion (default 0.001) -h shrinking: whether to use the shrinking heuristics, 0 or 1 (default 1) -b probability_estimates: whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0) -wi weight: set the parameter C of class i to weight*C, for C-SVC (default 1)
如果不知道各種參數之間的區別也不會玩的開心,首先來看-s參數的含義:
C-SVC對應的原問題是:

它的對偶問題如下:

對應的決策函數為:

nu-CVS對應的原問題是:

它的對偶問題為:

它的決策函數是:

one-class SVM原始問題是:

對偶問題為:

判定函數:

epsilon-SVR的原型為:

它的對偶問題為:

nu-SVR原問題如下:

對偶問題為:

使用軟件包中的heart_scale文件用來測試,使用下面命令用來測試:
svm-train -s 0 -t 2 ../heart_scale result_module
輸入文件的格式為:
+1 1:0.708333 2:1 3:1 4:-0.320755 5:-0.105023 6:-1 7:1 8:-0.419847 9:-1 10:-0.225806 12:1 13:-1
-1 1:0.583333 2:-1 3:0.333333 4:-0.603774 5:1 6:-1 7:1 8:0.358779 9:-1 10:-0.483871 12:-1 13:1
+1 1:0.166667 2:1 3:-0.333333 4:-0.433962 5:-0.383562 6:-1 7:-1 8:0.0687023 9:-1 10:-0.903226 11:-1 12:-1 13:1
-1 1:0.458333 2:1 3:1 4:-0.358491 5:-0.374429 6:-1 7:-1 8:-0.480916 9:1 10:-0.935484 12:-0.333333 13:1
……
在result中的輸出如下:
svm_type c_svc # SVM類型
kernel_type rbf # 核函數類型
gamma 0.0769231 # 核函數中的g
nr_class 2 # 分類時的類別數
total_sv 132 # 總共的支持向量個數
rho 0.424462 # 決策函數中的常量b
label 1 -1 # 類別標簽
nr_sv 64 68 # 各類別分別的支持向量的個數
SV # 支持向量的列表
1 1:0.166667 2:1 3:-0.333333 4:-0.433962 5:-0.383562 6:-1 7:-1 8:0.0687023 9:-1 10:-0.903226 11:-1 12:-1 13:1
0.5104832128985164 1:0.125 2:1 3:0.333333 4:-0.320755 5:-0.406393 6:1 7:1 8:0.0839695 9:1 10:-0.806452 12:-0.333333 13:0.5
……
其中的svm-toy就像一個玩具,比如。。。

從這個圖中可以看出上面大於2的類的划分還是基於兩個類的划分的,當然在下面的代碼中也可以很明顯地看到這一點。
而svm-predict則是用train出來的module來預測數據的,我們這里就用heart_scale建立的module來在heart_scale做檢驗,如下:
svm-predict.exe ../heart_scale ../result_module ../a
輸出為:
Accuracy = 86.6667% (234/270) (classification)
也就是說准確度達到了86.6667。那這個predict是怎么利用Module來預測的,雖然知道預測函數了,但是貌似看到代碼才算完,如下:
1 struct svm_model 2 { 3 struct svm_parameter param; /* parameter */ 4 int nr_class; /* number of classes, = 2 in regression/one class svm */ 5 int l; /* total #SV */ 6 struct svm_node **SV; /* SVs (SV[l]) */ 7 double **sv_coef; /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */ 8 double *rho; /* constants in decision functions (rho[k*(k-1)/2]) */ 9 double *probA; /* pariwise probability information */ 10 double *probB; 11 12 /* for classification only */ 13 14 int *label; /* label of each class (label[k]) */ 15 int *nSV /* number of SVs for each class (nSV[k]) */ 16 /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */ 17 /* XXX */ 18 int free_sv; /* 1 if svm_model is created by svm_load_model*/ 19 /* 0 if svm_model is created by svm_train */ 20 };
在具體的程序中大段的代碼都是在解析文件,核心的代碼如下(里面有注釋):
double svm_predict_values(const svm_model *model, const svm_node *x, double* dec_values) { int i; if(model->param.svm_type == ONE_CLASS || model->param.svm_type == EPSILON_SVR || model->param.svm_type == NU_SVR) { double *sv_coef = model->sv_coef[0]; double sum = 0; for(i=0;i<model->l;i++) sum += sv_coef[i] * Kernel::k_function(x,model->SV[i],model->param); sum -= model->rho[0]; *dec_values = sum; if(model->param.svm_type == ONE_CLASS) return (sum>0)?1:-1; else return sum; } else { int nr_class = model->nr_class; int l = model->l; double *kvalue = Malloc(double,l); // 依次計算Kernel for(i=0;i<l;i++) kvalue[i] = Kernel::k_function(x,model->SV[i],model->param); int *start = Malloc(int,nr_class); start[0] = 0; // 計算各個類的支持向量的開始的位置 for(i=1;i<nr_class;i++) start[i] = start[i-1]+model->nSV[i-1]; int *vote = Malloc(int,nr_class); for(i=0;i<nr_class;i++) vote[i] = 0; int p=0; for(i=0;i<nr_class;i++) for(int j=i+1;j<nr_class;j++) { double sum = 0; int si = start[i]; int sj = start[j]; int ci = model->nSV[i]; int cj = model->nSV[j]; int k; // 支持向量對應的參數 double *coef1 = model->sv_coef[j-1]; double *coef2 = model->sv_coef[i]; // 計算出各個類之間的差距 for(k=0;k<ci;k++) sum += coef1[si+k] * kvalue[si+k]; for(k=0;k<cj;k++) sum += coef2[sj+k] * kvalue[sj+k]; sum -= model->rho[p]; dec_values[p] = sum; // 如果大於0的話選i,否則選j if(dec_values[p] > 0) ++vote[i]; else ++vote[j]; p++; } int vote_max_idx = 0; // 從中選出最大的一個類型 for(i=1;i<nr_class;i++) if(vote[i] > vote[vote_max_idx]) vote_max_idx = i; free(kvalue); free(start); free(vote); // 返回地vote_max_idx對應的label return model->label[vote_max_idx]; } }
---------------------------------------------
歡迎拍磚。
