Friday, May 17, 2013

使用 LIBSVM 的 One-Class SVM 來尋找離群值

由於目前研究需要辨識資料樣本的離群值,而最近正好在學習 SVM,就想用 LIBSVM 的 distribution estimation (one-class SVM) 功能來試試看。以下是測試 one-class 的說明與 Matlab 程式碼。

一開始先試做出一個資料集。這個資料集裡有兩種類別,分別是是 x 和 y。這兩種資料均是高斯分佈的隨機變數,各有 200 筆資料。這兩類別的前 100 筆資料都是平均值為 +2,變異數為 1 的高斯亂數。而後 100 筆資料為平均值是 -2,變異數為 1 的高斯亂數。
data_x = [ randn( 100, 1 ) + 2; randn( 100, 1 ) - 2 ] ;
data_y = [ randn( 100, 1 ) + 2; randn( 100, 1 ) - 2 ] ;
 將這些資料放在一起,並作完均等化(normailized)後就可以得到要訓練模型與測試的事例(instance)。
instance = [ data_x, data_y ] ;
[ norm_instance, min_val, max_val ] = normalize( instance ) ;
而這些事例對應到的標示(label)均為 1。
label = ones( 200, 1 ) ;
之後就可以用 LIBSVM 來建立分類模型。
svm_cmd = '-s 2 -t 2 -n 0.1 -g 12' ;
model = libsvmtrain64( label, norm_instance, svm_cmd ) ;
[ predicted, accuracy ] = libsvmpredict64( label, norm_instance, model ) ;
在這裡的參數 "-s 2" 表示要用 one-class SVM,"-t 2" 表示要用 RBF Kernal,而 "-n 0.1" 及 "-g 12" 則是建立模型所需的參數,可以依據實際需求來調整。譬如說,如果期望離群值的數量不超過全部資料數的 10%,就要找一組 ng 使得分類正確率超過 90%。尋找的方法可以用暴力法,全部都試過一次看看。在此先以 n=0.1 及 g=12 來試試看。實驗的結果如下:
optimization finished, #iter = 92
obj = 38.822651, rho = 4.093761
nSV = 25, nBSV = 16
Accuracy = 90% (180/200) (classification)
下圖的綠點是 SVM 判斷為正常的點 ,紅點為判斷異常的點,藍色的區域則是會判斷為異常的區域。


 就這樣囉~(LIBSVM 真的好用!)

No comments: