本文是「风控PM记」系列文章之一,完整可见:系列文章。 持续更新中。
一、背景
风控策略同学在挖掘有效的风控规则时,常常需要基于业务经验去思考"哪几个特征组合起来能识别风险",这在特征组合的过程中会浪费大量时间。我们有没有什么方法能替代人工分析,直接得出策略组合呢?决策树就是其中一个选择,它可以自动化地挖掘大批量的策略组合。
通过决策树模型算法,我们可以提取准确率比较高的叶子节点,作为风控策略挖掘手段,替代或辅助人工,大大提高策略发现的效率和效果。
假设这样一条策略:
IF 征信逾期次数 > 1 AND 月收入 ≤ 3000 AND 负债比 > 0.5 THEN 拒绝
过去这样的规则靠策略同学人工凭经验组合特征、拉数验证、反复调优。当特征数量上升到几十上百个时,人力很难覆盖所有可能的组合,而实际有效的规则往往是 4-5 个字段的复杂组合,靠人拍脑袋想出来的概率很低。
二、决策树的核心理念
决策树本质上是一个自动学习出来的"追问流程"。它从全部数据出发,不断寻找一个问题把人群分成两半,让分出来的两组尽可能"纯"(要么好客户扎堆,要么坏客户扎堆)。
训练完成后,决策树是一棵二叉树。从根节点到每一片叶子的路径,就是一条 IF-THEN 规则。 一棵有 N 片叶子的树,就自动生成了 N 条候选策略。
决策树的生长过程
构建决策树是一个不断寻找最优特征进行划分的递归流程:
| 步骤 | 动作 | 说明 |
|---|---|---|
| 1. 计算指标 | 计算当前节点使用各项特征划分后的基尼系数(或信息熵) | 衡量划分后人群的"纯度" |
| 2. 选择最优 | 选择划分后基尼系数最小(纯度提升最大)的特征 | 让好坏客户尽可能分开 |
| 3. 分裂数据 | 按该特征的不同取值,将数据分裂成子节点 | 一分为二 |
| 4. 递归生长 | 对每个子节点重复上述过程,继续向下生长 | 直到无法再分 |
| 5. 生成叶节点 | 满足停止条件时停止分裂,确定最终预测结果 | 得到最终决策树 |
三、完整案例:信用卡审批策略生成
假设我们是一家银行,有 10,000 条历史客户数据,每条包含 3 个特征和"是否违约"标签,目标是自动生成一套审批策略。
场景设定
| 客户ID | 月收入 | 征信逾期次数 | 当前负债比(负债总额/资产总额) | 是否违约 |
|---|---|---|---|---|
| 001 | 2,500 | 0 | 0.25 | 否 |
| 002 | 8,000 | 1 | 0.45 | 否 |
| 003 | 1,800 | 3 | 0.55 | 是 |
| ... | ... | ... | ... | ... |
全局分布: 总样本 10,000 · 未违约客户 7,000(70%) · 违约客户 3,000(30%)
第 1 步:计算全局初始熵
熵值公式:H = -∑(pᵢ × log₂ pᵢ),衡量当前人群的"混乱度",熵越低越纯。
H(全局) = -(0.7 × log₂0.7 + 0.3 × log₂0.3)
= -(0.7 × (-0.5146) + 0.3 × (-1.7370))
= 0.8813
这个 0.8813 是基准线,后续所有划分都要和它比较,看谁能把熵降得最多。
第 2 步:分别尝试每个特征作为根节点
算法依次用"月收入""征信逾期次数""当前负债比"来划分数据,分别计算它们的信息增益(划分前熵 − 划分后熵),谁最大谁就是根节点。
① 尝试用"月收入"划分(最佳切分点 ≤ 3000)
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 3000 (A组) | 2,000 | 1,700 | 300 | 15.00% |
| > 3000 (B组) | 8,000 | 5,300 | 2,700 | 33.75% |
A 组熵 H(A) = -(0.85×log₂0.85 + 0.15×log₂0.15) = 0.6098
B 组熵 H(B) = -(0.6625×log₂0.6625 + 0.3375×log₂0.3375) = 0.9225
加权平均熵 = (2000/10000)×0.6098 + (8000/10000)×0.9225 = 0.85996
信息增益 = 0.8813 − 0.85996 = 0.02134
② 尝试用"征信逾期次数"划分(最佳切分点 ≤ 1 次)
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 1 次 (A组) | 6,500 | 5,500 | 1,000 | 15.38% |
| > 1 次 (B组) | 3,500 | 1,500 | 2,000 | 57.14% |
A 组熵 H(A) ≈ 0.6300
B 组熵 H(B) ≈ 0.9852
加权平均熵 = (6500/10000)×0.6300 + (3500/10000)×0.9852 = 0.7543
信息增益 = 0.8813 − 0.7543 = 0.1270
这个增益(0.1270)远大于"月收入"的增益(0.02134),说明"征信逾期次数"的区分能力更强。
③ 尝试用"当前负债比"划分(最佳切分点 ≤ 0.5)
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 0.5 (A组) | 6,000 | 4,800 | 1,200 | 20.00% |
| > 0.5 (B组) | 4,000 | 2,200 | 1,800 | 45.00% |
A 组熵 H(A) = 0.7219
B 组熵 H(B) = 0.9921
加权平均熵 = (6000/10000)×0.7219 + (4000/10000)×0.9921 = 0.8299
信息增益 = 0.8813 − 0.8299 = 0.0514
补充:切分点(比如"月收入 ≤ 3000")是怎么定出来的?
你可能会好奇:上面每个特征都说"最佳切分点是 XX",这个切分值本身是怎么找出来的?
其实选择切分点有多种方式 (等距分箱、等频分箱、卡方分箱、决策树自身的贪心搜索等),不同实现方式各有取舍。这里介绍其中最常见的一种 ------ 贪心搜索,拿"月收入"举例:
- 把所有样本按月收入排序(1500, 1800, 2500, 3000, 3200, 5000, 8000...)
- 在相邻两个值之间选一批候选切分点(比如取中点:1650, 2150, 2750, 3100, 4100...)
- 对每个候选切分点计算一次信息增益
- 选增益最大的那个作为该特征的最佳切分点
所以"月收入 ≤ 3000"不是拍脑袋决定的,而是算法在候选切分点中挑出来的、能让好坏客户分得最开的那个值。离散特征(如逾期次数)则直接把每个取值当候选切分点,道理是一样的。
实际工程中,面对海量数据还会做各种优化(比如先分箱缩减候选数量、增量式计算增益等),核心思路不变 ------ 都是"选一批候选点 → 挨个算一遍 → 选最好的"。
第 3 步:确定根节点
汇总三个特征的信息增益:
| 候选特征 | 最佳切分点 | 信息增益 | 排名 |
|---|---|---|---|
| 征信逾期次数 | ≤ 1 次 | 0.1270 | 1 |
| 当前负债比 | ≤ 0.5 | 0.0514 | 2 |
| 月收入 | ≤ 3000 | 0.02134 | 3 |
结论:选择"征信逾期次数 ≤ 1 次"成为根节点。
根节点把 10000 人分成两拨:
- 左子节点(逾期 ≤ 1 次):6,500 人,违约率 15.38%,熵 0.6300
- 右子节点(逾期 > 1 次):3,500 人,违约率 57.14%,熵 0.9852
第 4 步:递归分裂子节点
根节点确定后,算法在两个子节点内部重复上面的整个流程(计算当前熵 → 遍历特征和切分点 → 选增益最大的继续分裂)。
左子节点(逾期 ≤ 1 次)继续分裂
尝试 "月收入 ≤ 3000":
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 3000 | 1,500 | 1,380 | 120 | 8.00% |
| > 3000 | 5,000 | 4,120 | 880 | 17.60% |
信息增益 ≈ 0.0410
尝试 "负债比 ≤ 0.4":
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 0.4 | 3,500 | 3,220 | 280 | 8.00% |
| > 0.4 | 3,000 | 2,280 | 720 | 24.00% |
信息增益 ≈ 0.0520
对比结果:"负债比 ≤ 0.4"的增益更大,左子节点选择"负债比 ≤ 0.4"继续分裂。
右子节点(逾期 > 1 次)继续分裂
尝试 "月收入 ≤ 3000":
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 3000 | 500 | 320 | 180 | 36.00% |
| > 3000 | 3,000 | 1,180 | 1,820 | 60.67% |
尝试 "负债比 ≤ 0.5":
| 分组 | 样本数 | 好客户 | 坏客户 | 违约率 |
|---|---|---|---|---|
| ≤ 0.5 | 1,200 | 720 | 480 | 40.00% |
| > 0.5 | 2,300 | 780 | 1,520 | 66.09% |
计算后,"月收入 ≤ 3000"的增益更大,右子节点选择"月收入"继续分裂。
注意左右子节点选了不同的特征、不同的切分粒度(左边负债 ≤ 0.4,右边月收入 ≤ 3000)------ 这正是决策树"自适应粒度"的体现:同一特征在不同子集里,最优切分点可以完全不同。
第 5 步:停止条件
树不能无限生长,否则会过拟合(在训练数据上表现好,但拿到新客户就失效)。我们预设几条停止规则:
- 节点违约率 < 10% → 直接生成"通过"策略,停止分裂
- 节点违约率 > 60% → 直接生成"拒绝"策略,停止分裂
- 节点样本数 < 500 → 样本太少不可信,停止分裂
- 最大深度限制为 3 层
按照这些规则:
| 节点 | 违约率 | 样本数 | 决策 | 是否停止 |
|---|---|---|---|---|
| 逾期≤1 AND 负债≤0.4 | 8% | 3,500 | ✅ 通过 | 停止(<10%) |
| 逾期≤1 AND 负债>0.4 | 24% | 3,000 | ⚠️ 待定 | 继续生长 |
| 逾期>1 AND 收入≤3000 | 36% | 500 | ⚠️ 人工 | 停止(样本少) |
| 逾期>1 AND 收入>3000 | 60.67% | 3,000 | ❌ 拒绝 | 停止(>60%) |
"逾期 ≤ 1 AND 负债 > 0.4"这个中风险节点会继续用"月收入"分裂到第 3 层。
第 6 步:生成最终策略树

