有案例有代码,详细模型分数
编辑导语:风控模型的应用场景非常广泛,只要牵扯互联网金融的行业就少不了风控,风控模型建好后还要映射到信用分数空间,才能呈现给用户;本文作者分享了详细的建模方法,教你如何建立模型分数,我们一起来看一下。
目前在个人信用风控建模领域主要使用的模型有两种:
这两种建模方法无论哪种都需要 将模型结果映射到信用分数空间 ,最终呈现给用户一个能够表征信用的分数,比如国内的芝麻分、美国的FICO分。
那么问题来了,模型结果和分数同样都是数值,为什么不直接呈现模型结果?为什么还要进一步转化为分数?为什么使用分数校准?
本文的目的就是要让你知其然也知其所以然。
深入到业务中,带你一步步搞懂分数映射产生的背景以及分数校准背后的业务需求;在了解了业务之后,你就会发现分数的意义和映射方法的内在逻辑。
一、分数映射的产生——一款产品一个模式
先从最简单的情况入手,假设我们现在成立了一家小信贷公司,推出一款借贷产品,详情如下:
(该产品数值仅作示意,不代表真实情况)
此时我们要解决的第一个问题是:如何让这款产品盈利?
信贷业务能够盈利的关键是还款人的利息能够覆盖坏账损失(不能收回的各种应收款项)。
也就是说要尽可能的把钱借给信用良好、按时还款的用户以保证产品盈利。
在产品参数确定后,逾期率是保证产品盈利的唯一影响因素。
这里要提一下关键的一点:如何定义逾期率?
在信贷领域通常逾期超过60天的用户基本上就不会再还钱了,自然的我们就可以通过逾期超过60天的比例来衡量用户的好坏程度。
在机器学习建模时,有时为了增加坏账样本的数量,也会将逾期超过30天的比例定义为逾期率。
1. 逾期率多久可以忍受
根据信贷业务盈利的逻辑,我们可以得到下面这个盈亏平衡的公式:
其中:
- L —— 表示额度;
- InterestRate —— 表示贷款年化利率;
- FundsRate —— 表示资金成本年化利率;
- pd 表示逾期率(Probability of Default);
- OperatingCost —— 表示运营成本;
- NewCost —— 表示拉新成本,指获取单个新客户所支付的金额(拉新成本的定价要结合营销方案具体问题具体分析)。
举个简单的例子,若从渠道购买流量,购买金额除以该渠道的新客户数量就是该渠道的新客成本。
再比如举办拉新奖励活动,成功拉取一个新用户所需要支付的奖励金额也是拉新成本。
总之拉新成本的计算要围绕实际引流方案、投入来确定。
将产品详情中数值带入公式后计算得到 pd = 0.015 ,即盈亏平衡点。
2. 如何确定模型稳定性是否发生了变化
什么是阈值cutoff?
我们先看一看真实的模型打分结果长什么样子,这里用的是XGBoost模型:
- label —— 样本真实类别,0表示正常还款, 1 表示逾期;
- predict —— 模型预测值。
对于二分类问题的模型,预测结果是一个0~1的小数,最终该观测点被判定为哪个类别是由阈值所决定的:p >= cutoff 表示1, p < cutoff 表示0。
这里有个小问题:逾期率和模型结果的值域都是[0, 1],那么模型预测值等于逾期率这个假设成立吗?
我们做一个简单的统计,如下:
从均值、分位点的结果上看他们并不能直接划等号。
理论上来说Linear Regression模型的输出概率可以认为是真实概率,而其他分类器的输出概率并不反映真实概率。
接下来我们需要将模型预测结果先排序,再分箱计算各个桶的逾期率,找到满足盈亏平衡点要求的预测结果阈值,低于阈值通过贷款申请,反之则拒绝贷款申请。
“`python
def get_cutoff(data, bin_size, fpd):
“””
第一步:确定分箱箱数
第二步:按照predict分数排序,划分bins
第三步:计算各个bins的逾期率,找到逾期率满足盈亏平衡点的分界线
:param data: Dataframe类型,包含 label(是否逾期), predict(模型预测值)两列数据
:param bin_size: 分箱个数
:param pd: 盈亏平衡点的逾期率
:return:
“””
bin_width = round((max(data[‘predict’]) – min(data[‘predict’])) / bin_size, 6)
bin_lst = [min(data[‘predict’]) + bin_width * i for i in range(bin_size + 1)]
bin_lst[0], bin_lst[-1] = 0, 1
data[‘bin’] = pd.cut(data[‘predict’], bin_lst)
bin_group = data.groupby(‘bin’)[‘label’].agg([ ‘mean’]).reset_index()
print(bin_group)
cutoff = None
for i in range(20):
if bin_group.iloc[i][‘mean’] > fpd:
cutoff = bin_group.iloc[i][‘bin’].left
break
return cutoff
“`
将上一环节计算出的盈亏平衡点0.015作为参数代入函数,返回cutoff值。
根据打印的分箱结果,可以看到在(0.0299, 0.0327)处,逾期率为0.015512,是第一个逾期率超过盈亏平衡点0.015的分箱。
因此把cutoff定为 0.0299,以保证拒绝掉不满足盈亏平衡点的用户。
3. 如何向客户展示信用评估结果?
至此,你的小公司将面临几种选择:
A. 直接告诉用户贷款申请结果呢?通过或拒绝这样做不是不可以,但给用户的感觉有点霸道了(是不是很像申请信用卡的感觉,等了半个月被通知审核失败),这不是一个追求用户体验的互金小公司该有的服务态度。
B. 把模型预测值所在的分箱逾期率作为信用评估结果反馈给用户呢?
这样做也不是不可以,但设身处地的站在用户角度想一想会怎样?
用户会不会产生疑问:
- 这小数点后这么多位的数值到底是个啥?
- 高了好还是低了好?
- 从小到大我只见过1星到5星,0分到100分……
通常真实逾期率在小数点2位以后有所差别,显然把逾期率反馈给用户是不够专业的;这还没考虑是不是暴露了商业机密的问题,比如客群质量、定价等。
那怎样更合理的向客户展示信用评估结果呢,下篇告诉你!
本文由 @FAL金科应用研院 原创发布于人人都是产品经理,未经许可,禁止转载。
题图来自 unsplash,基于 CC0 协议