上图中,我们最常用的就是TPR(True Positive Rate)和FPR(False Positive Rate):
其中:
TPR = TP/(TP+FN)即真实1中预测错的;
FPR = FP/(FP+TN)即真实0中预测错的;
Precision = TP/(TP+FP)即预测1中对的
最理想的模型,是TPR尽量高而FPR尽量低,然而任何模型在提高正确预测概率的同时,也会难以避免地增加误判率。听起来有点抽象,好在有ROC曲线非常形象地表达了二者之间的关系。
ROC曲线是以FPR为横轴,TPR为纵轴,在不同阈值下计算FPR和TPR的值画出的图形。
AUC就是ROC曲线下方的面积,值一般在0.5-1.0之间。值越大表示模型判断准确性越高,即越接近1越好。ROC=0.5表示模型的预测能力与随机结果没有差别。
KS值表示了模型将 和-区分开来的能力。值越大,模型的预测准确性越好。一般,KS>0.2即可认为模型有比较好的预测准确性。
KS曲线与ROC有着相同的作用:
KS曲线是将概率从小到大进行排序,取10%的值为阈值,同理将10%*k(k=1,…9)处值作为阈值,计算不同的FPR和TPR,以10%*k(k=1,…9)为横坐标,同时分别以TPR和FPR为纵坐标画出两条曲线就是KS曲线。而KS值=|max(TPR-FPR)|。详细的可以参考网址:/a/132667664_278472
另外,还有另一种计算KS值的方法:
将所有的样本根据分数值从低到高排序均分成20组,分别计算20组的实际好样本数、实际坏样本数、累积好样本数、累积坏样本数、累积好样本数占比、累积坏样本数占比、差值。其中,实际好坏样本数分别为该组内的好坏样本数;累积好坏样本数为该组累积好坏样本数;累积好坏样本数占比为累积好坏样本数占总好坏样本数的比值;差值为累积坏样本数占比 - 累积好样本数占比。
PSI在上一篇中已经做了具体介绍,想了解的可以关注我:
实现这几个指标的python代码如下:
from sklearn.metrics import roc_curvefrom scipy.stats import ks_2samp# 计算ks值def ks_calc_auc(data,pred,y_label):'''功能: 计算KS值,输出对应分割点和累计分布函数曲线图输入值:data: 二维数组或dataframe,包括模型得分和真实的标签pred: 一维数组或series,代表模型得分(一般为预测正类的概率)y_label: 一维数组或series,代表真实的标签({0,1}或{-1,1})输出值:'ks': KS值'''fpr,tpr,thresholds= roc_curve(data[y_label],data[pred])ks = max(tpr-fpr)return ks# 计算AUC值import matplotlib.pyplot as pltfrom sklearn.metrics import roc_curve, roc_auc_scoredef roc_auc_z(data,pred,y_label):# 计算auc的值fpr,tpr,thresholds= roc_curve(data[y_label],data[pred])auc_score=roc_auc_score(data[y_label],data[pred])return auc_scoredef target_total(df,nameks,date,lable): # nameks特征名字# nameks特征名字# date分组日期:如:"月份"# lable就是y变量## 为了计算psilabels=['c'+str(i) for i in range(10)]# True_out,bins=pd.qcut(df['result'],q=10,retbins=True,labels=labels, duplicates='drop')True_out,bins=pd.cut(df['result'],bins=[0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1],retbins=True, labels=labels)df['True_out'] = True_out# bins[0] = bins[0]-0.001 #cut左开右闭,之前最小值再分组后组记号为空,这里减0.01划到最左侧区间ksdf = pd.DataFrame(columns=['月份'])month = []week = []ks = []roc = []psi = []for i in range(len(df[date].unique())):w = df[date].unique()[i]data_ks = df.loc[df[date] == w,]m = data_ks['月份'].unique()[0]# 计算ks值ks_z = ks_calc_auc(data_ks,'result',lable)# 计算roc_auc值roc_z = roc_auc_z(data_ks,'result',lable)# 计算psi值if len(df[date].unique())>=3:data_psi_last = df.loc[(df[date] <= df[date].unique()[2]),]else:fri_m = df['月份'].unique()[0]data_psi_last = df.loc[(df['月份'] == fri_m),]a=pd.DataFrame(data_psi_last.True_out.value_counts()).rename(columns={'True_out':'基准占比'})a=a.applymap(lambda y : y/sum(a.基准占比))b=pd.DataFrame(data_ks.True_out.value_counts()).rename(columns={'True_out':'当月占比'})b=b.applymap(lambda y : y/sum(b.当月占比))re=pd.merge(a,b,left_index=True,right_index=True)psi_z=0for k in range(len(re)):if re['基准占比'][k]==0:re['基准占比'][k]=0.000001if re['当月占比'][k]==0:re['当月占比'][k]=0.000001l=math.log((re['当月占比'][k]/re['基准占比'][k]))p=((re['当月占比'][k]-re['基准占比'][k])*(math.log((re['当月占比'][k]/re['基准占比'][k]))))psi_z=psi_z+pmonth.append(m)week.append(w)ks.append(ks_z)roc.append(roc_z)psi.append(psi_z)ksdf['月份'] = monthksdf[date] = weekksdf['features'] = nameksksdf['ks'] = ksksdf['roc'] = rocksdf['psi'] = psiksdf['psi'] = ksdf['psi']*100return ksdf