把每一片叶子的"根 → 叶"路径拼起来,就是一条 IF-THEN 规则:
| 策略ID | 规则 | 推荐决策 | 覆盖人群 | 预期违约率 |
|---|---|---|---|---|
| S1 | 逾期 ≤ 1 AND 负债 ≤ 0.4 | ✅ 自动通过 | 3,500 人 | 8% |
| S2 | 逾期 ≤ 1 AND 负债 > 0.4 AND 收入 ≤ 3000 | ⚠️ 转人工 | ≈1,500 人 | ≈22% |
| S3 | 逾期 ≤ 1 AND 负债 > 0.4 AND 收入 > 3000 | ❌ 拒绝 | ≈1,500 人 | ≈28% |
| S4 | 逾期 > 1 AND 收入 ≤ 3000 | ⚠️ 转人工 | 500 人 | 36% |
| S5 | 逾期 > 1 AND 收入 > 3000 | ❌ 拒绝 | 3,000 人 | 60.67% |
四、总结
本文小结
整个过程算法没有依赖任何人工经验或预设规则,纯粹通过数学计算,从数据中自动挖出了一套可解释、可执行的策略体系。回顾一下:
| 阶段 | 核心内容 |
|---|---|
| 第1步 | 计算全局初始熵 |
| 第2步 | 遍历所有特征,计算各切分点的信息增益 |
| 第3步 | 选择增益最大的特征作为根节点 |
| 第4步 | 对每个子节点递归重复"计算→比较→分裂"过程 |
| 第5步 | 应用停止条件(深度、纯度、样本量)防止过拟合 |
| 第6步 | 从根到叶提取路径,生成 IF-THEN 规则 |
决策树在风控中的核心定位是候选策略生成器,而非最终决策者。它主要应用于三类场景:新业务冷启动时快速生成底线规则、辅助策略同学挖掘人工难以想到的字段组合,以及满足强解释性需求(规则可直接转SQL上线,便于审计与监管)。
但其局限也很明显:容易过拟合、模型稳定性较差、贪心搜索策略难以保证全局最优,且单棵树规则同质化严重。
对此,常用优化方向包括采用随机森林或XGBoost丰富规则来源、特征采样提升多样性、规则合并去重建立规则库、结合业务专家进行合规Review,以及上线后通过A/B测试和效果衰减监控实现持续迭代。
决策树负责挖掘候选组合,而挑选、评估、上线与监控仍由人主导。
后续我们还会扩展其他自动化策略生成的方法。
风险小剧场
千里之堤,溃于蚁穴。
风险启示:风险的最大特征不是突然爆发,而是平时被当成"没事"的那些微小漏洞,在临界点上集体失控。