一个客户在APP上提交了借款申请,系统要在几秒内决定批不批、批多少、利率怎么定。你可能会以为背后跑着的是某个深度学习模型,但实际上,大多数信贷机构真正跑在评分决策流里的,还是那个看起来有点“过时”的逻辑回归。我在做个人贷款违约预测模型时也不例外——用逻辑回归做主干模型,而且一用就是很长时间。
逻辑回归在信贷风控里的地位,有点像家常菜里的西红柿炒蛋:不惊艳,但顶用,而且几乎人人都得学会做。原因不复杂:个人贷款违约预测这件事,核心不是“把精确率从98.1%提到98.2%”,而是要一个稳定、可解释、能落地到审批策略里的概率打分。这篇文章我就用自己做过的个人贷款违约预测项目为例,把逻辑回归从样本设计、特征工程、训练评估、评分卡换算到上线监控的完整链路拆开讲一遍。适合刚入行做风控建模的同学,也适合想搞明白“为什么公司非要我用逻辑回归”的业务和算法朋友。
1. 为什么做了这么多年风控,违约预测还是绕不开逻辑回归
1.1 可解释性是信贷决策的硬约束
做信贷风控和做图像识别最大的区别在于:图像识别判断错了顶多识别出一个猫,信贷判断错了是真金白银的损失,而且监管会来问“你为什么拒了这个人”。如果模型回答不了,产品就得下架。逻辑回归的每个特征对应一个明确的系数,正向还是负向、影响多大,都能直接读出来。客户年龄增加一岁,评分降低多少分,这些是可以写进审批说明里的。
我在某消费信贷项目里做过一个测试:同样的样本,跑了一个逻辑回归和一个梯度提升树模型,树模型的AUC确实高一些,但在一次业务评审会上,业务方拿着某笔拒绝样本的决策链来问“为什么拒”,树模型的shap值解释讲了大半天,对方依然半信半疑;而逻辑回归这边直接说“该客户近3个月征信查询次数过多,权重占比15%,单项减分30分”,业务方反而立刻接受了。这就是现实:不是树不好,是逻辑回归的系数本身就是业务语言。
1.2 逻辑回归输出的概率,是可以直接当钱用的
很多模型输出的是一个分类结果,但信贷决策需要的是一个连续的违约概率,或者一个评分。逻辑回归天然干这个事:输入特征x,输出违约概率p,然后通过odds换算成分数。风控策略里的“一刀切拒绝线”“分层定价”“额度调整”,全都是基于这个概率来设定的。
另外一件很多人忽略的事是,逻辑回归输出的概率相对可校准。树模型输出的“概率”其实是叶子节点的样本占比,会有明显的离散化和偏移;而逻辑回归基于极大似然估计,输出与真实违约率之间通常只需要做一次简单的校正就能贴近。对信贷这种“概率直接对应损失”的场景来说,这一点至关重要。
1.3 再复杂的模型,也需要一个逻辑回归当基线
我给团队定了一条规矩:任何新模型上线之前,先跑一个逻辑回归做基线。不是因为逻辑回归最好,而是它足够简单、稳健、不容易出错。如果树模型比逻辑回归只高0.5个点的AUC,但上线后需要投入大量精力做监控、解释和调参,那这笔账往往不合算。
而如果连逻辑回归都没跑通,说明样本或者特征本身就有问题,这时候去跑复杂模型大概率是在折腾自己。逻辑回归像一把尺子,量一量数据成色,也量一量复杂模型的真实增益。
2. 建模前最花时间的不是调参,而是样本设计与时间窗口
2.1 先搞清楚“违约”到底是谁
个人贷款违约预测里,最容易犯的错误就是没定义清楚目标变量。不是说“逾期了就是坏客户”,而是要定一个口径:观察期、表现期、逾期天数。我在项目里用的是比较通用的定义——表现期设为12个月,客户在观察期(比如申请前6个月)的特征被提取出来,之后12个月内只要出现逾期90天及以上的行为,就标记为chuyue客户。剩下的客户在表现期内没有出现严重逾期,才算是好客户。
这里有个关键逻辑:特征提取和表现期观察的时间窗口是不能重叠的。如果同一笔订单既拿去做特征,又拿它后面的逾期结果做标签,就变成了用未来预测现在,等于作弊。数据上看起来模型很准,上线后一定崩。这个坑我见过太多次,很多人一开始没注意,模型线下AUC做到0.75,一上线就掉到0.6以下,怎么找原因都找不到,最后发现是时间窗口穿越了。
2.2 训练集和验证集要按时间切,不能随机切
通用机器学习教程教你的都是随机切分训练集和测试集,但在信贷场景里这么干是错的。客户的借贷行为、收入水平、征信状况都在随时间变化,随机切分会让模型“偷看”到未来的信息分布。正确做法是按时间切:用较早时间段的数据做训练,用较晚时间段的数据做验证,模拟模型上线后面对新客户的情况。
我当时用某消费金融公司的申请数据,选了2019年7月到2020年6月的客户做训练集,2020年7月到2020年12月的客户做验证集,这样的结果才能真实反映模型在未来数据上的表现。用随机切分测出来的AUC通常会偏高零点三到五个百分点,别被这个虚高数字骗了。
2.3 违约率太低了,别乱下采样
个人贷款的整体违约率一般在2%-5%之间,好客户的样本量远大于坏客户。直接用原始样本训练,逻辑回归会倾向于把所有客户都预测成“好”,虽然准确率很高,但一点用都没有。常见的做法是下采样:把好客户抽一部分出来,让好和坏的比例变成大概2:1或者3:1。
但下采样之后有一个坑——模型输出的概率是训练样本里的概率,不是真实违约率。如果你用下采样后的样本训练出p=0.4,真实违约率可能只有0.03。这时候千万别直接把0.5当阈值,一定要做概率校准。校准公式其实不复杂,假设原始好客户权重为w,则调整后概率为:
p_adjusted = p / (p + (1-p) / w)
其中w是下采样后坏样本占比除以原始坏样本占比。比如原始坏率3%,采样后坏率33%,那w大概是11。这一步不做,你的评分卡所有分数都会系统性地偏掉。
2.4 拒绝样本要不要管
还有一个常被忽略的样本设计问题:建模用的样本一般只包含历史审批通过的客户,那些被拒掉的客户没有“表现期”,我们永远不知道他们会不会违约。但现实是,你上线后要评分的正是这些新申请客户,其中包含了很多过去会被拒绝的人。这就是拒绝推断问题。
我在项目里用的是一种比较实用的处理方式:先用通过样本训练一个初步模型,再用这个模型对拒绝样本做预测,把其中概率比较高的部分样本回填进训练集,给它们打上“预测坏”的标签。这种方法不完美,但能减轻样本选择偏差。如果完全不管拒绝样本,模型对高风险客户的区分能力会被系统性低估。
3. 特征工程里的分箱、WOE与IV:逻辑回归的灵魂步骤
3.1 为什么不能用原始数值直接喂给逻辑回归
逻辑回归本质上是一个线性模型,输入特征的数值大小和方向会直接影响系数估计。信贷特征里很多变量和违约率并不是线性关系。比如年龄,20多岁和50多岁违约风险都偏高,30-45岁反而低,这种倒U型关系用单一原始数值去拟合是拟合不出来的。解决方案就是分箱。
分箱还有一个实用的好处:能天然处理缺失值和异常值。在实际信贷数据里,收入的缺失、征信查询次数的极端值都很常见。分箱之后,缺失值单独成为一个箱,异常值并入最高或最低的箱里,模型中不会因为一个离群点被拉偏系数。这是把业务先验知识编码进模型的过程。
3.2 WOE编码的核心思想
分箱之后,每个箱位不能直接用序号当数值,因为箱位之间没有线性关系。常见做法是把每个箱位转换成WOE值(Weight of Evidence,证据权重)。WOE的计算公式为:
WOE = ln(好客户占比 / 坏客户占比)
每个箱位的WOE值反映了“这个箱位里的客户在多大程度上是好人还是坏人”。WOE越高,表明该箱位的好客户比例相对越高,风险越低;WOE越低甚至为负,表明该箱位的坏客户比例越高,风险越高。逻辑回归的系数直接和WOE对应,所以最后的分数解释起来非常直观。
我做分箱的时候有一条经验:每个特征的WOE趋势要尽量单调,或者至少符合业务常识。比如“近3个月征信查询次数”,查询次数越多的箱位WOE应该逐渐下降,说明风险在升高。如果某个箱位的WOE突然反弹,多半是分箱太细导致样本太少,噪声大,这时候要手动合并箱位。逻辑回归不像树模型那样能自动处理非线性,分箱质量决定了模型上限。
3.3 IV值筛选:哪些特征有资格进模型
IV值(Information Value)是衡量特征预测能力的最常用指标,和WOE紧密相关:
IV = Σ(好客户占比 - 坏客户占比) × WOE
我常用经验标准:IV小于0.02的特征基本没有预测力,不用;0.02到0.1属于弱预测力,可以结合业务意义决定是否保留;0.1到0.3属于中等偏强,重点保留;大于0.3的特征预测力很强,但也要小心,个别IV极高的变量往往和违约定义有重叠,可能引起逻辑回归共线性。
还得做一个相关性检查和VIF检查。有些特征单独看IV很高,但彼此高度相关,同时放进模型会导致系数不稳定。比如“近6个月查询次数”和“近3个月查询次数”IV都很高,实际上信息高度重叠。我在变量筛选阶段一般会先算一下相关系数矩阵,相关系数超过0.6的只保留IV较高的那个。
3.4 一个具体的分箱例子
以“客户年龄”为例,原始数据是20到60岁,我先用等频分箱粗分,再根据各箱WOE趋势手动调整,最终分成了“20-25”、“26-30”、“31-40”、“41-50”、“50岁以上”这几个箱。结果符合业务直觉:20-25岁客户收入不稳定,WOE偏低;31-40岁客户处于职业稳定期,WOE最高;50岁以上客户Work收入波动大,WOE又回落。这样的变量进入模型后,系数方向明确,业务解释顺畅。
另外一个典型的例子是“收入负债比”。这个变量很多人喜欢直接用数值,但它在不同收入段的影响明显不同。分箱后能看出,低负债比区间WOE基本平稳,高负债比区间WOE急剧下降——这就说明负债比超过某个阈值后风险陡增,逻辑回归的线性假设在这里直接失效,只有分箱才能捕捉到这种非线性。
4. 模型训练里容易翻车的地方:从损失函数到KS值
4.1 最大似然与正则化的取舍
逻辑回归用最大似然估计来求解参数,损失函数是交叉熵。这个学过统计的人都知道,但在工程实践里,真正影响模型效果的是正则化参数的选择。L1正则会把不重要特征的系数压到0,起到特征选择作用;L2正则把系数整体缩小,防止过拟合。
我在项目里偏好L2正则,因为信贷特征经过WOE变换后本来就不算太多,L2能让系数更稳定,保留特征的可解释性。正则化强度C值我一般用网格搜索,候选范围从0.01到10之间步进,选验证集KS最高的那组。有些人喜欢调随机梯度下降的迭代次数,其实逻辑回归收敛很快,真正影响结果的是特征质量而不是迭代次数。
4.2 KS和AUC,到底看哪个
信贷模型评估里最常用的两个指标是KS和AUC。AUC衡量整体排序能力,你把所有客户按预测违约概率从高到低排序,AUC表示随机抽一个坏客户比随机抽一个好客户排得更靠前的概率。KS则是把客户按违约概率分十等份,计算每一等份累计好客户占比和累计坏客户占比的最大差值,反映了模型在某个阈值附近的最大区分能力。
如果AUC高但KS低,说明模型整体排序不错但范围内区分能力不集中,这对策略应用来说可能不够。如果KS特别高,比如超过0.75,反而要警惕是不是特征穿越或者目标泄漏了。正常信贷逻辑回归的KS在0.35到0.55之间就算相当不错。我在模型效果评审时一般同时看KS、AUC和Gini系数,三者一致性才算模型稳健。
这里还有一个小技巧:评估的时候按预测分数分箱,逐箱对比实际违约率与预测违约率。理想情况下,分数越低的箱,实际违约率越高,而且违约率应单调递增。如果某个箱位实际违约率明显偏离,说明这个分数段可能混入了特殊客户,要回头检查特征,不能只看整体指标就放行。
4.3 阈值不是0.5,是算出来的
很多人拿到模型输出的概率之后,直接默认大于0.5就是违约,小于0.5就是好客户。但在贷款业务里,0.5这个阈值几乎从来不是最优解,因为违约事件很少,真实违约率可能才3%,模型输出的违约概率分布整体都偏低,0.5阈值会拒绝掉几乎所有人。
正确做法是画一张代价矩阵。把客户分成四类:实际好预测好(正确放行)、实际坏预测坏(正确拒绝)、实际坏预测好(漏放损失)、实际好预测坏(误拒损失)。误拒损失可以理解为“本来可以赚的利息收入”,漏放损失是“贷款本金损失”。两者不是等价的,通常漏放的代价是误拒代价的数倍。所以阈值要选在使总期望损失最小的位置。
我在某项目里做阈值选择时,计算了不同阈值下的期望损失曲线,发现最优阈值大约在0.08附近,而不是0.5。这个数字意味着我们只把预测违约概率超过8%的客户拒绝掉,剩下的客户进入人工审批或降低额度。业务方刚开始觉得8%太低,直觉上认为“这等于在乱拒”,但看到期望损失对比之后,他们接受了——这就是数据说话的力量。
4.4 概率校准怎么做才靠谱
模型训练时用了下采样,或者训练样本的违约率和线上真实违约率差得远,概率输出就不能直接用,要校准。除了前面提到的调整公式,还有一种常用方式是做Platt Scaling:在训练好的逻辑回归输出上再套一个逻辑回归,用验证集拟合出真实违约率与原始分数之间的映射。简单说,你有一个分数s,真实违约率的估计就是1 / (1 + exp(a + b×s)),其中a和b都是通过验证集估计的。
我在实际项目里发现,下采样校准后,再用验证集做一次平滑调整,线上KS几乎不掉,而校准后的概率可以直接用于额度定价。这一步虽然额外花时间,但属于“以后不会再翻车”的投资。忽略校准的模型上线后,业务方发现10分和100分额度定价对应的实际违约率完全对不上,那才是最头疼的事。
5. 从模型到评分卡:分数换算与业务落地
5.1 一个公式把概率变成评分
业务人员不习惯跟概率打交道,他们更习惯看到一个300分到900分之间的分数,分数越高风险越低。逻辑回归到标准评分卡有固定公式。把模型的线性输出记为ln(odds),其中odds是好客户概率与坏客户概率之比,即p/(1-p)。设定两个业务参数:
- 基准分base:当odds为某个设定值时对应的分数,比如设置odds=19(即5%坏率)时分数为600分;
- PDO(Points to Double the Odds,odds翻倍对应分数增量):一般设20或30,意思是odds每翻一倍,分数增加20分。
这样每个客户的分值就是:
Score = base + factor × ln(odds)
其中factor = PDO / ln(2)。算出每个特征对应各WOE箱位的分数,就是把回归系数乘以factor再乘以对应WOE,最后全部加起来再加上基准分。标准化之后,整个评分卡的每个分数都是一个具体可解释的业务动作依据,客户经理一眼就能看出来“这个人在年龄上减了32分,在征信查询上减了58分”。
5.2 分数分箱后要跟策略联动
评分卡通常不是直接用连续分数,而是分档。我当时把模型输出的分数分成了A、B、C、D、E五档,每档对应不同的审批策略:
| 评分档位 | 分数范围 | 策略动作 |
|---|---|---|
| A | 720以上 | 自动通过,标准定价 |
| B | 660-719 | 自动通过,降低额度 |
| C | 600-659 | 拒贷或人工审批 |
| D | 540-599 | 拒贷,可复议 |
| E | 540以下 | 直接拒绝 |
这个分档不是拍脑袋定的,是基于各分数段的实际违约率和客群价值测算出来的。比如720分以上客户群的年化违约率只有0.8%,完全可以给低利率额度;600分以下的客群违约率超过15%,即使提高利率也很难覆盖损失,最好不做。
5.3 评分卡的局限和人工兜底
评分卡只能给出一个量化判断,但它不能覆盖所有情况。某些客户可能因为近期突发重大疾病、失业等特殊情况,评分不高但未来还款意愿强烈。所以我的策略里通常保留一个复议通道:客户被拒后可以提交补充材料,人工审批员根据规则复核。
这里要特别提醒:人工复议的比例不能太高,否则审批标准失去一致性,评分卡形同虚设。我当时设定的复议占比上限是5%,也就是说95%的申请完全由模型决策,5%以内留给人工处理特殊情况。这样既保留了模型的客观性,也给了业务必要的人性化空间。
6. 上线不是终点:PSI监控与模型衰退
6.1 PSI是模型稳定性的体温计
模型上线后最怕的不是准确率下降,而是客群漂移。今天进来的客户和三个月前进来的客户,如果特征分布已经悄悄变了,模型再用旧数据训练时的决策逻辑来打分,结果一定会失真。衡量这种分布漂移的标准指标是PSI(Population Stability Index,群体稳定性指标)。
PSI计算方式是:把训练样本的分数分布当成预期分布,把当前月线上客群的真实分数分布当成实际分布,按分数分箱后计算累计差异。经验阈值是:PSI小于0.1说明群体稳定;0.1到0.25说明有漂移,需要关注;大于0.25说明群体结构显著变化,模型必须重新训练或进行切换。
6.2 线上监控要盯的不只是模型指标
除了PSI,我还会按月监控线上审批客群的实际逾期表现,看训练时的违约率和线上实际违约率是否一致。如果线上LGD前几个月的累计违约率和模型预测的违约率偏离超过了1.5倍,就要立刻排查原因:是外部经济环境变化,还是渠道调整引入了新客群,或者系统取数逻辑出了bug。
实际案例里最常见的原因往往不是模型本身变差了,而是特征口径变了。比如某个月换了征信数据源,某类字段从A库切到了B库,导致WOE表现完全不同。我经历过的某次线上KS从0.45掉到0.32,最后排查出来是因为数据供应商升级了接口,一个字段的缺失表达方式变了,大部分客户该字段被填充成一个默认值。这种事不亲自查一遍很难发现。
6.3 模型重训不是越频繁越好
对逻辑回归来说,重训需要谨慎。频繁重训会导致决策标准不稳定,今天能用这个客户,明天因为重训后参数微调被拒了,这会直接影响客户体验。实践中我一般设置3个月一次定期重训,但如果PSI持续走高,就提前触发重训。另外,每次重训之后要保留旧评分卡和新评分卡在相同样本上的分数差异分析,如果两类客户大量换挡,说明模型结构已经发生了结构性变化,要评估是不是某些特征的系数方向都翻转了。
我习惯在每次上线前保存一份线下校准数据,包括验证集的预测概率、真实标签和分数分箱,用于下一次模型迭代时的对照组。这样一旦线上出现不同于预期的表现,回头对比历史数据就能快速定位是特征偏移、数据质量问题还是模型本身衰退,而不是从头猜。
个人贷款违约预测模型用逻辑回归做到这里,其实已经形成了一套完整的生命周期管理。相比那些追求新模型架构的做法,我更愿意把精力花在样本窗口、特征分箱、概率校准和监控机制这些“看不见的地方”。这些环节才是真正决定模型能不能长期稳定赚钱的部分。如果你刚开始做这个方向,我的建议很简单:先把逻辑回归从头到尾做扎实,它会教会你信贷风控里所有最重要的逻辑。