1. 程式人生 > >模型評估:K-S值和AUC的區別

模型評估:K-S值和AUC的區別

(原創作者:陳玓玏)

在模型建立之後,必須對模型的效果進行評估,因為資料探勘是一個探索的過程,評估-優化是一個永恆的過程。在分類模型評估中,最常用的兩種評估標準就是K-S值和AUC值

可能有人會問了,為什麼不直接看正確率呢?你可以這麼想,如果一批樣本中,正樣本佔到90%,負樣本只佔10%,那麼我即使模型什麼也不做,把樣本全部判定為正,也能有90%的正確率咯?所以,用AUC值夠保證你在樣本不均衡的情況下也能準確評估模型的好壞,而K-S值不僅能告訴你準確與否,還能告訴你模型對好壞客戶是否有足夠的區分度。

下面分別看兩種評估指標的概念。

一、ROC曲線和AUC值

在邏輯迴歸、隨機森林、GBDT、XGBoost這些模型中,模型訓練完成之後,每個樣本都會獲得對應的兩個概率值,一個是樣本為正樣本的概率,一個是樣本為負樣本的概率。把每個樣本為正樣本的概率取出來,進行排序,然後選定一個閾值,將大於這個閾值的樣本判定為正樣本,小於閾值的樣本判定為負樣本,然後可以得到兩個值,一個是真正率,一個是假正率

真正率即判定為正樣本且實際為正樣本的樣本數/所有的正樣本數,假正率為判定為正樣本實際為負樣本的樣本數/所有的負樣本數。每選定一個閾值,就能得到一對真正率和假正率,由於判定為正樣本的概率值區間為[0,1],那麼閾值必然在這個區間內選擇,因此在此區間內不停地選擇不同的閾值,重複這個過程,就能得到一系列的真正率和假正率,以這兩個序列作為橫縱座標,即可得到ROC曲線了。而ROC曲線下方的面積,即為AUC值

對於AUC值,也許有一個更直觀的理解,那就是,在按照正樣本概率值對所有樣本排序後,任意選取一對正負樣本,正樣本排在負樣本之前的概率值,即為AUC值。也就是說,當所有的正樣本在排序後都能排在負樣本之前時,就證明所有的樣本都被正確分類了,此時的AUC值也會為1。那麼AUC值也就很好算了,如果有N個負樣本,其中正樣本有M個,那麼可取的所有帶正樣本的樣本對數對於排在第一位的正樣本來說,有M+N-1個,但其中包含M-1對(正,正)的樣本,而對於後面所有的正樣本而言,能夠取到的正樣本概率大於負樣本對數肯定小於其位置-1。

二、K-S曲線

K-S曲線其實資料來源和本質和ROC曲線是一致的,只是ROC曲線是把真正率和假正率當作橫縱軸,而K-S曲線是把真正率和假正率都當作是縱軸,橫軸則由選定的閾值來充當。

下面這一段解釋得更詳細的K-S和AUC的區別是參考的這篇部落格:

由於ks值能找出模型中差異最大的一個分段,因此適合用於cut_off,像評分卡這種就很適合用ks值來評估。但是ks值只能反映出哪個分段是區分最大的,而不能總體反映出所有分段的效果,因果AUC值更能勝任。
ROC值一般在0.5-1.0之間。值越大表示模型判斷準確性越高,即越接近1越好。ROC=0.5表示模型的預測能力與隨機結果沒有差別。
KS值表示了模型將+和-區分開來的能力。值越大,模型的預測準確性越好。一般,KS>0.2即可認為模型有比較好的預測準確性。

好了,引用結束。
K-S值一般是很難達到0.6的,在0.2~0.6之間都不錯。一般如果是如果負樣本對業務影響極大,那麼區分度肯定就很重要,此時K-S比AUC更合適用作模型評估,如果沒什麼特別的影響,那麼用AUC就很好了。

三、KS的計算和曲線繪製

程式碼如果要用,最好自己改改,因為這個資料格式是我自己用的,計算方式也是跟資料格式有關係的,工作中用的可能不一樣,所以最好是自己根據自己的寫一個,這個也只是我根據自己的資料格式來寫的,重要的是思路,不是程式碼本身。而且我畫的曲線是折線,最好是自己考慮寫一個平滑曲線的。

import matplotlib.pyplot as plt
#第一個引數是模型的預測值,第二個引數是模型的真實值
def draw_ks_curve(predict_result,true_result):
    tpr_list = []  #存放真正率資料
    fpr_list = []  #存放假正率資料
    dif_list = []  #存放真假正率差值
    max_ks_dot = []

    for i in np.arange(0,1.1,0.1):
        tpr = 0
        fpr = 0
        for j in range(len(predict_result)):
            if list(predict_result[j])[0]>i and true_result[j]==1:
               tpr = tpr+1
               tpr_list.append(tpr)
            if list(predict_result[j])[0]>i and true_result[j]==0:
               fpr = fpr+1
               fpr_list.append(fpr)
        tpr = tpr/sum(true_result)
        fpr = fpr/(len(true_result)-sum(true_result))
    fig = plt.figure(num=1, figsize=(15, 8),dpi=80)     #開啟一個視窗,同時設定大小,解析度
    plt.plot(np.arange(0,1,0.1),tpr_list)
    plt.plot(np.arange(0,1,0.1),fpr_list)