cswork / 系统设计

第 27 章 / 共 57 章 · 约 5 分钟

ML 案例 4:支付欺诈检测

本页目录
  1. 1. 需求澄清
  2. 2. 问题形式化
  3. 3. 数据与特征
  4. 4. 模型
  5. 5. 训练与评估
  6. 6. 服务与监控
  7. 7. 回答分级
  8. 8. 不同级别的期望
  9. 章节测验

先花 10 分钟自己设计:需求、核心实体、API 和高层架构,各写几行。写完或者跳过之后,下面的讲解才会展开。

先写你的思路

只存在这台设备上;登录后会存进你的账号。

欺诈检测要在一笔支付的授权流程里,用几十毫秒判断它是不是盗刷。它和推荐、广告有三点明显不同:错误的代价不对称(漏掉一笔欺诈和误拒一个正常用户,损失完全不同),标签要等几周甚至几个月,以及对手会主动适应你的模型。

1. 需求澄清

功能需求

  • 对每笔交易实时给出决定:通过、要求额外验证(短信验证码、3-D Secure)、拒绝
  • 可疑交易进入人工审核队列
  • 给审核员和用户提供可以解释的拒绝原因

非功能需求

  • 规模:峰值 5000 笔/秒
  • 延迟:风控决策在 100 ms 以内(它在支付授权的关键路径上)
  • 高可用:风控挂了,不能让所有支付都失败

代价不对称:

  • 漏过欺诈:损失交易金额,加上拒付手续费
  • 误拒正常交易:损失这笔收入,用户可能从此流失
  • 人工审核:审核员的成本和延迟

2. 问题形式化

二分类,预测 P(欺诈 | 交易)。但最终输出的是决策,不是概率:

分数区间决策
低直接通过
中额外验证或人工审核
高拒绝

阈值按期望成本选,而不是固定为 0.5:一笔 5000 元的交易和一笔 20 元的交易,欺诈概率相同,处理方式也应该不同。阈值还可以按金额区间、商户类别分别设定。

规则加模型:已知的模式和合规要求(黑名单、单卡频次上限)用规则,生效快、好解释;模型负责从复杂特征里泛化。出现新的攻击时,先用规则止血,等模型重训后学会。

支付风控的实时决策链路
滚动到此处后加载图表…
图表可横向滚动,展开后可缩放查看。
查看图表源码
flowchart LR
  accTitle: 支付风控的实时决策链路
  auth["支付授权请求"] --> feat["取特征:频次计数、设备、图特征"]
  feat --> rules["规则引擎:黑名单、硬限制"]
  rules --> model["模型打分"]
  model --> policy["决策策略:按金额和成本选阈值"]
  policy --> approve["通过"]
  policy --> challenge["额外验证或人工审核"]
  policy --> decline["拒绝"]
  challenge --> outcome["验证与审核结果"]
  outcome --> labels["标签:审核结果、拒付、用户举报"]
  approve -.->|"30~90 天后的拒付"| labels

3. 数据与特征

标签来源:持卡人发起的拒付(chargeback,通常在交易后 30~90 天才到)、人工审核结论、用户举报。标签有两个麻烦:

  • 延迟:最近几周的交易,大部分标签还没“成熟”
  • 选择偏差:被拒绝的交易永远不知道它到底是不是欺诈,模型拒得越多,训练数据里越缺这一块

特征:

类别例子
交易金额、币种、商户类别(MCC)、线上还是线下、时间
频次(velocity)这张卡过去 1 小时 / 24 小时的交易笔数和金额、涉及的商户数和设备数
设备与网络设备指纹、IP 归属地与账单地址的距离、是否使用代理或 VPN
行为偏离金额相对这张卡历史水平的偏离程度、是否首次在这个商户消费
关系图与其他账户共用的设备、卡、邮箱、地址;所在连通分量里已知欺诈账户的比例

频次特征用流式计算(滑动窗口计数器)实时维护在在线特征库里;训练时必须按每笔交易发生时刻的值回放,不能用当天汇总后的数,否则就是数据穿越。图特征计算量大,通常定期离线计算后写入 KV 存储,用来识别团伙作案。

