3. 混淆矩阵与核心指标:TP/FP/TN/FN、准确率、精确率、召回率、F1-score、特异度

在风控模型阈值调优中,混淆矩阵是评估分类模型性能的基础工具。它通过比较模型预测结果与实际标签,将样本划分为四种基本类型。理解这些核心指标,是后续设定最优告警阈值的数学前提。

3.1 混淆矩阵四象限

对于二分类风控模型(如“好客户” vs “坏客户”),混淆矩阵以实际类别为行、预测类别为列,形成 2×2 矩阵:

实际 \ 预测 预测为正(告警) 预测为负(非告警)
实际为正(坏客户) TP(真正例) FN(假负例)
实际为负(好客户) FP(假正例) TN(真负例)
  • TP(True Positive):模型正确告警的坏客户,命中风险。
  • FN(False Negative):模型漏过的坏客户,未触发告警,风险最高。
  • FP(False Positive):模型误告警的好客户,产生骚扰,增加人工成本。
  • TN(True Negative):模型正确放行的好客户,正常通过。
风控视角:FN 代表“漏报”,FP 代表“误报”。在信贷风控中,FN 的成本通常远高于 FP,因为一笔坏账可能抵消数百笔正常交易的利润。
混淆矩阵四象限结构图 混淆矩阵四象限结构图 TP TP 真正例(正确告警) FN 假负例(漏报) FP 假正例(误报) TN 真负例(正确放行) 实际正 实际负 预测正(告警) 预测负(非告警) FN(漏报)> FP(误报)> TP > TN 在风控中的成本权重 阈值调优本质是在 TP 与 FP 之间做权衡

3.2 核心指标定义与计算

基于混淆矩阵的四类计数,可以衍生出多个评估指标。以下为风控场景中最常用的六个指标:

指标名称 公式 风控含义 理想方向
准确率(Accuracy) (TP + TN) / (TP + FP + FN + TN) 整体预测正确的比例 越高越好
精确率(Precision) TP / (TP + FP) 告警中真正坏客户的比例(告警准确度) 越高越好
召回率(Recall) TP / (TP + FN) 坏客户被成功告警的比例(捕获率) 越高越好
F1-score 2 × (P × R) / (P + R) 精确率与召回率的调和平均 越高越好
特异度(Specificity) TN / (TN + FP) 好客户被正确放行的比例 越高越好
假正率(FPR) FP / (FP + TN) = 1 - Specificity 好客户被误告警的比例 越低越好
关键理解:准确率在样本不平衡时具有欺骗性。例如,当坏客户仅占 1% 时,模型全部预测为“好客户”也能获得 99% 准确率,但此时召回率为 0%,模型完全失效。风控场景必须关注精确率与召回率的平衡。

3.3 阈值对指标的影响

模型输出的原始分数(如违约概率)需要通过阈值转换为二分类标签。阈值的高低直接影响混淆矩阵的分布:

  • 降低阈值:更多样本被判定为正(告警),TP 和 FP 同时增加,FN 减少,TN 减少。召回率上升,精确率下降。
  • 提高阈值:更少样本被判定为正(告警),TP 和 FP 同时减少,FN 增加,TN 增加。召回率下降,精确率上升。

阈值调优的核心目标,是在业务容忍度范围内找到最优平衡点。例如,在反欺诈场景中,通常要求召回率 > 95%,同时尽可能控制误报率。

阈值变化对核心指标影响示意图 阈值变化对核心指标影响示意图 阈值(Threshold) 指标值 低 高 召回率 ↑ 精确率 ↓ F1-score(最优) 最优阈值 F1-score 最高点通常对应精确率与召回率的最佳平衡

3.4 风控场景指标选择策略

不同风控业务阶段对指标的侧重不同,以下为常见场景的推荐策略:

业务场景 首要指标 次要指标 阈值倾向
反欺诈实时拦截 召回率(Recall) 精确率(Precision) 较低阈值,宁可误报不可漏报
贷前信用审批 精确率(Precision) F1-score 较高阈值,避免误杀优质客户
贷中监控预警 F1-score 特异度(Specificity) 平衡阈值,兼顾捕获与误报
营销响应模型 精确率(Precision) 提升率(Lift) 较高阈值,精准触达
常见误区:不要盲目追求 F1-score 最大化。当业务对 FN 和 FP 的成本权重差异较大时(如欺诈损失是误报成本的 100 倍),应使用加权 Fβ-score 或直接优化业务成本函数,而非标准 F1-score。

3.5 代码示例:计算混淆矩阵与核心指标

以下 Python 代码演示如何基于模型预测概率和阈值,计算混淆矩阵及各项指标:

import numpy as np
from sklearn.metrics import confusion_matrix

# 模拟真实标签与模型预测概率
y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 1, 0])
y_prob = np.array([0.85, 0.32, 0.72, 0.91, 0.15, 0.45, 0.60, 0.22, 0.78, 0.08])

# 设定告警阈值
threshold = 0.5
y_pred = (y_prob >= threshold).astype(int)

# 计算混淆矩阵
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()

# 计算核心指标
accuracy = (tp + tn) / (tp + fp + fn + tn)
precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0
f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0.0
specificity = tn / (tn + fp) if (tn + fp) > 0 else 0.0

print(f"阈值: {threshold}")
print(f"混淆矩阵 -> TP: {tp}, FP: {fp}, FN: {fn}, TN: {tn}")
print(f"准确率: {accuracy:.4f}")
print(f"精确率: {precision:.4f}")
print(f"召回率: {recall:.4f}")
print(f"F1-score: {f1:.4f}")
print(f"特异度: {specificity:.4f}")

输出示例:

阈值: 0.5
混淆矩阵 -> TP: 4, FP: 1, FN: 1, TN: 4
准确率: 0.8000
精确率: 0.8000
召回率: 0.8000
F1-score: 0.8000
特异度: 0.8000