LibSVM庫的使用說明

轉載自:http://blog.csdn.net/ajianyingxiaoqinghan/article/details/73480476

本文摘自《libsvm》的GitHub中的README文檔

前言

LibSVM庫的函數和結構體都在頭文件 svm.h 中聲明,我們需要在 C/C++ 文件中添加語句 #include “svm.h” ,然後就可以將我們的程序鏈接到 svm.cpp 文件上。我們可以以 svm-train.c 和 svm-predict.c 作爲例程,瞭解它們是如何使用LibSVM庫函數的。我們定義了 LIBSVM_VERSION 並在 svm.h 中聲明瞭 extern int libsvm_version,所以我們可以檢查庫函數版本號。
在我們分類測試數據之前,我們需要使用訓練數據構建一個 SVM 模型(即 svm_model)。一個模型也可以被存儲到文件中,以便以後的運用。一旦一個 SVM 模型是可用的,你可以用它分類新數據。

LibSVM函數與結構體

svm_train

  • struct svm_model* svm_train(const struct svm_problem* prob, const struct svm_parameter* param);

該函數根據給定的訓練數據和參數,構建並返回了一個 SVM 模型。

svm_problem

svm_problem 結構體描述了問題:

struct svm_problem
{
    int l;
    double *y;
    struct svm_node **x;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上述結構體的說明如下:

  • l:訓練數據的數量;
  • y:包含目標數據的數組;
  • x:數組指針,每一個指針指向一個訓練向量,訓練向量是一個 svm_node 的數組;

例如,如果我們有下列的訓練數據:

LABEL    ATTR1    ATTR2    ATTR3    ATTR4    ATTR5
-----    -----    -----    -----    -----    -----
  1        0        0.1      0.2      0        0
  2        0        0.1      0.3     -1.2      0
  1        0.4      0        0        0        0
  2        0        0.1      0        1.4      0.5
  3       -0.1     -0.2      0.1      1.1      0.1

那麼此時 svm_problem 的組成就是:

    l = 5
    y -> 1 2 1 2 3
    x -> [ ] -> (2,0.1) (3,0.2) (-1,?)
         [ ] -> (2,0.1) (3,0.3) (4,-1.2) (-1,?)
         [ ] -> (1,0.4) (-1,?)
         [ ] -> (2,0.1) (4,1.4) (5,0.5) (-1,?)
         [ ] -> (1,-0.1) (2,-0.2) (3,0.1) (4,1.1) (5,0.1) (-1,?)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

svm_node

svm_node 結構體中存儲的是(index, value):

struct svm_node
{
    int index;
    double value;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

index = -1 表明了一個向量的結尾。
注:標籤號(index)的排列必須是升序排序。

svm_parameter

結構體 svm_parameter 描述了 SVM 模型的參數:

struct svm_parameter
{
    int svm_type;
    int kernel_type;
    int degree; /* for poly */
    double gamma;   /* for poly/rbf/sigmoid */
    double coef0;   /* for poly/sigmoid */

    /* these are for training only */
    double cache_size; /* in MB */
    double eps; /* stopping criteria */
    double C;   /* for C_SVC, EPSILON_SVR, and NU_SVR */
    int nr_weight;      /* for C_SVC */
    int *weight_label;  /* for C_SVC */
    double* weight;     /* for C_SVC */
    double nu;  /* for NU_SVC, ONE_CLASS, and NU_SVR */
    double p;   /* for EPSILON_SVR */
    int shrinking;  /* use the shrinking heuristics */
    int probability; /* do probability estimates */
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

參數說明如下:

  • svm_type:可以是C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR其中之一;
    • C_SVC:C-SVM 分類器;
    • NU_SVC:NU-SVM 分類器;
    • ONE_CLASS:one-class SVM;
    • EPSILON_SVR:epsilon-SVM 迴歸;
    • NU_SVR:nu-SVM 迴歸;
  • kernel_type:可以是 LINEAR, POLY, RBF, SIGMOID 其中之一;
    • LINEARu T v 
    • POLY(gammau T v+coef0) degree  
    • RBFexp(gamma×|uv| 2 ) 
    • SIGMOIDtanh(gamma×u T v+coef0) 
    • PRECOMPUTED:在訓練集文件中的存放核函數值;
  • cache_size:是核緩存的大小,單位是MBytes;
  • eps:停止標準(我們在 NU-SVC 中使用的標準是0.00001,在其他分類器中使用 0.001);
  • nu:用於 nu-SVM, nu-SVR, one-class-SVM 的參數;
  • p:epsilon-SVM 迴歸中損失函數的小量,損失函數對小量不敏感;
  • shrinking
    • shrinking = 1,則收縮是進行的;
    • shrinking = 0,則收縮無效;
  • probability
    • probability = 1,模型中包含概率信息;
    • probability = 0,模型中不包含概率信息;

其它的,nr_weight, weight_label 和 weight 用來爲某些類改變懲罰因子(如果一個類的 weight 值沒有改變,則被設置爲1).這將有助於訓練分類器使用不平衡輸入數據,或者有利於降低不對稱錯誤分類的代價。
nr_weight 是在 weight_label 數組和 weight 數組的元素個數。每一個 weight[i] 對應了一個 weight_label[i],意味着類 weight_label[i] 的懲罰,就是與 weight[i] 相乘的結果。
如果我們不想改變任何分類的懲罰因子,就把 nr_weight 設置爲0;。

注:
1. 因爲 svm_model 包含了 svm_problem 的指針,所以如果我們仍然需要使用由 svm_train() 函數生成的 svm_model ,我們不能釋放包含了 svm_problem 的內存空間。
2. 爲了避免錯誤參數,函數 svm_check_parameter() 應該在 svm_train() 函數之前調用。

svm_model

結構體 svm_model 存儲了從訓練過程中得到的模型。這裏並不推薦直接訪問該結構體中的值,編程者應該使用接口函數獲得其中的值。

struct svm_model
{
    struct svm_parameter param; /* parameter */
    int nr_class;       /* number of classes, = 2 in regression/one class svm */
    int l;          /* total #SV */
    struct svm_node **SV;       /* SVs (SV[l]) */
    double **sv_coef;   /* coefficients for SVs in decision functions (sv_coef[k-1][l]) */
    double *rho;        /* constants in decision functions (rho[k*(k-1)/2]) */
    double *probA;      /* pairwise probability information */
    double *probB;
    int *sv_indices;        /* sv_indices[0,...,nSV-1] are values in [1,...,num_traning_data] to indicate SVs in the training set */

