简介这份PDF文档聚焦数据回归中的定序回归模型面向金融风控、信用评分方向的学习者与从业者帮助理解如何用统计建模方法解决信用卡用户信用评级与违约风险识别问题。资源共1个PDF文件压缩包约447KB内容以论文形式组织涵盖信用评级对信用卡业务的重要性、数据集介绍与探索性分析、定序Probit模型介绍、模型拟合、自变量选择及结论等章节并附参考文献与致谢结构完整、便于按章节研读。目前已有323人学习下载。读者可从中掌握定序Probit回归的建模流程理解信用评级量化思路并借助文中对特定数据集的分析识别影响持卡人违约的主要因素为信用卡发放机构评估信用风险、降低违约损失提供方法参考适合作为信用评分入门与实证写作的参考材料。1. 定序回归做信用卡信用评级为什么它比二分类更贴近真实业务信用卡用户的信用评级绝大多数人第一反应是「违约/不违约」的二分类问题。但真实业务里银行给用户打的标签往往是「AAA、AA、A、BBB、BB、B」这样的等级序列或者至少是「优、良、中、差」四档。这些等级之间是有顺序的AAA 比 AA 好AA 比 A 好但「AAA 和 AA 的差距」并不等于「BB 和 B 的差距」。如果你直接套一个二分类模型或者用普通多分类 softmax 去拟合就把「有序」这个信息丢掉了模型学出来的边界会明显偏。定序回归Ordinal Regression就是专门吃这类标签的它假设存在一个潜在的连续变量——可以理解为「真实信用分」——你观测到的等级只是这个连续变量被若干阈值切出来的结果。信用卡信用评级这个场景天然适合定序回归因为评分卡背后的逻辑本来就是「分数落在哪个区间就是哪个等级」。这篇文章面向的是想把这个模型真正落地到信用评级里的工程师和数据分析师从数据准备、模型选型、参数设置到踩坑排查一步步讲清楚。读完你至少能拿一份带等级标签的信用卡数据跑出一个可解释、可复现的定序回归评级模型并知道它和 Probit、Logit、RVM 这些常见工具之间的关系。2. 定序回归的模型形式与信用卡评级场景的对应关系2.1 潜在变量框架把「信用分」当成看不见的连续变量定序回归的核心是一个潜在变量模型。设第 i 个用户有一个不可观测的连续信用倾向 y_i^*它由特征线性组合加噪声构成y_i^* x_i^T β ε_i你观测到的等级 y_i 取 1 到 K比如 1差2中3良4优规则是y_i k 当且仅当 α_{k-1} y_i^* ≤ α_k其中 α_0 -∞α_K ∞α_1 α_2 … α_{K-1} 是待估的切点thresholds。噪声 ε_i 的分布决定了模型类型取标准正态分布就是定序 Probit取逻辑分布就是定序 Logit。信用卡评级里我一般优先用 Probit因为信用评分领域大量经验表明正态潜变量假设和实际评分分布拟合得不错而且 Probit 的系数在经济解释上更接近「标准差变化」。这个框架最大的好处是你得到的不是一堆孤立的分类边界而是一条连续的信用倾向轴切点就是评级的分档线。业务方问「为什么这个用户是 A 不是 AA」你可以直接回答「他的潜在信用分落在 α_2 和 α_3 之间」这比黑箱模型的概率输出好解释得多。2.2 为什么不用二分类或多分类信息利用效率的差异很多人会想我把等级拆成多个二分类AAA vs 非 AAAAA vs 非 AA……不就行了这种做法叫「一对多」拆解问题在于每个二分类只用了部分信息而且各模型的分数尺度不一致最后合并时还得再校准误差会累积。普通多分类 softmax 更糟它把等级当成无序的类别模型可以自由地把「优」和「差」的边界画得比「优」和「良」还近完全违背业务常识。定序回归通过共享同一个 β 和单调递增的切点强制模型尊重顺序参数量也更少K-1 个切点 p 个系数在小样本信用数据上过拟合风险明显更低。信用卡评级数据通常几千到几万条特征几十个这个参数量优势很实在。2.3 与 Probit、RVM、高斯过程回归的关系热搜里出现的 Probit 模型其实就是定序回归取正态噪声的特例两者不是并列关系而是包含关系。RVM相关向量机多输出回归和高斯过程回归属于另一条技术路线它们直接对连续目标建模输出的是实数值。如果你手上的信用标签本身就是连续分数比如 300-850 的 FICO 分那用高斯过程回归或 RVM 做小样本预测是合理的但如果你拿到的是等级标签硬用回归去拟合等级数字1,2,3,4会隐含「等级间距相等」的假设这恰恰是定序回归要避免的。我的经验是等级标签用定序回归连续分数用高斯过程回归或 RVM两者不要混。下面这张表把几个容易混淆的模型放在一起对比。模型标签类型输出是否利用顺序典型场景二分类 Logit二值概率不适用违约/不违约多分类 Softmax无序多类概率否行业分类定序 Probit有序多类等级概率是信用评级定序 Logit有序多类等级概率是信用评级高斯过程回归连续实数值方差不适用连续信用分RVM 多输出回归连续实数值不适用小样本连续预测3. 用 Python 跑通定序 Probit 信用评级的最小流程3.1 数据准备等级标签的编码与特征处理假设你有一份信用卡数据字段包括年龄、月收入、负债收入比、逾期次数、查询次数以及一个等级标签 credit_grade取值是「差、中、良、优」。第一步是把等级映射成从 1 开始的整数并且确认顺序正确。这里有个容易翻车的地方很多人用 LabelEncoder它按字母或出现顺序编码可能把「优」编成 1、「差」编成 4顺序完全反了。必须手动映射。import pandas as pd import numpy as np # 读取数据假设是 csv df pd.read_csv(credit_users.csv) # 手动映射等级确保顺序差中良优 grade_map {差: 1, 中: 2, 良: 3, 优: 4} df[grade] df[credit_grade].map(grade_map) # 检查是否有未映射的标签 assert df[grade].notna().all(), 存在未映射的等级标签 # 特征列 feature_cols [age, monthly_income, debt_ratio, overdue_times, query_times] X df[feature_cols].values.astype(float) y df[grade].values.astype(int) # 标准化连续特征定序模型对尺度敏感 from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X) print(样本数:, X_scaled.shape[0], 特征数:, X_scaled.shape[1]) print(等级分布:, np.bincount(y)[1:])这段代码的关键点有三个。第一grade_map 的顺序必须和业务等级顺序一致这是定序回归的前提顺序错了后面全错。第二StandardScaler 对连续特征做标准化因为定序 Probit 的系数解释依赖于特征尺度不标准化的话不同特征的系数没法比较。第三打印等级分布如果某一档样本极少比如「优」只有十几条切点估计会很不稳定需要提前发现。参数上StandardScaler 默认按列减均值除标准差信用数据里月收入这类长尾特征可以考虑先做对数变换再标准化效果通常更稳。3.2 用 statsmodels 拟合定序 Probit 并读取切点Python 里做定序回归statsmodels 的 OrderedModel 是最直接的选择它同时支持 Probit 和 Logit。下面是最小可复现的拟合代码。from statsmodels.miscmodels.ordinal_model import OrderedModel # 拟合定序 Probitdistr 默认是 logit改成 probit model OrderedModel(y, X_scaled, distrprobit) res model.fit(methodbfgs, maxiter500, dispFalse) # 打印系数和切点 print(res.summary()) # 单独提取切点 thresholds res.params[-3:] # 4 个等级有 3 个切点 print(切点:, thresholds.values)逻辑说明OrderedModel 的第一个参数是观测等级 y第二个是特征矩阵 X。distrprobit 指定正态噪声如果写 logit 就是定序 Logit。fit 用 bfgs 优化maxiter 给 500 是为了防止小样本下不收敛。输出里前几个参数是 β 系数最后 K-1 个是切点。切点必须满足单调递增如果拟合出来切点顺序乱了说明数据有问题或者模型设定不对。参数方面method 可以换 newton 收敛更快但需要二阶导小样本下 bfgs 更稳。dispFalse 只是不打印迭代过程调试时可以设 True 看收敛情况。3.3 预测等级与概率把切点用起来拟合完模型预测新用户的等级本质是算潜在变量落在哪个切点区间。statsmodels 提供了 predict但理解它的输出对排查问题很重要。# 预测概率矩阵每行是一个用户每列是各等级概率 proba res.predict(X_scaled) print(前 5 个用户的等级概率:\n, proba[:5]) # 取概率最大的等级作为预测等级 pred_grade proba.argmax(axis1) 1 # argmax 从 0 开始加 1 还原 print(预测等级:, pred_grade[:10]) # 计算潜在信用分用于业务解释 latent_score X_scaled res.params[:-3] print(潜在信用分前 10:, latent_score[:10])这里 proba 的每一行加起来是 1列的顺序对应等级 1 到 4。argmax 得到的是索引加 1 才是真实等级。latent_score 是 x^T β它没有绝对单位但可以用来排序用户业务上可以把它线性映射到 300-850 的分数区间。注意 predict 默认返回概率矩阵如果你只要等级记得做 argmax。参数上如果想让预测更保守宁可把用户往低等级判可以对低等级概率加一个权重再 argmax这在风控里很常见。4. 参数设置、模型评估与常见踩坑排查4.1 切点初始化与收敛问题三个必调参数定序回归最容易出问题的地方是切点估计。statsmodels 默认用等距切点初始化如果数据分布严重不均优化可能卡住。我一般会关注三个参数method、maxiter、以及是否对切点加约束。method 优先试 bfgs不收敛再换 nmNelder-Mead后者慢但鲁棒。maxiter 至少给 500小样本给 1000。另外如果切点估计出来间距极小比如两个切点差 0.001说明对应等级样本太少考虑合并等级。下面是一个检查收敛和切点合理性的代码片段。# 检查收敛 print(是否收敛:, res.mle_retvals[converged]) # 检查切点单调性 th res.params[-3:].values print(切点:, th, 是否单调递增:, np.all(np.diff(th) 0)) # 如果切点间距过小提示合并等级 if np.min(np.diff(th)) 0.1: print(警告切点间距过小建议合并相邻等级或增加样本)这段代码在每次拟合后都该跑一遍。converged 为 False 时不要直接用结果先换优化方法或检查特征共线性。切点单调性是硬性要求不满足说明模型没学好。间距阈值 0.1 是我在信用数据上常用的经验值具体可以按业务调整。4.2 评估指标别只看准确率定序回归的评估准确率会低估模型因为它没利用顺序信息。更合适的指标是「相邻准确率」预测等级和真实等级差不超过 1 的比例和「平均绝对误差 MAE」。另外可以算一下每个等级的召回率看模型是不是把某档全预测成相邻档。from sklearn.metrics import mean_absolute_error, confusion_matrix mae mean_absolute_error(y, pred_grade) adjacent_acc np.mean(np.abs(y - pred_grade) 1) print(MAE:, round(mae, 3)) print(相邻准确率:, round(adjacent_acc, 3)) print(混淆矩阵:\n, confusion_matrix(y, pred_grade))MAE 衡量平均差几档相邻准确率衡量「大方向对不对」。信用评级里差一档通常可接受差两档以上就要警惕。混淆矩阵能看出具体是哪两档在混。参数上没有固定阈值但相邻准确率低于 0.8 时我会回去检查特征和切点。4.3 避坑与常见问题排查现象一模型把所有用户都预测成中间等级。原因通常是等级分布极不均衡中间档样本占绝大多数模型为了降低损失倾向于全猜中间。解决对样本加权或者合并极端小样本等级或者改用代价敏感的学习方式在预测时对少数档调高阈值。现象二切点估计为负或顺序颠倒。原因可能是特征里有强共线性或者某个特征和等级负相关但没做方向处理。解决先算特征和等级的 Spearman 相关系数把方向不一致的特征做反转再用 VIF 检查共线性VIF 大于 10 的特征删掉或做 PCA。现象三Probit 和 Logit 结果差异很大。这通常发生在样本量小且极端等级多的时候。原因是对噪声分布的假设敏感。解决两个都跑比较相邻准确率和 MAE选更稳的那个如果差异依然大说明数据量不够考虑用高斯过程回归做连续分数预测再切档。现象四预测概率全部接近 0.25。原因可能是特征标准化没做或者模型没收敛。解决确认 StandardScaler 已应用检查 converged 标志必要时增加 maxiter 或换优化器。现象五新数据预测报维度错误。原因是对新数据单独做了 fit_transform导致标准化参数不一致。解决标准化器只在训练集 fit新数据用同一个 scaler 做 transform保存 scaler 对象。5. 把定序回归接进评分卡阈值校准与业务落地的一个技巧模型跑通只是第一步真正落地到信用卡评级还要解决「切点怎么对应到业务分档」的问题。定序回归输出的切点是潜在变量尺度上的业务方要的是「多少分算优」。我的做法是先用模型算出所有用户的潜在信用分 latent_score然后按业务要求的各等级占比用分位数反推切点对应的分数。比如业务要求优占 10%、良占 30%、中占 40%、差占 20%那就取 latent_score 的 90%、60%、20% 分位点作为分档线。这样得到的分数区间既尊重模型排序又满足业务分布要求。下面是一个校准代码示例。# 按业务占比校准分档线 business_ratio [0.20, 0.40, 0.30, 0.10] # 差、中、良、优 cum_ratio np.cumsum(business_ratio)[:-1] # [0.2, 0.6, 0.9] cut_points np.quantile(latent_score, cum_ratio) print(业务分档线:, cut_points) # 把潜在分映射到 300-850 分 score_min, score_max 300, 850 score score_min (latent_score - latent_score.min()) / (latent_score.max() - latent_score.min()) * (score_max - score_min) print(信用分前 10:, score[:10].round(1))这段代码的关键是 cum_ratio 的计算业务占比是各档从低到高的比例累积后去掉最后一个因为 100% 对应最大值得到三个分位点。np.quantile 直接算出对应的 latent_score 值。然后线性映射到 300-850业务方就能看到熟悉的分数。参数上business_ratio 必须和等级顺序一致且加起来为 1。映射区间可以按公司标准改但一旦定了就不要频繁变否则用户分数会跳。还有一个进阶技巧定期用新数据重新拟合模型但切点不要每次都重估而是固定切点、只更新 β这样分数尺度稳定业务方不会觉得「同样的行为分数变了」。我一般每季度重估一次切点每月更新一次 β。这个习惯是从一次翻车经历里学来的早期我每次全量重估结果两个月的分数不可比风控策略全乱套。后来改成切点冻结、系数滚动才稳定下来。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?