風(fēng)控ML[4] | 風(fēng)控建模的KS

我們這做風(fēng)控模型的時(shí)候,經(jīng)常是會(huì)用KS值來(lái)衡量模型的效果,這個(gè)指標(biāo)也是很多領(lǐng)導(dǎo)會(huì)直接關(guān)注的指標(biāo)。今天寫一篇文章來(lái)全面地剖析一下這個(gè)指標(biāo),了解當(dāng)中的原理以及實(shí)現(xiàn),因?yàn)檫@些知識(shí)是必備的基本功。我將會(huì)從下面幾個(gè)方面來(lái)展開講解一下KS:
KS的概念 KS的生成邏輯 KS的效果應(yīng)用 KS的實(shí)現(xiàn)
01 KS的概念
KS的全稱叫“Kolmogorov-Smirnov“,我知道的是蘇聯(lián)數(shù)學(xué)家提出來(lái)的一個(gè)檢驗(yàn)方法,后面怎么地就用到了風(fēng)控模型的區(qū)分度評(píng)估就不知道咯。不過(guò)這不影響我們?nèi)ナ褂盟?,我們只需要知道在風(fēng)控中是怎么實(shí)現(xiàn)的,并且在實(shí)際場(chǎng)景中怎么去使用它就可以了。就如上面我們說(shuō)的,KS在風(fēng)控主要是用于評(píng)估模型的好壞樣本區(qū)分度高低的。什么是區(qū)分度?通俗來(lái)說(shuō),就是模型預(yù)測(cè)結(jié)果排序分桶后,每個(gè)桶的好壞樣本占比的有排序性,也就是說(shuō)不同的桶,壞人的識(shí)別能力都不同,我們可以通過(guò)“拒絕”壞人比較多的桶從而來(lái)實(shí)現(xiàn)風(fēng)險(xiǎn)控制。比較抽象?可以看下圖:

02 KS的生成邏輯
KS的生成邏輯公式也是十分簡(jiǎn)單:
在風(fēng)控領(lǐng)域,我們?cè)谟?jì)算KS前一般會(huì)根據(jù)我們認(rèn)為的“正態(tài)分布原則”進(jìn)行分箱,一般來(lái)說(shuō)分成了10份,然后再進(jìn)行KS的計(jì)算。具體的可以看下面的Demo:


03 KS的效果應(yīng)用
KS的值域在0-1之間,一般來(lái)說(shuō)KS是越大越有區(qū)分度的,但在風(fēng)控領(lǐng)域并不是越大越好,到底KS值與風(fēng)控模型可用性的關(guān)系如何,可看下表:

004 KS的實(shí)現(xiàn)
首先我們來(lái)對(duì)上面展示的例子進(jìn)行Python代碼實(shí)現(xiàn)。
import?pandas?as?pd
import?numpy?as?np
#?test?data
bin_df?=?pd.DataFrame([['bin0',?100,?10],
???????????????????????['bin1',?100,?20],
???????????????????????['bin2',?100,?30],
???????????????????????['bin3',?100,?34],
???????????????????????['bin4',?100,?40],
???????????????????????['bin5',?100,?50],
???????????????????????['bin6',?100,?58],
???????????????????????['bin7',?100,?70],
???????????????????????['bin8',?100,?75],
???????????????????????['bin9',?100,?95]]
??????????????????????,columns=['bins',?'bin_nums',?'bad_nums'])
bin_df['good_nums']?=?bin_df.bin_nums?-?bin_df.bad_nums
bin_df['bad_rate']?=?bin_df.bad_nums/bin_df.bin_nums
bin_df['good_rate']?=?1?-?bin_df.bad_rate
bin_df['bad_cum']?=?bin_df.bad_nums.cumsum()
bin_df['good_cum']?=?bin_df.good_nums.cumsum()
bin_df['bad_cum_rate']?=?bin_df.bad_cum/bin_df.bad_nums.sum()
bin_df['good_cum_rate']?=?bin_df.good_cum/bin_df.good_nums.sum()
bin_df['cum_rate_dif']?=?abs(bin_df.bad_cum_rate?-?bin_df.good_cum_rate)
bin_df

我們將數(shù)據(jù)進(jìn)行一下可視化:
from?matplotlib?import?pyplot
import?matplotlib.pyplot?as?plt
print("KS:",?bin_df.cum_rate_dif.max())
plt.plot(bin_df.bins,?bin_df.bad_cum_rate,?marker='o',?mec='r',?mfc='w',?label='bad_cum_rate')
plt.plot(bin_df.bins,?bin_df.good_cum_rate,?marker='*',?mec='r',?mfc='w',?label='good_cum_rate')
plt.plot(bin_df.bins,?bin_df.cum_rate_dif,?marker='x',?mec='r',?mfc='w',?label='good_cum_rate')
plt.legend()

可以看到可視化的效果和我們?cè)贓xcel里畫出來(lái)的差不多。
以上的代碼實(shí)現(xiàn)是基于分桶后的結(jié)果進(jìn)行操作的,但是在大多數(shù)的情況下,都是不先進(jìn)行分桶的,而是直接進(jìn)行KS的計(jì)算,而計(jì)算KS的方式主要有兩種:
#?test?data
y_true?=?np.array([1,1,0,0,0,0,0,0,0,0])?#?真實(shí)標(biāo)簽,0代表好人,1代表壞人
y_pred_proba?=?np.array([0.7,0.6,0.1,0.3,0.3,0.5,0.6,0.4,0.1,0.2])?#?模型預(yù)測(cè)概率結(jié)果,值域0-1,越大代表越解決壞人
#?way1
from?scipy.stats?import?ks_2samp
ks?=?ks_2samp(y_pred_proba[y_true?==?1],?y_pred_proba[y_true?==?0]).statistic
print("####?way1?####")
print("KS:",?ks)
#?way2
from?sklearn?import?metrics
fpr,?tpr,?thresholds?=?metrics.roc_curve(y_true,?y_pred_proba)
print("####?way2?####")
print("KS:",?max(tpr-fpr))
#?output
####?way1?####
KS:?0.875
####?way2?####
KS:?0.875
05 最后說(shuō)一下
光看KS值來(lái)評(píng)估模型效果其實(shí)是不足夠的,就好像我們看一個(gè)人并不能光看臉,還得看身材、人品、才能等等,我們還需要看AUC、準(zhǔn)確率、穩(wěn)定性、覆蓋率等等,這些后續(xù)都會(huì)陸續(xù)講到。今天我們就先了解清楚一下KS就可以了。