    /* for classification only */
    int *label;     /* label of each class (label[k]) */
    int *nSV;       /* number of SVs for each class (nSV[k]) */
                    /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
    /* XXX */
    int free_sv;        /* 1 if svm_model is created by svm_load_model*/
                        /* 0 if svm_model is created by svm_train */
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

參數解釋如下:

  • param:描述了在該模型中使用的參數;
  • nr_class:分類數量。對於迴歸問題和 one-class SVM,其值爲2;
  • l:支持向量的個數;
  • SV, sv_coef:分別代表支持向量和其相應係數。

假設有 k 種分類。對於數據中的分類 j,相應的 sv_coef 包含了 (k - 1) y * alpha 個向量,alpha的向量是一系列二分類問題的解決方案:1 vs j, 2 vs j, …, j-1 vs j, j vs j+1, j vs j+2, …, j vs k。並且 y=1 對應前面 j-1 個向量,y=-1 代表後面剩餘的 k-j 個向量。
舉例說明,如果這裏有 4 個分類,那麼 sv_coef 和 SV 如下所示:

    +-+-+-+--------------------+
    |1|1|1|                    |
    |v|v|v|  SVs from class 1  |
    |2|3|4|                    |
    +-+-+-+--------------------+
    |1|2|2|                    |
    |v|v|v|  SVs from class 2  |
    |2|3|4|                    |
    +-+-+-+--------------------+
    |1|2|3|                    |
    |v|v|v|  SVs from class 3  |
    |3|3|4|                    |
    +-+-+-+--------------------+
    |1|2|3|                    |
    |v|v|v|  SVs from class 4  |
    |4|4|4|                    |
    +-+-+-+--------------------+

可以以函數 svm_train() 爲例,觀察其中如何將值分配給 sv_coef。

  • rho:偏差值 (-b);
  • probA, probB:在概率輸出中使用的參數。如果有 k 個類別,則會存在 k×(k-1)/2 個二值問題,以及 rho, probA, probB 值,它們按照二值問題的順序對齊:1 vs 2, 1 vs 3, …, 1 vs k, 2 vs 3, …, 2 vs k, …, k-1 vs k
  • sv_indices[0, …, nSV-1]:在 [1, …, num_training_data]中,標示訓練集裏面支持向量的值;
  • label:包含訓練數據的標籤;
  • nSV:每個類中的支持向量的數量;
  • free_sv:標誌位,用來決定 SV 的空間是否應該被函數 free_model_content(struct svm_model*) 和 free_and_destroy_model(struct svm_model**) 釋放。如果模型是由函數 svm_train() 生成的,那麼 SV 在 svm_problem 中指向的數據不應該被移除。例如,如果 svm_model 不是由 svm_train 函數生成,那麼free_sv值爲0;但是如果是由 svm_load_model 函數生成,則 free_sv 值爲1;

svm_predict

  • double svm_predict(const struct svm_model* model, const struct svm_node* x);

該函數以模型 model 爲基礎,對測試向量 x 進行分類或迴歸預測。

  • 對於分類模型,將會返回 x 的預測分類;
  • 對於迴歸模型,將會返回使用模型計算得到的 x 值;
  • 對於 one-class 模型,返回 +1 或 -1;

svm_cross_validation

  • void svm_cross_validation(const struct svm_problem* prob, const struct svm_parameter* param, int nr_fold, double* target);

該函數用來進行交叉驗證。數據被分離成 nr_fold 組,在給定的參數下,按照順序的每一組用由剩餘數據訓練得到的模型進行驗證。驗證過程中的預測標籤(所有概率情況)被存到目標數組中。
svm_prob 格式與 svm_train() 相同。

svm_get_svm_type

