AUC(Area Under Curve)被定义为ROC曲线下的面积。我们往往使用AUC值作为模型的评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。其中,ROC曲线的横轴为(1-特异性),即1-预测对的bad实例/实际的bad实例数;纵轴为敏感性,即预测对的good实例/实际good的实例。从而AUC可以表示模型的准确性和排序能力。
那既然有了AUC为何还要KS呢?
答案很简单,因为他们展示模型功效的视角不一样。
下面我们来看一下KS的计算原理。
事实上,K-S检验出现在统计学非参数检验中,其全名为Kolmogorov-Smirnov Test。
先简单介绍下单样本的K-S检验。单样本K-S检验是利用样本数据来推断总体是否服从某一分布(如:Normal, Uniform, Poisson, Exponential),适用于探索连续型随机变量的分布形态。
好了,单样本K-S事实上检验的是分布形态,那不难理解两样本分布的K-S检验主要推测的就是两个样本是否具有相同的分布了。
KS的计算步骤如下:
- 计算每个评分区间的好坏账户数(计算的是特征的KS的话,是每个特征对应的好坏账户数)。
- 计算每个评分区间的累计好账户数占总好账户数比率(good%)和累计坏账户数占总坏账户数比率(bad%)。
- 计算每个评分区间累计坏账户占比与累计好账户占比差的绝对值(累计good%-累计bad%),然后对这些绝对值取最大值即得此评分卡的KS值。
ks_2samp实现: scipy.stats.ks_2samp 计算
def ks_calc_2samp(data,score_col,class_col):
'''
功能: 计算KS值,输出对应分割点和累计分布函数曲线图
输入值:
data: 二维数组或dataframe,包括模型得分和真实的标签
score_col: 一维数组或series,代表模型得分(一般为预测正类的概率)
class_col: 一维数组或series,代表真实的标签({0,1}或{-1,1})
输出值:
'ks': KS值,'cdf_df': 好坏人累积概率分布以及其差值gap
'''
Bad = data.ix[data[class_col[0]]==1,score_col[0]]
Good = data.ix[data[class_col[0]]==0, score_col[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
crosstab实现:采用pandas.crosstab函数来计算累积概率分布
def ks_calc_cross(data,score_col,class_col):
'''
功能: 计算KS值,输出对应分割点和累计分布函数曲线图
输入值:
data: 二维数组或dataframe,包括模型得分和真实的标签
score_col: 一维数组或series,代表模型得分(一般为预测正类的概率)
class_col: 一维数组或series,代表真实的标签({0,1}或{-1,1})
输出值:
'ks': KS值,'crossdens': 好坏人累积概率分布以及其差值gap
'''
ks_dict = {}
crossfreq = pd.crosstab(data[score_col[0]],data[class_col[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
roc_curve实现:sklearn库中的roc_curve函数计算roc和auc时
from sklearn.metrics import roc_curve,auc
def ks_calc_auc(data,score_col,class_col):
'''
功能: 计算KS值,输出对应分割点和累计分布函数曲线图
输入值:
data: 二维数组或dataframe,包括模型得分和真实的标签
score_col: 一维数组或series,代表模型得分(一般为预测正类的概率)
class_col: 一维数组或series,代表真实的标签({0,1}或{-1,1})
输出值:
'ks': KS值
'''
fpr,tpr,threshold = roc_curve((1-data[class_col[0]]).ravel(),data[score_col[0]].ravel())
ks = max(tpr-fpr)
return ks
对于模型我们期望他有什么功效特征呢?那当然是模型给出的评分对于Good sample和Bad sample有很强的区分能力。也就是说对于该模型的评分结果,Good sample累积概率的分布形态和Bad sample累积概率的分布形态有显著的差异。所以我们可以使用两样本分布的K-S检验达到我们模型验证的目的。
验证过程中,如果发现坏客户估计值的经验分布与好客户估计值的经验分布有显著差异且差异表现为更多的坏客户集中于低分区&更多的好客户集中于高分区,那就能说明我们的模型具备了一定的区分功效。所以我们使用K-S统计量对这个区分能力进行量化,K-S统计量等于好客户和坏客户的累积概率差的最大值,即:
那么如何在SAS里实现累积概率的作图以及KS统计量的计算呢?
SAS的proc npar1way可以帮助我们轻松得到好坏样本的累积概率分布图以及KS统计量:
代码如下
proc npar1way data=dataset wilcoxon edf;
class y;
var edf;
run;
同时可得其KS统计量=0.132846。
对于得到的KS值该如何评判?
以下是传统的评价准则,通常要求模型KS值在0.4以上。
继续来开一下脑洞
一般的理论介绍到这里就已经结束了,但是KS值总有那么一点不完美,那就是KS统计量实际上是通过一个点的值来判断好坏样本分布的差异性,也就是说指标存在一定的不稳定性。那有什么方法可以改善他的稳定性呢?
我们不妨参考ROC——>AUC的思想,使用面积(如下图红色部分)来表达其分布的差异。
定义了一个新统计量“K-S曲线下的面积(Area under the K-S curve)”,其将两条累积概率曲线做差形成KS曲线,并计算其于x轴之间的面积(事实上就等于上图红色区域的面积),并将其面积值简写为AUKS。以下是他们对于AUKS的定义和评价:
当
,可以假设
,则
与K-S统计量相比,AUKS统计量的优点在于:从整个评分的取值域而不是一个点来检验模型的优劣,具有更好的稳定性,对样本量的依赖程度相对较低。我们用两个统计量对评价模型进行了验证,在模拟实验中,与K-S统计量相比,AUKS统计量始终有更加稳定的均值、更小的标准差和更小的变异系数,作为信用评分模型的评价指标具有更好的稳定性。