我一直覺得 SVM 是個很有趣的東西,不過一直沒辦法去聽林智仁老師 的 Data mining與SVM的課,後來看了一些Internet上的文件,後來聽 kcwu 講了一下 libsvm 的用法後,就想整理一下,算是對於並不需要知道完整 SVM 理論的人提供使用 libsvm 的入門。 原始 libsvm 的README跟FAQ也是很好的文件, 不過你可能要先對 svm 跟流程有點了解後才看得懂 (我在看時有這樣的感覺); 這篇入門就是為了從零開始的人而寫的。
不過請記得底下可能有些說法不一定對,但是對於只是想用 SVM 的人來說我覺得這樣說明會比較易懂。這篇入門原則上是給會寫基本程序的人看的,也是給我自己一個備忘, 不用太多數學底子,也不用對 SVM 有任何預備知識。
SVM:什麼是SVM,它能為我們做什麼?
SVM, Support Vector Machine , 簡而言之它是個起源與人工神經網絡有點像的東西,現今最常拿來就是做分類。也就是說,如果我有一堆已經分好類的東西(可是分類的依據是未知的),那當收到新的東西時,SVM可以預測新的數據要分到哪一堆去。聽起來是很神奇的事(如果你覺得不神奇,請重想一想這句話代表什麼:分類的依據是未知的!,還是不神奇的話就請你寫個程序,解解上面的問題),不過 SVM 基於統計學習理論的,可以在合理的時間內漂亮的解決這個問題。
以圖形化的例子來說明,假定我在空間中標了一堆用顏色分類的點, 點的顏色就是它的類別, 位置就是它的數據, 那 SVM 就可以找出區隔這些點的程序, 依此就可以分出一個個的區域; 拿到新的點(數據) 時, 只要對照該位置在哪一區就可以找出它應該是哪一顏色(類別)了。當然 SVM 不是真的只有分區那麼簡單, 不過看上面的例子應該可以了解 SVM 大概在作什麼. 要對 SVM 再多懂一點點,可以參考 cjlin 在 data mining 課的 slides: pdf 或 ps 。我們可以把 SVM 當個黑盒子, 數據丟進去讓他處理然後我們再來用就好了.
哪裡得到SVM?
libsvm 當然是最完美的工具.下載處: libsvm.zip 或者 libsvm.tar.gz
.zip 跟 .tar.gz 基本上是一樣的, 只是看你的操作系統; 習慣上 Windows 用 .zip 比較方便 (因為有WinZIP, 也有WinRAR), UNIX 則是用 .tar.gz
編譯libsvm
解開來後, 假定是UNIX 系統, 直接打 make 就可以了; 編不出來的話請詳讀說明和運用常識. 因為這是指南, 所以我不花時間細談, 而且編不出來的情形真是少之又少, 通常一定是你的系統有問題。 其他的子目錄可以不管, 只要 svm-train, svm-scale, svm-predict 三個執行文件有就可以了. Windows 的用戶要自己重編當然也是可以, 不過已經有編好的執行文件在裡面了: 請檢查 windows 子目錄, 應該會有 svmtrain.exe, svmscale.exe, svmpredict.exe, svmtoy.exe.
libSVM的使用
libsvm 有很多種用法, 這篇指南只打算講簡單的部分.
程序
svmtrain
訓練數據. 跑SVM被戲稱為 “開火車” 也是由於這個程序名而來. train會接受特定格式的輸入, 產生一個 “Model” 文件. 這個 model 你可以想像成SVM的內部數據,因為預測要model才能預測, 不能直接吃原始數據.想想也很合理,假定 train 本身是很耗時的動作, 而 train可以以某種形式存起內部數據,那下次要預測時直接把那些內部數據載入就快多了.
svmpredict
依照已經訓練好的 model, 再加上給定的輸入(新值), 輸出預測新值所對應的類別.
svmscale
掃描數據. 因為原始數據可能范圍過大或過小, svmscale 可以先將數據重新 scale (縮放) 到適當范圍使訓練與預測速度更快。
文件格式
文件格式要先交代一下. 你可以參考 libsvm 裡面附的 “heart_scale”: 這是SVM 的輸入文件格式.
[label] [index1]:[value1] [index2]:[value2] …
[label] [index1]:[value1] [index2]:[value2] …
一行一條記錄數據,如:
+1 1:0.708 2:1 3:1 4:-0.320 5:-0.105 6:-1
label
或說是class, 就是你要分類的種類,通常是一些整數。
index
是有順序的索引,通常是連續的整數。
value
就是用來 train 的數據,通常是一堆實數。
每一行都是如上的結構, 意思就是: 我有一排數據, 分別是 value1, value2, …. value, (而且它們的順序已由 index 分別指定),這排數據的分類結果就是label。
或許你會不太懂,為什麼會是 value1,value2,…. 這樣一排呢? 這牽涉到 SVM 的原理。 你可以這樣想(我沒說這是正確的), 它的名字就叫 Support “Vector” Machine, 所以輸入的訓練數據是 “Vector”(向量), 也就是一排的 x1, x2, x3, … 這些值就是 value,而 x[n] 的n就是由index 指定。 這些東西又稱為 “(屬性)attribute”。
真實的情況是,大部份時候我們給定的數據可能有很多 “特征(feature)” 或說 “屬性(attribute)”,所以輸入會是一組的。 舉例來說,以前面點分區的例子 來說,我們不是每個點都有 X 跟 Y 的坐標嗎? 所以它就有兩種屬性。 假定我有兩個點: (0,3) 跟 (5,8) 分別在 label(class) 1 跟 2 ,那就會寫成
1 1:0 2:3
2 1:5 2:8
同理,空間中的三維坐標就等於有三組屬性。這種文件格式最大的好處就是可以使用稀疏矩陣(sparse matrix), 或說有些 數據的屬性可以有缺失。
運行libsvm
下來解釋一下libsvm 的程序怎麼用。 你可以先拿 libsvm 附的heart_scale 來做輸入,底下也以它為例:
看到這裡你應該也了解,使用 SVM 的流程大概就是:
1.准備數據並做成指定格式 (有必要時需 svmscale)
2.用svmtrain 來訓練成 model
對新的輸入,使用 svmpredic來預測新數據的類別.
svmtrain
svmtrain 的語法大致就是:
svmtrain [options] training_set_file [model_file]
training_set_file 就是之前的格式,而 model_file 如果不給就會 叫 [training_set_file].model。 options 可以先不要給。
下列程序執行結果會產生 heart_scale.model 文件:(螢幕輸出不是很重要,沒有錯誤就好了)
./svmtrain heart_scale
optimization finished, #iter = 219
nu = 0.431030
obj = -100.877286, rho = 0.424632
nSV = 132, nBSV = 107
Total nSV = 132
svmpredict
svmpredict 的語法是 :
svmpredict test_file model_file output_file