風控模型評估

  本文總結了一下評分卡建模過程中常用的模型評估方法,並結合代碼展示,理論結合實際,方便初學者對模型評估的方法有深入的理解。之前寫過一篇模型評估的指標,偏於理論,詳情見風控模型指標詳解

1.AUC

  AUC值指的是ROC曲線下面積大小,該值能夠量化反映基於ROC曲線衡量的模型性能。所以,需要了解ROC曲線的繪製方法。
  首先,需要了解TPR(真陽性率)和FPR(假陽性率)。TPR就是P個正樣本中被預測爲正的概率,FPR是N個負樣本中被預測爲正樣本的概率。(FPR,TPR)形成ROC曲線上的一個點。

  ROC曲線通過不斷移動截斷點來生成不同的(FPR,TPR),可以理解爲評分卡中的cut-off在不斷變化。

  繪製出ROC曲線之後,AUC就是ROC曲線下的面積。此外ROC曲線相對應的P-R曲線之間的區別,有興趣的可以研究下,這裏不再贅述。下面附上代碼:

def plot_roc(y_label,y_pred):
    """
    y_label:測試集的y
    y_pred:對測試集預測後的概率
    
    return:ROC曲線
    """
    tpr,fpr,threshold = metrics.roc_curve(y_label,y_pred) 
    AUC = metrics.roc_auc_score(y_label,y_pred) 
    fig = plt.figure(figsize=(6,4))
    ax = fig.add_subplot(1,1,1)
    ax.plot(tpr,fpr,color='blue',label='AUC=%.3f'%AUC) 
    ax.plot([0,1],[0,1],'r--')
    ax.set_ylim(0,1)
    ax.set_xlim(0,1)
    ax.set_title('ROC')
    ax.legend(loc='best')
    return plt.show(ax)

2.KS

  KS曲線與ROC曲線非常的類似。KS曲線是兩條線,其橫軸是閾值,縱軸是TPR與FPR。兩條曲線之間之間相距最遠的地方對應的閾值,就是最能劃分模型的閾值。KS曲線是用來衡量分類型模型準確度的工具。

KS的計算步驟如下:

  1. 計算每個評分區間的好壞賬戶數。
  2. 計算每個評分區間的累計好賬戶數佔總好賬戶數比率(good%)和累計壞賬戶數佔總壞賬戶數比率(bad%)。
  3. 計算每個評分區間累計壞賬戶佔比與累計好賬戶佔比差的絕對值(累計good%-累計bad%),然後對這些絕對值取最大值即得此評分卡的K-S值。
def plot_model_ks(y_label,y_pred):
    """
    y_label:測試集的y
    y_pred:對測試集預測後的概率
    
    return:KS曲線
    """
    pred_list = list(y_pred) 
    label_list = list(y_label)
    total_bad = sum(label_list)
    total_good = len(label_list)-total_bad 
    items = sorted(zip(pred_list,label_list),key=lambda x:x[0]) 
    step = (max(pred_list)-min(pred_list))/200 
    
    pred_bin=[]
    good_rate=[] 
    bad_rate=[] 
    ks_list = [] 
    for i in range(1,201): 
        idx = min(pred_list)+i*step 
        pred_bin.append(idx) 
        label_bin = [x[1] for x in items if x[0]<idx] 
        bad_num = sum(label_bin)
        good_num = len(label_bin)-bad_num  
        goodrate = good_num/total_good 
        badrate = bad_num/total_bad
        ks = abs(goodrate-badrate) 
        good_rate.append(goodrate)
        bad_rate.append(badrate)
        ks_list.append(ks)
    
    fig = plt.figure(figsize=(8,6))
    ax = fig.add_subplot(1,1,1)
    ax.plot(pred_bin,good_rate,color='green',label='good_rate')
    ax.plot(pred_bin,bad_rate,color='red',label='bad_rate')
    ax.plot(pred_bin,ks_list,color='blue',label='good-bad')
    ax.set_title('KS:{:.3f}'.format(max(ks_list)))
    ax.legend(loc='best')
    return plt.show(ax)

  此外還有基尼係數,列出三者的綜合判斷標準:

3.交叉驗證

  交叉驗證是爲了評估模型的泛化能力。

  1. k折交叉驗證
  • 第一步,不重複抽樣將原始數據隨機分爲 k 份。
  • 第二步,每一次挑選其中 1 份作爲測試集,剩餘 k-1 份作爲訓練集用於模型訓練。
  • 第三步,重複第二步 k 次,這樣每個子集都有一次機會作爲測試集,其餘子集作爲訓練集。在每個訓練集上訓練後得到一個模型,用這個模型在相應的測試集上測試,計算並保存模型的評估指標。
  • 第四步,計算 k 組測試結果的平均值作爲模型精度的估計,並作爲當前 k 折交叉驗證下模型的性能指標
  1. 時間序列交叉驗證
      金融數據具有時間週期性的特點,不同時間段的樣本分佈和變量分佈會有一定差異,首先在選取建模的樣本時就要考慮是否能代表總體的樣本分佈或者近段時間用戶的狀態。在做交叉驗證時也需要考慮到時間週期這一點,例如我們選取的是1月份至10月份的數據,可以借鑑K折驗證的思想,將數據集按照月份分爲 10份,每次挑選其中一份作爲測試集,其他作爲訓練集,得到10組的驗證結果,觀察隨着月份的推移,模型的結果是否有比較大的趨勢變化,這個也可以反映出樣本是否穩定。如果變化較明顯,則需要分析是什麼原因導致的,是內部大的業務政策,還是外部的經濟環境。
