利用Python計算KS的實例詳解
在金融領域中,我們的y值和預測得到的違約概率剛好是兩個分布未知的兩個分布。好的信用風控模型一般從準確性、穩(wěn)定性和可解釋性來評估模型。
一般來說。好人樣本的分布同壞人樣本的分布應該是有很大不同的,KS正好是有效性指標中的區(qū)分能力指標:KS用于模型風險區(qū)分能力進行評估,KS指標衡量的是好壞樣本累計分布之間的差值。
好壞樣本累計差異越大,KS指標越大,那么模型的風險區(qū)分能力越強。
1、crosstab實現(xiàn),計算ks的核心就是好壞人的累積概率分布,我們采用pandas.crosstab函數(shù)來計算累積概率分布。
2、roc_curve實現(xiàn),sklearn庫中的roc_curve函數(shù)計算roc和auc時,計算過程中已經(jīng)得到好壞人的累積概率分布,同時我們利用sklearn.metrics.roc_curve來計算ks值
3、ks_2samp實現(xiàn),調(diào)用stats.ks_2samp()函數(shù)來計算。鏈接scipy.stats.ks_2samp¶為ks_2samp()實現(xiàn)源碼,這里實現(xiàn)了詳細過程
4、直接調(diào)用stats.ks_2samp()計算ks
import pandas as pd import numpy as npfrom sklearn.metrics import roc_curvefrom scipy.stats import ks_2samp def ks_calc_cross(data,pred,y_label): ’’’ 功能: 計算KS值,輸出對應分割點和累計分布函數(shù)曲線圖 輸入值: data: 二維數(shù)組或dataframe,包括模型得分和真實的標簽 pred: 一維數(shù)組或series,代表模型得分(一般為預測正類的概率) y_label: 一維數(shù)組或series,代表真實的標簽({0,1}或{-1,1}) 輸出值: ’ks’: KS值,’crossdens’: 好壞客戶累積概率分布以及其差值gap ’’’ crossfreq = pd.crosstab(data[pred[0]],data[y_label[0]]) crossdens = crossfreq.cumsum(axis=0) / crossfreq.sum() crossdens[’gap’] = abs(crossdens[0] - crossdens[1]) ks = crossdens[crossdens[’gap’] == crossdens[’gap’].max()] return ks,crossdens def ks_calc_auc(data,pred,y_label): ’’’ 功能: 計算KS值,輸出對應分割點和累計分布函數(shù)曲線圖 輸入值: data: 二維數(shù)組或dataframe,包括模型得分和真實的標簽 pred: 一維數(shù)組或series,代表模型得分(一般為預測正類的概率) y_label: 一維數(shù)組或series,代表真實的標簽({0,1}或{-1,1}) 輸出值: ’ks’: KS值 ’’’ fpr,tpr,thresholds= roc_curve(data[y_label[0]],data[pred[0]]) ks = max(tpr-fpr) return ks def ks_calc_2samp(data,pred,y_label): ’’’ 功能: 計算KS值,輸出對應分割點和累計分布函數(shù)曲線圖 輸入值: data: 二維數(shù)組或dataframe,包括模型得分和真實的標簽 pred: 一維數(shù)組或series,代表模型得分(一般為預測正類的概率) y_label: 一維數(shù)組或series,代表真實的標簽({0,1}或{-1,1}) 輸出值: ’ks’: KS值,’cdf_df’: 好壞客戶累積概率分布以及其差值gap ’’’ Bad = data.loc[data[y_label[0]]==1,pred[0]] Good = data.loc[data[y_label[0]]==0, pred[0]] data1 = Bad.values data2 = Good.values n1 = data1.shape[0] n2 = data2.shape[0] data1 = np.sort(data1) data2 = np.sort(data2) data_all = np.concatenate([data1,data2]) cdf1 = np.searchsorted(data1,data_all,side=’right’)/(1.0*n1) cdf2 = (np.searchsorted(data2,data_all,side=’right’))/(1.0*n2) ks = np.max(np.absolute(cdf1-cdf2)) cdf1_df = pd.DataFrame(cdf1) cdf2_df = pd.DataFrame(cdf2) cdf_df = pd.concat([cdf1_df,cdf2_df],axis = 1) cdf_df.columns = [’cdf_Bad’,’cdf_Good’] cdf_df[’gap’] = cdf_df[’cdf_Bad’]-cdf_df[’cdf_Good’] return ks,cdf_df data = {’y_label’:[1,1,1,1,1,1,0,0,0,0,0,0], ’pred’:[0.5,0.6,0.7,0.6,0.6,0.8,0.4,0.2,0.1,0.4,0.3,0.9]} data = pd.DataFrame(data)ks1,crossdens=ks_calc_cross(data,[’pred’], [’y_label’]) ks2=ks_calc_auc(data,[’pred’], [’y_label’]) ks3=ks_calc_2samp(data,[’pred’], [’y_label’]) get_ks = lambda y_pred,y_true: ks_2samp(y_pred[y_true==1], y_pred[y_true!=1]).statisticks4=get_ks(data[’pred’],data[’y_label’])print(’KS1:’,ks1[’gap’].values)print(’KS2:’,ks2)print(’KS3:’,ks3[0])print(’KS4:’,ks4)
輸出結(jié)果:
KS1: [ 0.83333333]KS2: 0.833333333333KS3: 0.833333333333KS4: 0.833333333333
當數(shù)據(jù)中存在NAN數(shù)據(jù)時,有一些問題需要注意!
例如,我們在原數(shù)據(jù)中增加了y_label=0,pred=np.nan這樣一組數(shù)據(jù)
data = {’y_label’:[1,1,1,1,1,1,0,0,0,0,0,0,0],’pred’:[0.5,0.6,0.7,0.6,0.6,0.8,0.4,0.2,0.1,0.4,0.3,0.9,np.nan]}
此時執(zhí)行
ks1,crossdens=ks_calc_cross(data,[’pred’], [’y_label’])
輸出結(jié)果
KS1: [ 0.83333333]
執(zhí)行
ks2=ks_calc_auc(data,[’pred’], [’y_label’])
將會報以下錯誤
ValueError: Input contains NaN, infinity or a value too large for dtype(’float64’).
執(zhí)行
ks3=ks_calc_2samp(data,[’pred’], [’y_label’])
輸出結(jié)果
KS3: 0.714285714286
執(zhí)行
ks4=get_ks(data[’pred’],data[’y_label’])
輸出結(jié)果
KS4: 0.714285714286
我們從上述結(jié)果中可以看出
三種方法計算得到的ks值均不相同。
ks_calc_cross計算時忽略了NAN,計算得到了數(shù)據(jù)正確的概率分布,計算的ks與我們手算的ks相同
ks_calc_auc函數(shù)由于內(nèi)置函數(shù)無法處理NAN值,直接報錯了,所以如果需要ks_calc_auc計算ks值時,需要提前去除NAN值。
ks_calc_2samp計算得到的ks因為searchsorted()函數(shù)(有興趣的同學可以自己模擬數(shù)據(jù)看下這個函數(shù)),會將Nan值默認排序為最大值,從而改變了數(shù)據(jù)的原始累積分布概率,導致計算得到的ks和真實的ks有誤差。
總結(jié)
在實際情況下,我們一般計算違約概率的ks值,這時是不存在NAN值的。所以以上三種方法計算ks值均可。但是當我們計算單變量的ks值時,有時數(shù)據(jù)質(zhì)量不好,存在NAN值時,繼續(xù)采用ks_calc_auc和ks_calc_2samp就會存在問題。
解決辦法有兩個
1. 提前去除數(shù)據(jù)中的NAN值
2. 直接采用ks_calc_cross計算。
以上這篇利用Python計算KS的實例詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持好吧啦網(wǎng)。
相關文章:
1. 使用Python webdriver圖書館搶座自動預約的正確方法2. SpringBoot整合Redis的步驟3. ASP.NET MVC使用jQuery ui的progressbar實現(xiàn)進度條4. Python3 json模塊之編碼解碼方法講解5. 在線php代碼縮進、代碼美化工具:PHP Formatter6. android H5本地緩存加載優(yōu)化的實戰(zhàn)7. PHP如何開啟Opcache功能提升程序處理效率8. PHP程序員簡單的開展服務治理架構(gòu)操作詳解(二)9. 詳解如何使用Net將HTML簡歷導出為PDF格式10.排行榜使用Python webdriver圖書館搶座自動預約的正確方法 1. android H5本地緩存加載優(yōu)化的實戰(zhàn) 2. ASP.NET MVC使用jQuery ui的progressbar實現(xiàn)進度條 3. 詳解如何使用Net將HTML簡歷導出為PDF格式 4. 5. PHP程序員簡單的開展服務治理架構(gòu)操作詳解(二) 6. PHP如何開啟Opcache功能提升程序處理效率 7. SpringBoot整合Redis的步驟 8. Python3 json模塊之編碼解碼方法講解 9. IntelliJ IDEA設置自動提示功能快捷鍵的方法 10. 在線php代碼縮進、代碼美化工具:PHP Formatter

網(wǎng)公網(wǎng)安備