如果還沒有看過predict_proba的part1的朋友,很多資訊可能要看完part 1才能跟得上,歡迎大家先回頭看part 1的內容。
上次我解密了Decision Tree是怎麼樣輸出機率預測的,並且也強調了:Decision Tree的predict_proba並不可靠!
而這篇要從大家另外一個最喜歡使用的ML model SVM來進行分析,SVM的predict_proba是如何實踐的,我們可以信任他嗎?應該要使用他嗎?
SVM有沒有機率性質的預測???
答案是沒有
這邊非常推薦大家去聽林軒田老師的機器學習課程,其中對所有模型的說明都比現在普遍大學課程更詳細,但是講的更易懂
簡單來講,SVM是藉由每個點對Decision Boundary的位置,來判斷類別,而我們模型的預測就是這個點與我們Decision Boundary的距離,如果距離為正數則predict為1,距離為負數則predict為-1。
因為我們模型預測的是距離,而距離可以是 負無限大 ~ 無限大,所以我們的輸出必定沒有機率性質,因為他沒有符合機率的公理。
但是SVM卻讓我們直覺上有機率的感覺
因為我們有每個點對Decision Boundary的距離,所以直覺來想,離Decision Boundary越近,我們模型的信心越低,離Decision Boundary越遠,我們模型的信心越高。
而這種信心的概念,也正是SVM的optimization目標,藉由讓Decision Boundary與兩個類別的所有點都盡量遠,來讓我們模型更robust。
那我們要怎麼把這個直覺變成一個數學公式???
接下來就要提到Calibration的概念
什麼是Calibration
在機器學習中,Calibration做的事情就是讓模型的機率預測變得更準,或是讓沒有機率預測的模型產出機率預測。
簡單來講,上面我們講了SVM本身的預測並不具備機率的性質,因為不符合機率的公理。
那Calibration做的事情就是在SVM的預測上加入新的機制,讓新的預測符合機率性質。
那這邊大家可能就會立即想到一個非常常見的例子:Sigmoid function
沒錯 Sigmoid function做的事情其實就是Calibration想做的事情,把每個Deep Learning最後的linear output變成具備機率性質的output。
而實際上我們在Calibration中也有類似Sigmoid function的方法:
Platt Scaling
Platt Scaling介紹
Platt Scaling其實做的事情就是在SVM後加入一個Trainable的Sigmoid,更準確而言,加上一個1D Logistic Regression,如下列公式。
f_i 就是原本的SVM output,而A跟B就是Logistic Regression的Weight跟Bias。
而因為我們已知Logistic Regression的最後會加上一個Sigmoid Function。
而Sigmoid function會將 負無限大~無限大的數值映射到 0~1之間,所以我們就把原本不具備機率性質的預測轉換為符合機率的公理。
那這邊可能有人會問:
為甚麼我們要A跟B,不是直接使用Sigmoid function就可以符合機率性質嗎?
實際上這是對的,如果我們單單只是需要機率性質的話我們只需要加入Sigmoid function即可,但是Platt Scaling藉由加上A跟B兩個參數,讓模型更有彈性去做修正,而如果Platt Scaling本身認為原本SVM做的夠好,那大可以把A變成1、B變成0,這樣就跟直接加上Sigmoid function一致。
也就是說加入trainable的A跟B給Platt Scaling多一個彈性,變成更通用的模型。
Platt Scaling什麼時候好用???
實際上大部分時候都滿好用的,尤其Platt Scaling被大量的使用、研究在SVM上,所以我們SVM的predict_proba通常效果滿好的。
不過實際使用上來看,Platt Scaling在兩種情況效果特別好
- 當我們模型的機率預測具有對稱性的錯誤時,也就是說我們在預測高機率跟低機率有對稱的錯誤。
- 當我們模型under estimate機率時,也就是說我們習慣把0.9的機率預測成0.7、0.1的機率預測成0.3,對於兩個class的信心都偏低的時候。
這兩種情況只要使用Platt Scaling通常都會有明顯的提升。
不過這也導致,如果我們機率預測不具備對稱性的錯誤時,Platt Scaling不見得有幫助,而最常見讓我們不具備對稱性的情況就是:Imbalanced Dataset。
所以Imbalanced Dataset使用Platt Scaling時要非常非常的小心。
Scikit Learn SVM predict_proba範例。
from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
from sklearn.model_selection import train_test_splitiris = load_iris()
X, y = iris.data, iris.targetX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)clf2 = SVC(probability=True)
clf2.fit(X_train, y_train)
prob = clf2.predict_proba(X_test)print(prob)
這邊要特別注意,要使用SVM的predict_proba的話,必須在叫出SVC的時候就將probability設為True,也就是這行。
clf2 = SVC(probability=True)
而上面這整段code的output為下。
相對於Decision Tree顯然是更中庸的機率預測,不會動不動就變成100%的機率,但是還是可以看到很多90%以上的機率存在。
而在使用SVM的predict_proba時還有一個非常非常重要需要注意的事情!
SVM的predict_proba跟predict可能結果不一致。
也就是說,有時候我們可能predict成1的input,在predict_proba裡面得到低於0.5的機率,也就是說predict_proba傾向把同樣這個input預測成0。
因為我們的platt scaling有A跟B這兩個term,所以可能會讓原本預測的機率數值,符號改變掉(如果原本太靠近Decision Boundary,可能會因為加上B而從一邊變到另外一邊)
所以在使用SVM的時候,如果要用predict_proba,就必須自行利用numpy的argmax function來產出最終output,而不能使用svc.predict()
除此之外,必須要注意只有svm.SVC這個function有probability = True的選項,linearSVC是不具備的,所以請不要使用linearSVC來進行predict_proba,會直接爆error。
同時當你把predict = True開起來時,svm.SVC的training時間會大幅度上升,約4~5倍,是一個滿大的tradeoff。
這邊先收尾SVM的Calibration,scikit learn裡面有實驗各種calibration的方法在SVM上的效果,每一條線越靠近中間黑色虛線越好。
可以看到SVC+Sigmoid的效果,也就是在SVM上做platt scaling的效果是非常好的。
而其他的方法以及如何解讀上面這張圖,我將在Calibration的第三篇,重點解釋Calibration的各種概念!!
怎麼衡量目前的機率預測好壞??其他Calibration的方法??
結論SVM的predict_proba很好用,效果也很好,可以直接使用,但是要特別注意predict_proba跟predict兩者不一致的情形。
如果喜歡這篇文章可以幫我多拍手幾次XD,或是對於哪個類型文章有興趣都可以在留言區跟我講~ 後續會以中難度的ML/DS/AI知識為主,以及AI/HCI研究相關知識