前言:终于开始写风控模型啦!评分卡入门看了好几天,然后实践了一下,现在梳理总结一下整个推导以及建模过程,以便记性不好的本人随时查看。
另外由于scorecardpy那个包我在分箱的时候总报错,所以直接参照领导自己写的评分卡模型进行分箱和建模。
1. 评分卡模型基本思想
首先介绍几个概念:
odds:几率比/优势比
(odds ratio;OR)是另外一种描述概率的方式。优势比将会告诉我们某种推测的概率比其反向推测的概率大多少。换句话说,优势比是指某种推测为真的概率与某种推测为假的概率的比值。计算公式为 p 1 − p \frac{p}{1-p} 1−pp,其中,p表示事情发生的概率。odds越大,表明事情发生的概率就大
分数转换的基本思想:
希望分数每增加多少,odds就可以减少一倍
- 在一个
指定的分数
上,希望我的odds能达到多少
- 总的来说,
分数越高
,是好客户的概率就越大,更容易发生借贷
。
2. 评分卡模型基本推导公式
- 逻辑回归中
对数几率比和线性回归
的关系 - 转换后的
分数与几率比
的线性关系 - 将分数划分为
基础分数
和特征分数和
3. 评分卡模型代码
(1) 计算每个数据集上的模型分数
,保留整数
points0=600
odds0=1/50
model_param=lr_model_result.params #逻辑回归的系数
model_vars=features #最终入模的变量
B=-20/np.log(2)
A=points0-B*np.log(odds)
train_score=np.round(A+B*np.log(train_pred/(1-train_pred)))
#train_pred是逻辑回归预测出来的概率值
oot_score=np.round(A+B*log(oot_pred/(1-oot_pred)))
(2) 计算基础分
base_point=A+B*model_param['intercept']
(3) 生成每个变量在不同分箱上的模型分数
scard=pd.concat([feature_dict[f]['train_table'] for f in features])
#feature_dict是自己写的包含每个特征的每个区间的描述性统计信息,包括数量,比例,woe值,iv值等
s=pd.DataFrame()
for f in features:
#各自的特征的woe值乘以系数和B
f_data=round(scard[scard['var']==f]['woe']*B*model_param[f],0)
s=s.append(pd.DataFrame(f_data))
scard['woe_score']=s
#只需留下变量,分箱,每个分箱上的woe,以及每个分箱上的评分
scard_stat=scard[['var','bins','woe','woe_score']]
4. 根据区间段进行重新评分
由于最终上线后的模型在实际业务操作中,是根据该样本的特征所在区间段的评分进行加和求得,即 S c o r e = b a s e _ p o i n t + 每 个 特 征 的 特 征 分 Score=base\_point+每个特征的特征分 Score=base_point+每个特征的特征分,而逻辑回归中的分数是根据概率值按照 S c o r e = A + B ∗ l n p 1 − p Score=A+B*ln\frac{p}{1-p} Score=A+B∗ln1−pp来计算的。因此需要通过每个特征的特征分加和的方式再计算一次最后的预测分,从而进行模型的评估(主要是每个区间段上的坏账率)
train_score1=dataset['train'][features+['y']]
train_score['tezheng1']=train_score['tezheng1'].map(lambda x:
-2 if 123<x<=145 else
(4 if 145<x<200 else 7))
...
train_score1['score']=np.round(base_point+train_score1['tezheng1']+...+train_score1['tezhengk'])
(5) 根据标签和分数进行评估
#ut是自己写的模块哈
a=ut.split_performance_table(train_y,train_score1['score'],split=10)
b=ut.split_performance_table(oot_y,oot_score1['score'],split=10,breaks=a[1])
#按照训练集中的切分点进行划分
最后大概就长这个样子:
6. 如何观察
- 分数分段的时候要看是否包含整个分数段的最小值,如果是的话,需要在pd.cut中加入参数
include_lowest=True
坏账率
在每个分数段上应该是逐渐递减
的,也就是说分数越高,坏账率越小观察lift
的值,lift表示与不利用模型相比,采用模型预测能力变好了多少
,lift一般在2以上认为比较好- 再观察ks的值,
ks表示客群的稳定性
,一般最大值为0.2以上比较好
7. 计算每个月的ks
- 每个月的ks应该尽可能靠近大盘的ks,即最终模型效果的ks值,
每个月一般不能相差太大
,否则可以认为每个月客群不稳定
from sklearn.metrics import roc_curve
def ks(y_true,y_score):
fpr,tpr,_=roc_curve(y_true,y_score)
return np.max(np.abs(tpr-fpr))