欺诈只占约 0.1%,可以对正常交易降采样,或者给欺诈样本加权,但评估必须在真实分布上做。

4. 模型

  1. 基线:规则加逻辑回归
  2. 主模型:GBDT(XGBoost、LightGBM)。表格特征上效果好,能处理缺失值,推理快,还能用 SHAP 给出每笔交易的主要原因,方便审核和解释拒绝
  3. 补充:图模型离线识别欺诈团伙;无监督的异常检测(比如孤立森林)发现还没有标签的新型攻击

最后由决策层把规则、模型分数和金额组合起来,按成本选择阈值。

5. 训练与评估

按时间切分,并且只用标签已经成熟的数据:比如用 4 个月前到 1 个月前的数据训练。最近一个月的标签还在陆续到达,不能当作“没有欺诈”。

离线指标:

  • PR-AUC
  • 固定误拒率(比如 0.5%)下的召回
  • 按金额加权的召回:抓住的欺诈金额占全部欺诈金额的比例
  • 总期望损失:在选定的阈值下,漏过的欺诈损失 + 误拒成本 + 审核成本

处理选择偏差:对一小部分本该被拒绝的低金额交易改为“额外验证”,验证是否通过就是标签,用它估计被拒交易里真实的欺诈比例。

上线:先跑影子模式(只打分不生效),对比新旧模型的决策差异;再在一小部分流量上做冠军-挑战者(champion-challenger)实验。拒付率是滞后指标,短期先看误拒率、审核队列长度和用户投诉。

6. 服务与监控

  • 频次计数器放在内存存储或流处理的状态里,每笔交易实时更新
  • 模型和特征服务都设超时;超时或故障时退回只用规则的保守策略,既不能让所有支付失败,也不能全部放行
  • 每次拒绝都记录原因代码(来自规则或 SHAP),用于审核和用户申诉

监控与对抗:

  • 分数分布和特征分布的漂移;某个特征突然大面积缺失
  • 每天的拒绝率、验证通过率、审核队列积压
  • 欺诈者会不断调整手法,模型效果会随时间衰减,通常每周重训;出现新攻击时先用规则快速封堵

7. 回答分级

目标与决策

  • Bad:输出一个阈值为 0.5 的分类结果,用准确率评估。
  • Good:通过、验证、拒绝三档决策;用 PR-AUC 和固定误拒率下的召回评估。
  • Great:按期望成本和交易金额选阈值;讲清规则和模型的分工;给出拒绝原因代码。

标签与特征

  • Bad:把最近的交易都当作有标签的数据,用当天汇总的统计量做特征。
  • Good:知道拒付标签有延迟,只用成熟的标签训练;设计频次、设备和行为偏离特征。
  • Great:频次特征流式维护,并按交易时刻回放;用图特征识别团伙;指出被拒交易没有标签的选择偏差,并用小比例的验证流量来估计。

上线与对抗

  • Bad:离线 AUC 涨了就全量上线,没有兜底。
  • Good:影子模式加冠军-挑战者实验,监控拒绝率和漂移。
  • Great:故障时退回规则的保守策略;规则快速止血,模型定期重训;按金额加权评估真实损失。

8. 不同级别的期望

级别期望
Mid(L4)在提示下给出二分类建模、主要特征和适合不均衡数据的指标,知道要实时决策
Senior(L5)主动处理标签延迟、频次特征的时刻正确性、按成本选阈值,以及影子模式上线
Staff(L6+)讨论对抗性和选择偏差、规则与模型的分工、故障兜底、可解释性与合规,以及误拒对用户和收入的长期影响

章节测验

6 道选择题
  1. 为什么欺诈检测的阈值不应该固定为 0.5?
  2. 训练模型时,最近一个月的交易应该怎么处理?
  3. “这张卡过去 1 小时的交易笔数”这类频次特征,训练时最容易犯什么错?
  4. 被模型拒绝的交易没有真实标签,这会导致什么问题?怎么缓解?
  5. 风控模型服务超时了,支付流程应该怎么办?
  6. 为什么欺诈模型需要定期重训,还要配合能快速上线的规则?

章节讨论

正在加载讨论…