模型信心的本質!:Probability Calibration
在兩週前,我針對sklearn裡面被廣泛使用卻很少人真正了解的method predict_proba()做出了解釋,因為大部分的應用中我們都希望知道模型的信心指數,所以大家會使用predict_proba()來做出具備機率性質的預測,但是卻很少人真的知道每個模型是怎麼產出機率數值的。
而在前兩篇我針對的是最被廣泛使用的兩類模型,一是Decision Tree、二是SVM,解釋了他們背後的邏輯,如果還不清楚這兩個模型如何給出機率預測、信心指數的話,推薦回去參考我前兩篇的解釋。
如果前兩篇都看完了,那我想大家最基礎的一個takeaway就是不要使用Decision Tree的predict_proba()。
但是這邊我們馬上就會遇到一個困境,我們這樣在使用每一個method的時候,都要花時間去研究它背後的原理,同時即便原理是好的,有些時候實際用起來效果還是不好。
依據ML的核心思想,我們應該要基於「衡量的結果 performance」來決定我們是否要使用一個模型或是方法。
我們要怎麼衡量我們的機率預測是否準確???
Calibration Curve,衡量你的機率是否準確!
有些朋友可能已經注意到了,我在SVM最後的時候放了一張圖(下圖),必且告訴你們,每個model畫出來的曲線,越靠近中間黑色斜直線(虛線)越好,這其實就是一個衡量機率是否準確的方法,而我們稱他為Calibration Curve。
這邊可能很多人就會有疑問了,我們這個Calibration Curve具體是怎麼算出來的,在Classification裡,我們的label只有0跟1兩種啊,怎麼樣衡量今天0.9的機率跟0.8的機率哪個比較準確?
實際上Calibration Curve用了一個非常聰明的方法,如下圖,他將我們模型預測的機率進行排序。(p^(y)是我們的predict_proba()、y是true label)
排序完之後,再進行binning,然後算出每個bin之中的average p^(y)跟y,也就是說如果你一個bin裡面有3筆data,分別的true label是 1, 1, 0,那你這個bin的average true label就是0.66666,而你的p^(y)如果分別是0.8, 0.7, 0.6,那這個bin的average p^(y)就是0.7,而我們希望0.666跟0.7這兩個數值越近越好,如果差很遠我們就會認為我們預測的機率很不準確。
當我們把一個dataset裡面所有test data都進行完binning之後,我們就可以依據p^(y)小到大畫出calibration curve。
所以這就是為甚麼說calibration curve越靠近中間斜直線越好,因為你跟斜率為1的斜直線越接近,就代表你每一個bin的average p^(y)跟y數值越接近。
而在scikit learn裡面calibration curve是一個非常成熟的function,可以直接使用,請參考calibration_curve。
除了Calibration curve以外,我們偶爾也會參考我們機率的分布,如果我們傾向預測非常極端的機率,或是預測某些機率特別多次,對我都是值得注意的訊號。
而做這件事情非常容易,就是畫我們預測出來的機率的histogram,如下圖。
這邊可以看到,Decision Tree所有的預測都是最極端的兩個bin,這就是上次我們講的Decision Tree容易over estimated的問題,而相對而言其他包含SVM、Random Forest都更穩定一點。
除了Calibration Curve及Histogram以外,還有一個大家常看的數值稱為Brier Score,Scikit Learn裡面一樣有支援的功能,請參考brier_score_loss。
但是我非常非常不推薦使用brier score來判斷calibration的效果
這邊我們看brier score的算式,如下圖
實際上Brier score就是把true label (只有0跟1),以及predict_proba()拿來算mean square error,所以對我們而言沒有任何意義,反而像是decision tree這種預測的很極端的,在brier score上效果會被高估。
完整如何衡量任何一個predict_proba效果的code可以參考下面這份code,包含calibration curve、histogram跟brier score。
那最後一個大問題,如果有些model沒有predict_proba(),我們是不是就沒有辦法了。
實際上ML裡calibration這個詞的意思,就是將預測校準成機率的形式,把不準的機率變準,把沒有機率性質的變成有機率性質。
而在scikit learn裡面一樣有非常完整的支援,請參考CalibratedClassifierCV。
calibrated_clf = CalibratedClassifierCV(base_estimator=base_clf, cv=3)
只要將任意一個base_estimator放入CalibratedClassifierCV這個function,我們都可以將它變成有predict_proba()的模型。(大部分模型都可行)
而在使用CalibratedClassifierCV時,內部有兩種進行calibration的方法。
第一種就是Platt Scaling,上一篇有詳細介紹過,這次不再贅述,歡迎大家回去參考上一篇。
不過Platt Scaline的核心就是在原本model output上再train一個logistic regrssion。
而第二個方法稱為isotonic regression。
isotonic regression本身就是一種regression model,能針對我們data去train出一個遞增函數。(如下圖)
而isotonic regression的好處就是比起一般的regression,他更flexible,同時又不容易被noise影響到,詳細細節或許之後再寫一篇介紹各種好用但是鮮為人知的regression時會再介紹。
而在Calibration中,isotonic regression跟platt scaling一樣,就是在原本的output上再train一個isotonic regression來校準我們的預測值。
這邊要注意,因為platt scaling跟isotonic regression其實都並非針對calibration curve去進行optimize,而是針對true label,也就是說當我們使用它們時,我們的probability會越來越傾向over estimated(因為true label只有0跟1),所以並不是加上platt scaling或isotonic regression就會變好,一般而言我們還是要針對calibration curve去挑選我們要的model。
Calibration實際上是上線的模型非常常做的事情,因為當我們有模型信心時我們多了不少資訊,我們可以從模型信心的下降來發現data drift,而不是真的到出錯了才發現這種問題。
但是Calibration是現在ML的課程、書籍幾乎不會提到的細節,因為對performance沒有直接幫助。
我用3篇講了calibration需要注意的細節跟基礎背景知識,在DL裡面我們有更多uncertainty based的方法,非常推薦大家再去深入研究。
如果喜歡這篇文章可以幫我多拍手幾次XD,或是對於哪個類型文章有興趣都可以在留言區跟我講~ 後續會以中難度的ML/DS/AI知識為主,以及AI/HCI研究相關知識