简介:汽车贷款违约风险预测是汽车金融风控的关键环节。这份基于大样本Logistic回归与零膨胀回归模型的预测模型文档,面向金融风控建模人员、信贷研究学者及汽车金融从业者,针对现有评分系统主观性强、缺少客观量化依据的问题,提供了完整的建模思路与实证样本分析方案。包体共1个docx文件,大小149KB,内容涵盖项目背景、立项依据、模型构建与修正流程,以及基于3万多个客户样本数据验证预测正确率的方法。目前已有247人学习浏览。文档详细展示了多元条件概率模型的建立过程,包括Logistic回归与零膨胀泊松回归的模型选型、参数修正和效果对比,并将违约概率预测值与真实值进行校验,目标是将预测正确率分别控制在75%和85%以上。适合需要借鉴汽车信贷违约概率建模方法、开展信用风险评估课题研究的读者作为参考模板。 刚做完一个汽车贷款违约概率预测的项目,数据量接近60万笔,模型用的是Logistic回归加零膨胀回归的双轨方案。这个项目做下来,最大的感受是:汽车贷款这种业务,违约率通常只有1%到3%,属于典型的“稀有事件”场景,常规的分类模型思路在这种数据上很容易失灵。今天把这个项目的完整思路、踩过的坑、模型细节全部盘一遍,给后面要做信贷违约预测的朋友做个参考。
1. 违约预测的“稀有事件”困境:为什么不能直接套Logistic
先看一组典型数据。汽车金融公司的存量贷款里,违约客户占比往往不超过3%,有些经营稳健的机构甚至能把M2+逾期率压到1%以下。这意味着,如果我们直接拿全量样本去训练一个Logistic回归,模型会非常“懒惰”——因为它只要把所有客户都预测为“正常”,准确率就能达到97%以上。
这种情况在学术上叫类别不平衡,在业务上叫稀有事件建模。很多人第一反应是用SMOTE过采样、欠采样,或者调高违约样本的权重。这些方法在中小样本上确实有用,但到了几十万甚至上百万级的大样本场景,数据量本身已经很大了,这时候过采样反而会破坏原始分布,导致概率校准失效。
我的处理思路是这样的:先承认“违约”是个稀有事件,然后把这个事实直接用进模型结构里,而不是靠采样技巧去硬掰。这里就引出了零膨胀回归模型的核心价值。它的基本思路是,把客户分成两类:一类是“结构上就不可能违约”的人群,另一类是“有可能违约”的人群。对于第二类人,再用Logistic回归去估计违约概率。
用大白话解释一下:就像预测一个病人会不会住院。大部分健康人群根本不会住院,你不需要对他们一一建模;真正需要预测的,是那些有基础疾病、处于风险中的人群。零膨胀模型做的就是这个分层:先区分“安全人群”和“风险人群”,再对风险人群做精细的违约概率估计。
这个思路在汽车贷款场景下非常契合业务直觉。一个全款比例高、历史征信干净、收入稳定的客户,在很长一段时间内几乎不存在违约可能;而一个首付低、负债率高、最近半年有多次信贷申请的客户,才是真正需要被模型“盯着”的对象。
但这里有个关键点:零膨胀模型并不是免费的午餐。它的“零膨胀项”本身需要变量去解释,也就是说,你得找到哪些特征能区分“安全人群”和“风险人群”。如果业务上没有这个区分逻辑,模型只会变成两个互相牵制的回归,反而比单一的Logistic还差。
2. 大样本场景下的数据处理:60万笔样本前的必要步骤
这个项目的原始数据是62万笔存量贷款,加了标签之后(逾期超过90天记为违约,即M3+口径),正负样本比大约是1:42。开始建模之前,我花了一周多的时间做数据清洗和特征工程,这里有几个环节值得展开讲讲。
2.1 清洗和过滤:不是所有数据都适合进模型
第一步是剔除带明显噪音的记录。比如贷款金额为0、客户年龄小于18或大于70、利率明显超出合理区间的(正常车贷年化利率一般在4%到15%之间,超过20%的要么是高息产品要么是数据错误)。这些记录占的比例不高,大约0.5%,但会干扰模型对连续变量的分箱效果。
还要处理重复申请和同一客户的多次贷款记录。汽车金融里存在“一车多贷”的情况,同一个客户、同一辆车,在不同机构申请了多笔贷款。这种记录如果都进训练集,会造成样本间的相关性,破坏模型的独立性假设。我的方案是:对同一客户ID只保留最新一笔贷款,或者按时间切片后做交叉验证。
2.2 特征工程:从原始字段到衍生变量
原始的信贷数据字段大概有40多个,包括:年龄、性别、学历、婚姻状况、单位性质、收入、首付比例、贷款金额、贷款期限、车型价格、利率、征信查询次数、已有贷款笔数、信用卡张数、近6个月逾期次数等等。
这些原始字段里,真正能直接用进模型的没几个。因为Logistic回归和零膨胀回归本质上都是线性模型,对输入特征的分布和尺度很敏感。如果不做变换,收入这个字段可能从3000到50000,而首付比例是0到1,两者的系数量级会差出4个数量级,模型优化会很困难。
我主要做四类衍生变量:
- 衍生为比率:月还款额/月收入(债务收入比DTI)、贷款金额/车辆评估价(LTV)、首付比例等。这些比率变量比绝对金额更稳定,也更有业务解释力。
- 分箱后WOE编码:对连续变量,先用等频分箱(一般是5到10箱),然后计算每个箱子的WOE(Weight of Evidence,证据权重)。公式是WOE = ln(好客户占比 / 坏客户占比)。再做单调性检查,如果不单调,调整箱的边界。
- 时序刻画:征信查询次数细分为近1个月、近3个月、近6个月、近12个月的查询次数。业务上,短期内密集查询往往意味着资金紧张,是强风险信号,但它的影响会随时间衰减,所以分窗口建模效果更好。
- 交叉变量:比如“高LTV且近期多次征信查询”这种组合,单个变量未必显著,但交叉后风险快速上升。
2.3 大样本下容易忽略的“时间穿越”问题
大样本项目最容易犯的错是“时间穿越”,也就是用未来的信息去预测过去的事件。比如,如果数据集里包含了客户的“当前负债率”,但这个负债率是建模时点的快照,而你和模特建的是三个月前的违约行为,那这中间的关系就是混乱的。
我的做法是严格按时间切片:用2022年1月到2023年6月的放款数据作为样本,观测窗口是放款后12个月,所以标签最早要到2024年6月才能完整生成。所有特征变量只用放款当时及之前就能拿到的数据,不允许透入任何“未来信息”。这一步虽然会损失一部分样本量(比如2023年下半年的放款因为观察期不够只能弃用),但换来的是模型的可信度和上线后的稳定性。
3. Logistic回归的建模细节:从业务逻辑到系数解读
讲完数据,进入模型部分。先说明为什么首选Logistic回归。在信贷风控这个行业,Logistic回归几乎是默认基准模型,原因很简单:可解释性极强。模型给出来的系数可以直接转成评分卡里的分数,监管审计时也能说清楚每一个变量的变化对违约概率的影响方向和幅度。
3.1 从线性回归到Logistic:为什么需要Sigmoid变换
普通的线性回归输出的是连续值,但违约概率必须落在0到1之间。Logistic回归的做法是,把线性组合 z = β₀ + β₁x₁ + ... + βₖxₖ 丢进Sigmoid函数:
p = 1 / (1 + e^(-z))
这个变换把线性部分的值域从负无穷到正无穷,压缩到0到1的开区间。当z趋向正无穷,p趋近1;z趋向负无穷,p趋近0;z=0时,p=0.5。实际操作中,我更习惯看log(odds),也就是 ln(p/(1-p)),因为它和特征变量之间是线性关系,模型系数可以直接解释为“该变量每变化一个单位,违约对数几率的变化量”。
用业务语言翻译一下:如果模型的LTV系数是2.8,意味着LTV每上升0.1(比如从0.7变成0.8),违约对数几率上升0.28,对应的违约概率也会相应上升。这个解释在风控评审会上非常有用,业务人员一听就懂。
3.2 变量筛选:逐步回归和IV值的取舍
变量不是越多越好。在我的项目里,从50多个候选特征里筛出了18个进入模型。
筛选分两步:先做单变量分析,计算每个变量的IV值(Information Value,信息值)。IV值小于0.02的变量基本没有预测力,直接淘汰;大于0.3的反而要小心,可能是过度拟合的征兆。在这个数据集里,IV值最高的几个变量是:征信近12个月查询次数(IV约0.21)、债务收入比DTI(IV约0.19)、车辆评估价(IV约0.15)。
做完单变量筛选,再做多变量回归,这时候主要看共线性和显著性。两个IV都很高的变量如果高度相关(比如“贷款金额”和“车辆评估价”,相关系数经常到0.8以上),只能保留一个。我的判断标准是看VIF(方差膨胀因子),VIF超过5的变量逐个去掉重跑模型,直到所有变量的VIF都低于5为止。
3.3 训练集/验证集/测试集:时间外验证才是硬道理
大样本建模时,我见过很多人随机抽样划分训练集和测试集,然后拿着看起来不错的AUC沾沾自喜。随机划分的问题在于:模型从中学习到了样本的结构性规律,但这个规律在时间维度上未必稳定。信贷业务的核心规律是“好时候的客户在坏时候会怎么样”,所以必须做时间外验证。
我的划分方式是:按放款月份排序,前70%的月份(2022年1月到2023年3月)做训练集,中间15%(2023年4月到2023年8月)做验证集,最后15%(2023年9月到2023年12月)做测试集。保证训练集和测试集在时间上完全不相交。这样得出的准确率才有实战参考价值。
实际测试结果,训练集AUC约0.78,测试集AUC约0.75。看起来只差了0.03,但这两组数字的含义完全不同:前者说明模型“记住了”训练数据的规律,后者才说明模型“能预测”未来新贷款的违约风险。
4. 零膨胀回归:一道数学题如何区分“安全人群”和“风险人群”
现在进入这个项目最特别的部分——零膨胀回归模型(Zero-Inflated Model)。为什么汽车贷款这么适合用零膨胀模型?因为前面已经提到了,绝大多数客户在正常还款周期内根本不会违约,这“大量存在的零违约事件”并不是随机产生的,而是源于客户本身的“结构性质”——他们无论经济状况如何波动,都会优先保证车贷还款(因为车是代步工具、离不开),所以这些零值不应该和真正的随机波动混在一起建模。
4.1 ZIP模型的两阶段结构:从概率公式看建模逻辑
零膨胀Logistic回归(Zero-Inflated Logistic Regression)的数学表达是两层混合:
首先,用一部分概率π表示“该客户属于结构上的安全人群(零膨胀项)”,那么会有1-π的概率表示“该客户进入风险人群”。对于进入风险人群的客户,再假设其违约概率是p(这个p由一个标准Logistic回归算出)。于是,整体违约概率的表达式为:
P(违约) = π × 0 + (1-π) × p = (1-π) × p
反之,P(不违约) = π + (1-π) × (1-p)
这里的关键在于π本身也是由变量决定的,通常再用一个Logistic回归去拟合π的对数几率。所以ZIP模型本质上包含两个回归方程:一个负责判断“是否属于安全人群”,另一个负责计算“进入风险人群后的违约概率”。
4.2 哪个模块该放什么变量:基于业务直觉的配置
实际操作中,两个模块用到的特征可以不同,这个自由度是ZIP模型相对标准Logistic最大的优势。在我的项目里,膨胀项(判断安全人群)用的核心变量是:工作单位类型是否为政府机关/大型国企、社保缴纳时长、公积金缴存记录。这些变量反映的是客户收入的长期稳定程度,几乎直接立判“安全”还是“风险”。
而风险人群里的违约概率模块,用的则是:LTV、近6个月征信查询次数、信用卡使用率、当前贷款笔数。这些变量反映的是流动性压力和杠杆水平,更适合刻画“有风险的人,风险到底有多大”。
这种分工让模型的每个部分都更清晰。标准Logistic回归强行把两类变量塞进同一个线性方程,等于让收入稳定性和资金压力互相牵制,常常导致收入变量的系数被稀释。而ZIP模型把这两类影响拆开处理,系数大小更符合业务直觉,模型的解释性上了一个台阶。
4.3 运行结果对比:ZIP模型在存量客户识别上赢了多少
在同样的时间外测试集上做对比:
- 标准Logistic回归:AUC 0.751
- 零膨胀Logistic回归:AUC 0.774
提升幅度约0.023,看上去不大,但在风控场景里,AUC每提升0.01对坏账率的压制作用都非常可观。更明显的变化出现在提升度曲线(Lift Curve)上:对预测违约概率最高的前10%客户,ZIP模型能抓到约35%的真实违约客户,而标准Logistic只能抓到约29%。这意味着,同样的催收资源,用ZIP模型定位客户,效率能提高两成以上。
另一个值得注意的差异是概率分布的形态。标准Logistic给出的违约概率预测值大部分集中在0.01到0.08之间,曲线很平滑;ZIP模型因为先做了一层“安全/风险”分流,预测概率呈现明显的双峰形态——“安全人群”的概率集中在接近0的位置,“风险人群”的概率覆盖较宽区间。双峰分布对后续人工复核和阈值设定很有帮助,因为你可以更自然地定义一个“高风险区间”。
5. 评分卡转换:把模型输出变成业务能直接用的分数
模型建完,终究要落地。信贷风控里最常用的落地形式是评分卡,把违约概率映射成一个整数分数,分数越高代表风险越低(注意方向和概率是反的)。
5.1 评分卡的计算:比你想的更简单
标准评分卡的转换公式是:
Score = offset + factor × ln(odds)
其中odds = p/(1-p),p是预测违约概率。offset和factor是通过两个假设反推出来的:设定当odds为某个基准值时对应的分数(比如odds=1/20时分数为600),以及odds翻倍时分数的增量PDO(Point-to-Double Odds,通常取20或50)。
这两个条件一设,factor和offset就能解出来。如果factor=20/ln(2)≈28.85,offset=600-28.85×ln(1/20)≈686.4。然后每个变量的每个分箱,都有一个对应的分数贡献:分数贡献 = -factor × βᵢ × WOEᵢ。把所有变量的贡献加起来再加offset,就是最终评分。
5.2 分数校准的重要性:概率是假的,排名是真的
这里要提醒一点:模型输出的违约概率本身,并不是绝对准确的“真实违约概率”。尤其用了零膨胀模型之后,由于有一个“结构安全人群”的先验分流,算出的概率已经带上了建模假设的色彩。所以不要直接把p=0.03解读为“客户有3%的概率违约”,而应该把评分或预测值当成排序变量用。
更准确的做法是,在模型输出后做一次概率校准(Probability Calibration)。我常用的方法是Isotonic Regression(保序回归),把模型输出的原始分数映射到真实的违约频率上。做完校准后的预测值,才能用于资产定价、准备金计提这类对绝对水平敏感的用途。
我的习惯是:区分度和排序能力看校准前的模型输出,绝对概率水平看校准后的结果。两者分开用,能避免很多不必要的业务冲突。
6. 过程中的坑与反思:哪些地方可能让你前功尽弃
最后写写这个项目踩过的坑,每一个都是真金白银换来的教训。
第一个坑是零膨胀项和风险人群项的正负号互串。ZIP模型里两个模块的标签设置很容易搞反。常规Logistic里“违约=1、正常=0”,但在ZIP的膨胀项里,“膨胀”代表的是“安全人群=1”。如果沿用惯性直接把违约标签喂进去,系数方向的解释就会完全颠倒。我当时在检查系数时发现“社保缴纳时长”的系数居然为正(越长越容易违约),排查了半天才发现是膨胀项的标签写反了。
第二个坑是WOE分箱的单调性问题。很多变量在分箱后的WOE不是单调的,比如年龄变量,25岁以下和45岁以上的违约率都偏高,中间年龄段偏低,呈U形分布。这种情况下直接用原始WOE进模型,Logistic的线性结构无法刻画这种非线性关系。解决办法是把年龄重新编码成到两个方向的距离变量:“距25岁的距离”和“距45岁的距离”,或者直接分成两个哑变量,让模型自己学。
第三个坑是样本外验证时忽略了逾期标签的“右截断”问题。信贷数据天然有生存分析的特征:早期放款的贷款,观察期长,违约暴露更充分;临近数据集截止日期放的款,还没来得及违约就被标成了“正常”。如果不做处理,测试集里的违约率会系统性偏低,模型AUC被错估。我的方案是只保留观察期至少满9个月的贷款,或者用一个时间权重去调整,具体做法看数据条件和业务容忍度。
第四个坑更加隐蔽:零膨胀回归模型在不同时间切片上,两个模块的最优变量组合可能会发生漂移。经济上行的时候,膨胀项(安全人群)的区分度很高;经济下行的时候,原本的“安全人群”也会开始违约,膨胀项的预测力下降。这提醒我,模型上线后不能一劳永逸,必须周期性地做变量稳定性监测,比如计算特征分布的PSI(Population Stability Index),PSI超过0.1就该预警,超过0.25就需要考虑模型重构了。
7. 模型上线后的监控要点:建模结束只是开始
模型不是交一版结果就完事了。上线后要建立一套监控报表,我建议至少包含三类指标:
第一类是区分度指标,按月重算AUC和KS(Kolmogorov-Smirnov统计量),看模型能不能持续把好坏客户分开。一旦连续三个月AUC低于0.7,就要触发排查。
第二类是校准度指标,按月统计每个分数段的真实违约率和预测违约率的偏差。尤其关注高分段,也就是模型认为“很安全”的那批客户,如果真实违约率持续高于预期,说明膨胀项的安全人群认定标准出了问题。
第三类是特征稳定性指标,对进入模型的每个变量计算PSI。重点关注征信查询次数和债务收入比这类对经济周期敏感的变量。如果模型的分数分布整体向高风险区间漂移,可能需要业务部门配合调整审批策略,而不是盲目调模型。
我在这个项目里做了个简单的时间序列跟踪表,每个月更新一次,持续观察了半年。期间发现“近3个月征信查询次数”这个变量的PSI从0.08升到了0.17,提示外部信贷需求正在快速升温,整个客群的风险结构在变差。这种信号比模型AUC变化来得更早,某种意义上,变量的稳定性监控比模型本身更重要。
汽车贷款的违约预测永远是一个持续迭代的工作。每一批新还款表现数据都在告诉我们,之前对客户风险的判断哪些是对的,哪些需要修正。把这套监控机制建立起来,哪怕模型本身不做频繁更新,业务决策也有了一根持续校准的标尺。
本文还有配套的精品资源,点击获取