# 交叉驗證
def cross_verify(x,y,estimators,fold,scoring='roc_auc'):
    """
    x:自變量的數據集
    y:target的數據集
    estimators:驗證的模型
    fold:交叉驗證的策略
    scoring:評級指標,默認auc
    
    return:交叉驗證的結果
    """
    cv_result = cross_val_score(estimator=estimators,X=x,y=y,cv=fold,n_jobs=-1,scoring=scoring)
    print('CV的最大AUC爲:{}'.format(cv_result.max()))
    print('CV的最小AUC爲:{}'.format(cv_result.min()))
    print('CV的平均AUC爲:{}'.format(cv_result.mean()))
    plt.figure(figsize=(6,4))
    plt.title('交叉驗證的評價指標分佈圖')
    plt.boxplot(cv_result,patch_artist=True,showmeans=True,
            boxprops={'color':'black','facecolor':'yellow'},
            meanprops={'marker':'D','markerfacecolor':'tomato'},
            flierprops={'marker':'o','markerfacecolor':'red','color':'black'},
            medianprops={'linestyle':'--','color':'orange'})
    return plt.show()

畫出的效果圖如下:

4.學習曲線

  學習曲線的縱軸是訓練集的大小,橫軸是模型在訓練集上和交叉驗證集上的平均得分(準確率),可以反映隨着訓練集大小的改變,模型在訓練集和驗證集上的誤差得分情況。進而判定模型的擬合情況。

  • 第一張圖中,隨着訓練集不斷增大,模型在訓練集和驗證集上的得分不斷靠近,但兩者的得分都比較低,存在欠擬合的問題。
  • 第二張圖中,隨着訓練集增大,模型在訓練集和驗證集上的得分不斷靠近,且兩者的得分都比較高,說明模型的擬合比較良好。
    更多關於學習曲線的問題可以查看官方文檔,鏈接是學習曲線
    注意:金融模型很容易出現過擬合的問題,解決過擬合的方法有很多,例如增加建模樣本,正則化等,例如邏輯迴歸裏可以選擇L1正則化或L2正則化,且可設置正則化的強度,另外做評分卡時,入模的變量不宜太多,太多的變量會使模型過於複雜,容易出現過擬合,一般應限制在15個以下。
# 學習曲線
def plot_learning_curve(estimator,x,y,cv=None,train_size = np.linspace(0.1,1.0,5),plt_size =None):
    """
    estimator :畫學習曲線的基模型
    x:自變量的數據集
    y:target的數據集
    cv:交叉驗證的策略
    train_size:訓練集劃分的策略
    plt_size:畫圖尺寸
    
    return:學習曲線
    """
    from sklearn.model_selection import learning_curve
    train_sizes,train_scores,test_scores = learning_curve(estimator=estimator,
                                                          X=x,
                                                          y=y,
                                                          cv=cv,
                                                          n_jobs=-1,
                                                          train_sizes=train_size)
    train_scores_mean = np.mean(train_scores,axis=1)
    train_scores_std = np.std(train_scores,axis=1)
    test_scores_mean = np.mean(test_scores,axis=1)
    test_scores_std = np.std(test_scores,axis=1)
    plt.figure(figsize=plt_size)
    plt.xlabel('Training-example')
    plt.ylabel('score')
    plt.fill_between(train_sizes,train_scores_mean-train_scores_std,
                     train_scores_mean+train_scores_std,alpha=0.1,color='r')
    plt.fill_between(train_sizes,test_scores_mean-test_scores_std,
                     test_scores_mean+test_scores_std,alpha=0.1,color='g')
    plt.plot(train_sizes,train_scores_mean,'o-',color='r',label='Training-score')
    plt.plot(train_sizes,test_scores_mean,'o-',color='g',label='cross-val-score')
    plt.legend(loc='best')
    return plt.show()

5.混淆矩陣

  混淆矩陣的指標有精確率,查全率(召回率),誤傷率。這三個指標的值取決於評分卡的cutoff點怎麼設置。評分卡最後會輸出一個評分分佈表,根據評分的等級和業務目標來選擇適當的cutoff點,從而計算出這三個指標。

# 混淆矩陣 /分類報告
def plot_matrix_report(y_label,y_pred): 
    """
    y_label:測試集的y
    y_pred:對測試集預測後的概率
    
    return:混淆矩陣
    """
    matrix_array = metrics.confusion_matrix(y_label,y_pred)
    plt.matshow(matrix_array, cmap=plt.cm.summer_r)
    plt.colorbar()

    for x in range(len(matrix_array)): 
        for y in range(len(matrix_array)):
            plt.annotate(matrix_array[x,y], xy =(x,y), ha='center',va='center')

    plt.xlabel('True label')
    plt.ylabel('Predict label')
    print(metrics.classification_report(y_label,y_pred))
    return plt.show()

【作者】:Labryant
【原創公衆號】:風控獵人
【簡介】:某創業公司策略分析師,積極上進,努力提升。乾坤未定,你我都是黑馬。
【轉載說明】:轉載請說明出處,謝謝合作!~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章