  • int svm_get_svm_type(const struct svm_model* model);

該函數返回模型的 svm_type。svm_type 可能存在的值在文件 svm.h 中已經定義。

svm_get_nr_class

  • int svm_get_nr_class(const svm_model* model);

對於分類模型,函數返回分類的數量;
對於迴歸模型或 one-class 模型,返回值爲 2 ;

svm_get_labels

  • void svm_get_labels(const svm_model* model, int* label);

對於分類模型,該函數將標籤名稱輸出到標籤數組。
對於迴歸模型和 one-class 模型,標籤不變。

svm_get_sv_indices

  • void svm_get_sv_indices(const struct svm_model* model, int* sv_indices);

該函數將支持向量的編號輸出到 sv_indices 數組。
sv_indices 的大小是支持向量的大小,該值可以通過調用 svm_get_nr_sv 函數得到。
每個 sv_indices[i] 的範圍都在 [1, …, num_training_data] 之中。

svm_get_nr_sv

  • int svm_get_nr_sv(const struct svm_model* model);

該函數返回所有支持向量的個數。

svm_get_svr_probability

  • double svm_get_svr_probability(const struct svm_model* model);

對於帶有概率信息的迴歸模型,該函數輸出一個大於 0 的 sigma 值。對於測試數據,我們認爲概率模型爲:目標值 = 預測值 + z。
其中,z 是拉普拉斯變換:exp(|z|/sigma)2×sigma  
如果模型不是 svr ,或者不包含需要的信息,返回 0 值。

svm_predict_values

  • double svm_predict_values(const svm_model* model, const svm_node* x, double* dec_values);

該函數通過一個模型 model 計算向量 x ,得到預測決策值,並返回其預測標籤(分類問題)或函數值(迴歸問題)。
對於 nr_class 個分類的分類模型,該函數在數組 dec_values 中給出 nr_class * (nr_class - 1) / 2 個決策值,其中 nr_class 的值可以通過函數 svm_get_nr_class 得到,其順序是:

label[0] vs. label[1],
...,
label[0] vs. label[nr_class-1],
..., 
label[nr_class-2] vs. label[nr_class-1]

標籤 label 可以由函數 svm_get_labels 得到。
該函數返回值是 x 的預測分類結果。注:當 nr_class = 1 時,該函數不會給出任何決策值。

對於迴歸問題,dec_values[0] 和返回值都是通過模型計算 x 得到的預測值。
對於 one-class 模型,dec_values[0] 是 x 的決策結果,返回值是 +1 或 -1。

svm_predict_probability

  • double svm_predict_probability(const struct svm_model* model, const struct svm_node* x, double* prob_estimates);

該函數對一個帶有概率信息的模型,對測試向量 x 進行分類或迴歸操作。
對於帶有概率信息的分類模型,該函數在數組 prob_estimates 中給出了 nr_class 種概率估計(nr_class 值可以從函數 svm_get_nr_class 得到)。結果將返回高概率的分類。
對於迴歸問題或 one-class 問題,數組 prob_estimates 不變,返回值與函數 svm_predict 相同。

svm_check_parameter

  • const char* svm_check_parameter(const struct svm_problem* prob, const struct svm_parameter* param);

該函數檢測參數是否在該問題的可行範圍之中。該函數應該在調用 svm_train() 和 svm_cross_validation() 之前調用。如果參數是可行的,則返回 NULL 值;否則返回一個錯誤信息。

svm_check_probability_model

  • int svm_check_probability_model(const struct svm_model* model);

該函數檢測模型是否包含概率估計的所需信息。如果是,將返回 +1;否則,返回 0。
該函數應該在調用 svm_get_svr_probability 和 svm_predict_probability 函數之前進行調用。

svm_save_model

  • int svm_save_model(const char* model_file_name, const struct svm_model* model);

該函數將模型存到一個文件中。
存儲成功,返回 0;存儲出現錯誤,返回 -1。

svm_load_model

  • struct svm_model* svm_load_model(const char* model_file_name);

該函數從一個文件中讀取模型,返回一個模型的指針。
如果模型不能被讀取,則返回一個空指針。

svm_free_model_content

  • void svm_free_model_content(struct svm_model* model_ptr);

該函數釋放被模型結構體佔用的內存空間。

svm_free_and_destroy_model

  • void svm_free_and_destroy_model(struct svm_model** model_ptr_ptr);

該函數用來釋放被模型佔用的內存空間,並銷燬模型結構體。
該函數與函數 svm_destroy_model 相同,但函數 svm_destroy_model 在版本 3.0 之後被棄用。

svm_destroy_param

  • void svm_destroy_param(struct svm_parameter* param);

該函數釋放被參數集合佔用的內存空間。

svm_set_print_string_function

  • void svm_set_print_string_function(void (* print_func)(const char *));

用戶可以指定一個函數的輸出格式。例如:

svm_set_print_string_function(NULL);
  • 1
  • 1

可以使用默認輸出到stdout。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章