9. 標準的分類問題: 這是哪種鳶尾花 契子 回顧近半年來資料分析的工作內容,主要都是在處理一類分類,趁著工作到一段落,把這半年以來的經驗做個紀錄以供未來回顧,同時提供一些過來人的經驗,希望能幫到有緣的讀者。另外,由於簽了保密協議,無法使用真實資料做示範,故會以鳶尾花資料為例來說明R語言中如何進行一類分類。
本文的架構如下,於第二節簡述何為一類分類,第三節提供4種常見的一類分類演算法在R語言中如何實現並簡述其概念,第四節介紹一類分類演算法的評估指標,第五節回顧整個學習過程中掉過的坑或遇到很好的資源或對我而言重要的個人成長,當雜記看吧,希望能博君一笑XD
什麼是一類分類? 說來蠻奇妙的,第一次看到 “一類分類” 這個詞是在學生時代閱讀台大林智仁教授的LIBSVM工具包 ,其中提到該包支援一類支援向量機(one-class SVM),當下我是一頭霧水,一類有什麼好分類的,殊不知未來工作就是要與之奮鬥@@
二類分類 所以話說回來,什麼是一類分類呢?它憑什麼有一個自己的專屬名稱呢?相較於令人困惑的一類分類,吾人將先說明二類分類是什麼再回頭解釋一類分類是什麼。一個常見的二分類例子為判斷性別,如給機器一張人頭像照片,看其否能辨別是男是女。讓機器去學習如何判別男女會經過如下步驟首先,提供大量的標準答案來讓機器去“學習”隱藏在照片後的規則,接著利用獨立的資料對機器進行考試(不提供答案)以判斷其學習成效。最後,如果學習成效良好,機器學習到的規則就可以拿可以拿來做進一步的應用,如預測新資料。這一個完整的過程,有兩個條件需要被滿足,一為大量的資料,二為要有標準答案。需要大量資料的原因為樣本數大的結果比較可信,以推估全校的平均身高而言,當全校師生為2000人時,你願意採用隨機抽出20人的平均身高或是200人的平均身高?毫無疑問的,隨機抽取的人數當然是越多越好。至於需要標準答案的原因則是指每個樣本都需要能被正確分類的(機器學習中稱此為貼上標籤),由於知道正確的結果,所以機器學習方向錯誤時,就可以被導正。
一類分類 在知道二類分類與其需要被滿足的兩個條件後,讓我們來看機器會怎麼面對這個問題—判斷一個人是否生病。套用上述的邏輯,首先第一步是蒐集樣本,徵求健康的人與患者,接著就會卡住了,健康的人還好說,生病的人非常難以尋找,尤其是患有罕見疾病(發生率小於千分之一)的人。所以在某些二類分類情況中,因某類的資料獲取非常困難所導致樣本數不足的問題,會造成機器學習的效果相當不好。其次,假設歷經千辛萬苦我們蒐集到了病人的資料,這時只要對資料做完標籤後,就可以讓機器放開手腳了,但是怎麼貼標籤呢,窮舉出所有病的情況一個一個貼標籤是不切實際的,所以用二類分類的方式是不可行的。為了處理這樣的問題,於是有了一類分類。在判斷一個人是否生病時,一類分類的概念為只專注於學習健康的人特徵,當遇到不具備健康特徵的人時,就判斷其不健康,這樣的好處在於避免掉了收集資料的困難以及無法定義特定對象的問題,而實務中的某些情況,的確也適用於這樣的例子:例如金融界的詐欺偵測,因為詐欺者的資料難以收集也不容易去定義全部詐欺的行為,所以針對詐欺者專門寫一套辨識方式相當不可行。
四種一類分類演算法 機器學習的過程主要為挑選特徵搭配演算法來達到研究目的,亦有人稱這個過程為建模。本節將會透過鳶尾花資料介紹4種一類分類演算法,分別是一類支援向量機(One class support vector machine)、高斯混合模型(Gaussian mixture model)、自編碼器(Autoencoder)、孤立森林(Isolation forest)。
鳶尾花資料集 鳶尾花資料[1 ] 在R中可以直接被呼叫。如下所示,該資料收集了三種鳶尾花品種的花萼及花瓣之長度與寬度,共有4個特徵,每個品種的樣本數為50。挑鳶尾花資料集的原因為這是一個赫赫有名的分類例子,這筆資料從1936開始就被廣泛研究,文獻的方法比較中常看到該資料集被拿來測試,所以可以去除機器學習中最繁重的清資料與特徵工程的部分,讓焦點更注重於演算法本身。
## 'data.frame': 150 obs. of 5 variables: ## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... ## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... ## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... ## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... ## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
## ## setosa versicolor virginica ## 50 50 50
探索性資料分析 要進行建模的階段時,個人習慣先看一下資料的樣貌,也就是探索性資料分析(Exploratory Data analysis),沒問題再進入下一步。。在R中一個簡易的方式為利用指令 ‘describe’ 看一下基本的敘述統計量,如對資料沒有疑慮後,再進行建模。為了因應一類分類的需要,將三個品種的標籤改為屬於山鳶尾(setosa)與不屬於山鳶尾(Non-setosa)。
Sepal.Length 1 150 5.843333 0.8280661 5.80 5.808333 1.03782 4.3 7.9 3.6 0.3086407 -0.6058125 0.0676113 Sepal.Width 2 150 3.057333 0.4358663 3.00 3.043333 0.44478 2.0 4.4 2.4 0.3126147 0.1387047 0.0355883 Petal.Length 3 150 3.758000 1.7652982 4.35 3.760000 1.85325 1.0 6.9 5.9 -0.2694109 -1.4168574 0.1441360 Petal.Width 4 150 1.199333 0.7622377 1.30 1.184167 1.03782 0.1 2.5 2.4 -0.1009166 -1.3581792 0.0622364 Species* 5 150 2.000000 0.8192319 2.00 2.000000 1.48260 1.0 3.0 2.0 0.0000000 -1.5199333 0.0668900
至於選入模型的特徵,則是參照前人的研究,使用花瓣的長度與寬度。如下圖所示,以花瓣為特徵時,山鳶尾與另外兩個品種能很好的被區分開來。
plot (raw.data[,c (3 ,4 )],col= c ("blue" ,"red" )[setosa_binary],pch= c (15 ,17 )[setosa_binary]);grid ();legend ("bottomright" ,legend= c ("Non-setosa (N=100)" ,"Setosa (N=50)" ),pch= c (15 ,17 ),col= c ("blue" ,"red" ))
最後將山鳶尾的資料分成訓練集資料與測試集資料,兩者的比例為8:2。另外,非山鳶尾的資料也通通作為測試集。
一類支援向量機(One class support vector machine) 一類支援向量機的概念為透過對一類樣本去建立一個決策邊界,該邊界可以想像為空間中的一個超球體,該球體的半徑盡可能極小,但是包含了全部的某一類樣本,所以當一筆資料無法進入該球體時則被判斷為異常。執行的程式如下:
library ("e1071" ) svm.tuned.model<-tune.svm (~ .,data= train.data, , nu = seq (2 ^ (- 7 ),2 ^ (- 4 ),length= 10 ) , gamma = seq (2 ^ (- 8 ),2 ^ (- 3 ),length= 10 ) ) #plot(svm.tuned.model) svm.model<-svm.tuned.model$ best.model pred1 <- predict (svm.model, train.data,decision.value= T) pred2 <- predict (svm.model, test.data,decision.value= T) svm.result<-factor (pred2,c (F,T),c ("Non-setosa" ,"Setosa" )) svm.confusion.matrix<-table (svm.result,setosa_binary[test_index]) svm.confusion.matrix
## ## svm.result Non-setosa Setosa ## Non-setosa 100 2 ## Setosa 0 8
高斯混合模型 (Gaussian mixture model) 高斯混合模型為針對某一類樣本去進行配適,當估計完成,得到對應的密度函數參數後,即可用來評估新資料是否與這群樣本來自於同樣的分類。如果可能性很高,則判斷為同類 ; 如果可能性很低,則判斷為異類。可能性的高低會由一個臨界值來判斷,臨界值的判斷很吃經驗,根據Tax的論文[2 ] ,它給出一個參考的方式,訓練集資料的前5%。執行的程式如下:
## Package 'mclust' version 5.4.5 ## Type 'citation("mclust")' for citing this R package in publications.
## ## Attaching package: 'mclust'
## The following object is masked from 'package:psych': ## ## sim
## ## GMM.result Non-setosa Setosa ## Non-setosa 100 2 ## Setosa 0 8
自編碼器(Autoencoder) 自編碼器為對資料做壓縮再做還原的一個過程,這項工具原本是作為萃取資料特徵(降維)用的,如果資料能被壓縮後又成功還原就代表著資料的壓縮方式是正確且有效的。但是在一類分類中它卻有了不同的應用,如果單一類別的資料能被成功壓縮又還原,那另一類型的資料進來會發生什麼事呢?答案就是其沒有辦法被正確的還原,因為機器學習到的壓縮資料並不適用於不同類的資料,尤其是在資料長得非常不一樣的時候,所以可以根據還原的程度去判斷一筆資料是否為異常值。執行的程式如下:
## Warning: small validation set, only 4 observations
## ## AE.result Non-setosa Setosa ## Non-setosa 100 0 ## Setosa 0 10
孤立森林 (Isolation Forest) 孤立森林(Isolation Forest,iForest)是劉飛博士在莫納什大學就讀期間在陳開明教授和周志華教授的指導下於 2008 年發表的。其主要思想為對資料建立很多棵分類樹將資料中的樣本點分開,由於異常點在資料中占的比例比較少,且在一些特徵上與正常點有差異,所以在分類時,異常點更容易被區分開。而正常樣本由於佔較大的比例且彼此之間特徵差異很小故很難區分開。基於異常值少而且不一樣這樣的特性,iForest透過衡量分類時各樣本是否容易被區分開的程度來尋找異常值。所以圖形上來看,異常值容易被區分開所以會接近分類樹的根部;而正常值因不容易區分,所以會遠離分類樹的根部。基於這樣的特性,可用分類樣本所需的路徑長度(距離分類樹根部的遠近)來衡量資料是否容易被區分開。當路徑越長說明該資料越難以分開,原文中有將路徑的長度轉換成異常分數 (s),並建議了如下的評估: 當異常分數很接近 1時,可以斷定其為異常值;當異常分數遠遠小於0.5時,推論其為正常值是相當安全的;當所有的資料的異常分數都約莫等於 0.5時,則資料中沒有明顯的異常值。執行的程式如下:
## Warning in .h2o.startModelJob(algo, params, h2oRestApiVersion): Stopping tolerance is ignored for _stopping_rounds=0..
## ## iForest.result Non-setosa Setosa ## Non-setosa 100 1 ## Setosa 0 9
一類分類的評估
精準度悖論 在進行完分類後,各演算法在測試集的結果可透過混淆矩陣表示。如
檢測結果為陰性 真陰(True Negative, TN) 偽陰(False Negative, FN) 檢測結果為陽性 偽陽(False Positive, FP) 真陽(True Positive, TP)
一般而言,吾人會希望混淆矩陣中分類正確的結果(TP與TN)越高越好,一個常見的指標為準確度(Accuracy),其透過計算正確分類資料佔全部資料的比重來衡量分類結果。
A c c u r a c y = T P + T N T P + F P + T N + F N A c c u r a c y = T P + T N T P + F P + T N + F N
然準確度這個指標在兩類資料極度不平衡的情況下,會是一個不好的度量方式。假設吾人收集了10000個樣本,其中有兩名罕病患者,如吾人預測全部的樣本均為陰性,此時的準確度為
A c c u r a c y = T N + T P T P + F P + T N + F N = 9998 + 0 0 + 0 + 9998 + 2 = 99.98 % A c c u r a c y = T N + T P T P + F P + T N + F N = 9998 + 0 0 + 0 + 9998 + 2 = 99.98 %
但是患者實際上有罕病且被正確判斷出來的比率為0。這種準確度很高但是模型實際的判斷能力很差的現象稱為準確度悖論(Accuracy paradox )。因為有準確度悖論這項議題的存在,所以單看精準度是不夠的,這裡吾人另外考慮以F1分數(F 1 − s c o r e F 1 − s c o r e )與特異度(Specificity)來做衡量。將先說明F1分數後再說明特異度。F1分數為準確率(Precision)與召回率(Recall)的調和平均數。
F 1 − s c o r e = 2 × R e c a l l × P r e c i s i o n R e c a l l + P r e c i s i o n F 1 − s c o r e = 2 × R e c a l l × P r e c i s i o n R e c a l l + P r e c i s i o n
P r e c i s i o n = T P F P + T P P r e c i s i o n = T P F P + T P
R e c a l l = T P T P + F N R e c a l l = T P T P + F N
精確度代表在所有被判斷為陽性的個體中,確實為陽性之比率,亦有人稱該值為陽性預測值(Positive Predictive Value,PPV);召回率代表在所有實際為陽性的個體中,被正確判斷為陽性之比率。在上述預測全部的樣本均為陰性極端的例子裡,精確度與召回率的分子TP均為0。代表兩指標均可反映出預測全部資料為陰性是一個不適當的方式。至於F1分數則可以讓吾人很好的去同時衡量精確度與召回率,例如A與B兩模型出來的結果中A模型準確率結果較優而B模型則是召回率較好,此時可以根據F1分數較高者來決定較佳的模型。說明完F1分數後,接著說明特異度。其計算方式為
S p e c i f i c i t y = T N F P + T N S p e c i f i c i t y = T N F P + T N
特異度的涵義為所有實際為陰性的個體中,被正確判斷為陰性之比率。觀察準確率、召回率與特異度的分子後,可以發現特異度所要衡量的事情與前兩者指標不同,前兩者關心的事情為正確判斷為陽性的個數(TP),而特異度則是關心正確被判斷為陰性的個數(TN)。所以最後的結果評估時,吾人不會只看單一指標,而是會同時考量多個指標。
鳶尾花資料在各分類演算法下結果比較 最後從下表的結果比較中可以看出4種演算法的結果在各指標的數值都至少有8成,而自編碼器的結果甚至達到百分之百正確,但這並不意味著自編碼器是最好的模型,個人實務上的經驗是特徵搭配演算法才會有最好的結果。#library("caret")
output<-rbind (confusionMatrix (svm.confusion.matrix)$ byClass, confusionMatrix (GMM.confusion.matrix)$ byClass, confusionMatrix (AE.confusion.matrix)$ byClass, confusionMatrix (iForest.confusion.matrix)$ byClass) finaloutput<-output[,c (1 ,2 ,5 ,6 ,7 )] rownames (finaloutput)<-c ("一類支援向量機(One class support vector machine)"," 高斯混合模型 (Gaussian mixture model)"," 自編碼器(Autoencoder)","孤立森林 (Isolation Forest)" )
一類支援向量機(One class support vector machine) 1 0.8 0.9803922 1 0.9900990 高斯混合模型 (Gaussian mixture model) 1 0.8 0.9803922 1 0.9900990 自編碼器(Autoencoder) 1 1.0 1.0000000 1 1.0000000 孤立森林 (Isolation Forest) 1 0.9 0.9900990 1 0.9950249
文獻整理與後記: 這裡紀錄這半年來記憶深刻的文獻,至於一些零碎的感想或是摔過的坑則放在後記。
文獻整理 4種演算法的參考文獻:關於高斯混合模型:如果直接在網路上打異常檢測,有現成的影片可以看,如Couresa創辦人Andrew Ng的影片 或台大電機系李宏毅的影片 。我最有收穫的點則分別是Andrew會提到實務上的經驗,例如資料量又多少才會夠,而李老師則是開頭關於貼標籤的部分講得很清楚,金融界的異常資料並不是很好貼標,所以分析方式跟可以直接貼標的分析面向就會不太相同。但是我自己是最喜歡看Tax的論文[2 ] ,這篇建議了臨界值怎麼選,而且也系統性的看了其他一類演算法的方式,將一類演算法分成三個面向density, boundary, reconstruct。 關於一類支援向量機:R套件為e1071為改寫LIBSVM的程式碼,所以如果要看背後原理要看林智仁老師的文章[4 ] ,從相關文獻[5 ] 中可以看出林老師他們實驗室應該有跟Schölkopf合作,ν ν -support 是蠻重要的點,會直接影響到參數設定。 關於自編碼器,Hinton這篇[6 ] 並沒有直接提到可用於異常檢測,但是強烈建議看一下,文章非常短,不到4頁,其提到了自編碼器如何降維還有激活函數的選擇(雖已不適用於現在),但這篇當初提出時影響真的太大了,每次看感覺都不一樣,彷彿從沒讀懂似的…。 關於孤立森林,相較於其他三者,這篇[7 ] 算是最新的概念了,基於對離群值特性的觀察而發展出不同的檢測方式。完全是從不同的思考點切入啊。這篇作者的指導教授是南京大學的周志華教授,有寫中文版的機器學習(暱稱:西瓜書),如果國外文獻看不下去,也可以看他的XD 幾篇很好的review,如果關鍵字搜尋“one class classification”應該會搜到這篇[8 ] ,主要是講一類支援向量機與其他,這篇是包山包海,應該能找到各個領域的應用,另外該篇作者推薦了這兩篇異常檢測[9 ] 、新奇檢測[10 ] ,我第一次沒看到那小小的註解,在第N次閱讀時發現這寶藏,千萬不要錯過了,真的是獲益良多! 除了一類演算法外,還有其他方式可以分析不平衡資料(一類資料幾乎沒有或是佔非常少比例的情況)。例如:人為的改變資料比例,關鍵字為SMOTE[11 ] 。
後記 使用程式套件時就是一個黑盒子,原始碼一定要好好看,不要太相信。在使用非監督學習方法挑選特徵時,真的就發現有R套件寫錯,不過也達成人生第一個debug公開資源包的成就,所以如果結果真的沒辦法解釋的話,或許回頭看看原始碼很有幫助。 雖然上面列了4種方法,但最後還是用到了集成學習才達到公司設的標準。不過集成真的不要太早用,畢竟解釋性太差,真不行,最後臨門一腳再用比較剛好。 文獻搜索時,這些詞的意思是差不多的,異常檢測(Anomaly detection)、極端值(Outlier)、不平衡資料(imbalanced data)、novelty detection。用關鍵字搜尋時,搜到的文獻會不太一樣,搭配著看能互補。 平時多看一下東西真的沒壞處,我完全沒想到這份工作的獲得是靠當初學生時代心血來潮多看的5分鐘,那曾經令我困惑的一類分類。 雖然上面一點數學式都沒列,不過真想搞懂這些方法,最好還是看一下XD 這篇文章沒談到key point,尤其是調參的部分完全沒說到怎麼調,畢竟已經是用toy model了,沒什麼好調的XD在我實務上的經驗裡,自編碼器的部分是最難處理的,超參數真的太多了,相較於其他三者而言。如果資料量不夠,真的不要太期待自編碼器或說深度學習能給你帶來太大的benefit…乖乖用“傳統的”方法快速又實際,不要糾結於一定要用最新的技術。 wiki的東西參考就好,免費的最貴…曾經開心地相信上面的資訊,結果發現引用年代錯誤。
資料來源:https://rstudio-pubs-static.s3.amazonaws.com/597912_8b0c4c14e130464d83c13ddbce22771b.html