KS和roc曲线
- TN:将负类预测为负类(真负类)
- FN:将正类预测为负类(假负类)
- TP:将正类预测为正类(真正类)
- FP:将负类预测为正类(假正类)
精确率:是针对我们预测结果而言的,它表示的是预测为正的样本中有多少是真正的正样本。
召回率:是针对我们原来的样本而言的,它表示的是样本中的正例有多少被预测正确了。
准确率 (Accuracy)
测试样本中正确分类的样本数占总测试的样本数的比例。
精确率 (Precision)
准确率又叫查准率,测试样本中正确分类为正类的样本数占分类为正类样本数的比例。
召回率 (Recall)
召回率又称查全率,测试样本中正确分类为正类的样本数占实际为正类样本数的比例。
F1 值
F1 值是查准率和召回率的加权平均数。F1 相当于精确率和召回率的综合评价指标,对衡量数据更有利,更为常用。
真正类率(TPR)
预测的正类中实际正实例占所有正实例的比例。(跟召回率一样的计算公式)
负正类率(FPR)
预测的正类中实际负实例占所有负实例的比例。
KS曲线
我们训练出来的模型,一般不是直接给出是正类还是负类的结果,给的是为正类的概率,我们还需要选择一个阈值,实例通过模型得到的概率大于阈值,判断为正类,小于阈值判断为负类。也就是说阈值的不同,以上的各个指标的值也是不同的。把阈值看成自变量,以上TPR、和FPR看成因变量,在二维坐标系里面做关系曲线,这就是KS曲线。
KS值
我们想要评估模型的能力,在阈值不同的情况下,TPR和FPR 又不一样,突然迷惘起来,这个时候,需要找到一个唯一评判标准,最值有唯一性,上图红色部分表示TPR-FPR,那我们就用最高点作为模型能力的评估标准吧!!对,没有错,最高点就是所谓的KS值,我们用KS值来作为评估模型区分能力的指标,KS值越大,模型的区分能力越强。公式如下:
ROC 曲线
ROC的全称是“受试者工作特征”(Receiver Operating Characteristic)曲线。
还是以上的TPR和FPR值,以上我们知道了KS值能表示模型的区分能力,我们只在阈值等于KS值时,觉得模型是好的,这样忽视掉了阈值取其他值的情景,有没有一种评估标准,无关阈值的取值呢?
在实际应用场景中,模型预测了一个样本集,在预测为正类中,我们当然希望的是,预测为正类的样本中,实际也为正类样本的比例越高越好,预测为正类的样本中,实际为负类样本的比例越小越好,也就是说,TPR越大越好,最好等于1,FPR越小越好,最好等于0,可是没有这么完美的事情,TPR变大的同时,FPR也会变大。数学家是聪明的,同时变化是吧,变化的速度总是有区别的吧?
我们随机取很多阈值,得到很多FPR和TPR。用 X轴表示FPR,Y轴表示TPR,绘制上图曲线,这个曲线就是ROC曲线。(0,0)和(1,1)这两个坐标点根据实际情况,我们知道是固定的,假如两者的变化率是一样的,也就是说是一条过(0,0) 和(1,1) 的直线,此时斜率为1,也就是说随着阈值的变化,FPR和TPR 都同等程度变化。绘制出了曲线,是否可以用曲线的特性来表示模型的能力呢?我们希望得到的是:
- FPR 变化快的时候,TPR变化慢.
- FPR变化慢的时候,变化快。
到这里,我们又找到了一个评估模型的指标,对,就是图中的阴影面积,观察发现,我们可以用这个阴影面积的大小,来反应上面我们希望得到的特性,这个阴影面积的大小叫做AUC值。
AUC
AUC(Area Under Curve) 被定义为ROC曲线下的面积,因为ROC曲线一般都处于y=x这条直线的上方,所以取值范围在0.5和1之间,使用AUC作为评价指标是因为ROC曲线在很多时候并不能清晰地说明哪个分类器的效果更好,而AUC作为一个数值,其值越大代表分类器效果更好。需要注意的是AUC是一个概率值,当随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的分数将这个正样本排在负样本前面的概率就是AUC值。所以,AUC的值越大,当前的分类算法越有可能将正样本排在负样本值前面,既能够更好的分类。
评分卡 分箱 WOE IV
分箱
- 把离散特征的类别进行分箱二次分类(比如,中国的所有城市,通过分箱划分为县区市地区等),可以让模型快读迭代。
- 对于连续特征,分箱会降低数据的噪声影响。分箱后的数据有很强的稳定性。
- 将连续数据分箱后,进行哑变量或独热编码的处理,每个特征中的每一类别就有了权重,这样相当于为模型引入的非线性,能够提升模型的拟合能力。
一句话概括:分箱主要是为了避免连续型变量的取值过于稀疏从而影响模型去学习其中的“好坏”规律。
无监督分箱:等频分箱和等距分箱。等频分箱是使每箱的样本数相等,等距分箱是使每个箱的宽度相等。
有监督分箱:卡方分箱、决策树分箱、Best-KS分箱
- 卡方分箱:是一种自底向上的(即基于合并的)数据离散化方法。 先算出单变量每个取值的卡方,再把卡方值相近的取值合并到一个箱里。
- 决策树分箱:与卡方分箱不同,决策树分箱是一种自上而下的分箱方法。通过计算信息增益,我们可以对单个自变量的划分生成决策树。决策树的分裂节点就是每个箱的边界。最终得到的叶子节点就是每一个箱。
- Best-KS分箱也是一种从上到下的分箱方法。和决策树使用信息增益判断是否分箱不同,Best-KS分箱一般选择KS值最大的地方做分裂点。
不论采用哪种分箱方式,我们最终得到的都是各区间的分裂点。在Python中,它很可能是一个列表的形式,像这样:[5,20,35,40,60]。仅仅得到分裂点是不够的,我们还需要对原始数据进行相应的处理。这就引出了下面的两个概念:
WOE与IV值
WOE的全称是“Weight of Evidence”,即证据权重。WOE是对原始自变量的一种编码形式。
WOE的两种公式理解
1.坏人的分布减去好人的分布。
2.每个箱中的坏人好人之间的比值 与 整个特征中坏人好人之间的比值 的差异。
WOE越大,以上这两种差异就越大。原始数据中好人,坏人都混在一起,是无法分清的。我们通过分箱的操作,可以把好人坏人尽可能的分割开,而WOE就是衡量分箱后,好人坏人的分割程度的。
IV是Information Value的缩写。它其实是单变量所有WOE取值的加权平均,用来衡量这个变量整体的预测能力,或者说“区分度”。IV值越大,则变量的区分效果越好。
逻辑回归模型转化为评分卡:
由逻辑回归的基本原理,我们将客户违约的概率表示为p,则正常的概率为1-p。因此,可以设:
此时,客户违约的概率p可表示为:
根据逻辑回归计算可得:
评分卡设定的分值刻度可以通过将分值表示为比率对数的线性表达式来定义,即可表示为下式:
其中,A和B是常数。式中的负号可以使得违约概率越低,得分越高。通常情况下,这是分值的理想变动方向,即高分值代表低风险,低分值代表高风险。
式中的常数A、B的值可以通过将两个已知或假设的分值带入计算得到。通常情况下,需要设定两个假设:
(1)给某个特定的比率设定特定的预期分值;
(2)确定比率翻番的分数(PDO)
根据以上的分析,我们首先假设比率为x的特定点的分值为P。则比率为2x的点的分值应该为P-PDO。代入式中,可以得到如下两个等式:
假设我们期望x=(bad/good)=5%时的分值为50分,PDO为10分(即每增加10分bad/good比例就会缩减一半),代入式中求得:B=14.43,A=6.78,这个时候bad/good=10%时score=40
评分卡刻度参数A和B确定以后,就可以计算比率和违约概率,以及对应的分值了。通常将常数A称为补偿,常数B称为刻度。
则评分卡的分值可表达为:
式中:变量x1…xn是出现在最终模型中的自变量,即为入模指标。由于此时所有变量都用WOE转换进行了转换,可以将这些自变量中的每一个都写(βiωij)δij的形式:
式中ωij 为第i行第j个变量的WOE,为已知变量;βi为逻辑回归方程中的系数,为已知变量;δij为二元变量,表示变量i是否取第j个值。上式可重新表示为:
此式即为最终评分卡公式。如果x1…xn变量取不同行并计算其WOE值,式中表示的标准评分卡格式,基础分值等于(A?Bβ0);由于分值分配公式中的负号,模型参数β0,β1,…,βn也应该是负值;变量xi的第j行的分值取决于以下三个数值:
总的来说整体的思想就是根据每个变量的系数进行评分转换,好的变量我们给与高的评分,坏的变量给与低分或者负分。
T检验:比较两个平均数的差异是否显著
F检验:检查不同样本的总体方差是否相同的一种方法
实战代码: 数据为财务相关指标数据,第一列是公司代码,中间是相关指标,最后一列是是否违约数据。
import numpy as np
import pandas as pd
from scipy import stats
import scorecardpy as sc
from sklearn.linear_model import LogisticRegression
data = pd.read_excel(r'E:\工作\逻辑回归过程文档\datadata.xlsx')
data.columns = ["COMPCODE","TOTASSET","净资产收益率","总资产收益率","每股收益盈利能力","销售净现率","每股现金净流量","流动比率","速动比率","现金债务比","权益债务比","每股净资产","营运资金与总资产的比率","应收账款周转率","存货周转率","总资产周转率","销售增长","利润增长","资本增长","长期债务与营运资金的比率","资产留存收益的比率","资产负债率"," Log(总资产)","log(净资产)","TARGET"]
for i in data.columns:
data[i] = data[i].fillna(stats.mode(data[i])[0][0])
data =data[~data.isin([np.nan, np.inf, -np.inf]).any(1)]
compcode = data['COMPCODE']
data=data.drop('COMPCODE', axis=1)
data=data.drop('TOTASSET', axis=1)
dt_s=data
'''
def var_filter(dt, y, x=None, iv_limit=0.02, missing_limit=0.95,
identical_limit=0.95, var_rm=None, var_kp=None,
return_rm_reason=False, positive='bad|1')
'''
lable = dt_s.columns
print(lable)
train, test = sc.split_df(dt_s, 'TARGET').values()
bins = sc.woebin(dt_s, y="TARGET")
'''
def woebin(dt, y, x=None,
var_skip=None, breaks_list=None, special_values=None,
stop_limit=0.1, count_distr_limit=0.05, bin_num_limit=8,
# min_perc_fine_bin=0.02, min_perc_coarse_bin=0.05, max_num_bin=8,
positive="bad|1", no_cores=None, print_step=0, method="tree",
ignore_const_cols=True, ignore_datetime_cols=True,
check_cate_num=True, replace_blank=True,
save_breaks_list=None, **kwargs):
'''
bins_adj=bins
train_woe = sc.woebin_ply(train, bins_adj)
test_woe = sc.woebin_ply(test, bins_adj)
y_train = train_woe.loc[:,'TARGET']
X_train = train_woe.loc[:,train_woe.columns != 'TARGET']
y_test = test_woe.loc[:,'TARGET']
X_test = test_woe.loc[:,train_woe.columns != 'TARGET']
lr = LogisticRegression(penalty='l1', C=0.9, solver='saga', n_jobs=-1)
lr.fit(X_train, y_train)
print(lr.coef_)
print(lr.intercept_)
train_pred = lr.predict_proba(X_train)[:,1]
test_pred = lr.predict_proba(X_test)[:,1]
train_perf = sc.perf_eva(y_train, train_pred, title = "train")
test_perf = sc.perf_eva(y_test, test_pred, title = "test")
card = sc.scorecard(bins_adj, lr, X_train.columns, points0=600, odds0=1/19, pdo=80)
train_score = sc.scorecard_ply(train, card, print_step=0)
test_score = sc.scorecard_ply(test, card, print_step=0)
all_score = sc.scorecard_ply(dt_s, card, print_step=0)
all_score['COMPCODE']=list(compcode)
sc.perf_psi(
score = {'train':train_score, 'test':test_score},
label = {'train':y_train, 'test':y_test}
)
评分结果如下: 可以看到随着评分增加违约概率降低。
|