深夜的小区监控室里,值班保安老李面前摆着 24 块屏幕。99% 的时间里画面一片平静,只有 1% 的时刻,一个黑影可能一闪而过——那是小偷。如果老李每五分钟写一次“一切正常”,他的“准确率”高达 99%,但一个贼也抓不到。这正是类别不平衡问题的写照:当少数类少到像大海捞针,模型很容易被海量的多数类“惯坏”,只会无脑说“正常”。 本文要讲的,就是教模型像老李一样学会分配注意力。两类核心方法:一类是代价敏感学习,从“损失权重”和“错误代价”入手,让模型重视稀有事件;另一类是 Focal Loss,它像一位因材施教的培训师,把训练重心从“已经学会的简单样本”移到“吃不准的疑难样本”上。我们会一步步拆解反比频率权重公式、代价矩阵、调制因子 gamma 与 alpha 的调参,最后用对比实验告诉你什么场景该选什么策略。
掌握这些方法,你就能在欺诈检测、罕见病筛查等场景中,用 F1 与 PR-AUC 讲出比“99% 准确率”更诚实的故事——这是 AI 从业者处理不平衡数据的核心竞争力。
可视化演示
展示类别不平衡分布、Focal Loss不同gamma调制曲线对比、代价敏感矩阵权重热力图。理解代价敏感学习与Focal Loss调参策略。切换模式查看不同机制。
本节配有交互动效(进入视口后自动加载,约 3KB)。
类别不平衡分布 多数类95% vs 少数类5%严重不平衡 反比频率权重:少数类获得19倍权重 w_i=N/(K·n_i) 加权后两类损失贡献趋于平衡
不平衡问题概述
老李值夜班时,面前 24 块屏幕,99% 的时间画面平静,只有 1% 的时间可能闪过小偷黑影。如果他偷懒,每五分钟写一次“一切正常”,他的“准确率”高达 99%——但安全主管一眼看出这份报告毫无价值,因为一个贼也没抓到。这就是类别不平衡的第一个陷阱:准确率会撒谎。
机器学习的分类器和老李一样。当多数类(平静画面)与少数类(小偷)比例悬殊,比如 99:1,模型只要无脑预测“多数类”就能拿到 99% 的准确率,但它对真正关心的少数类一无所知。这种问题叫类别不平衡,广泛存在于欺诈检测、罕见病诊断、异常检测等场景中。衡量不平衡常用的指标是失衡比 r,r 越大越危险。
面对不平衡,解决思路分三条:数据层面的重采样(过采样少数类、欠采样多数类)、算法层面的代价敏感学习(给少数类更高权重,或定义不同误分类代价)、决策层面的阈值移动。本文主线是代价敏感学习,旁及它与重采样的关系。评价模型也要从准确率转向 F1、PR-AUC 等指标,因为它们对少数类表现更敏感。
对老李来说,报告“一切正常”太容易了,难的是在 1% 的时间窗口里盯出黑影。不平衡问题的本质,就是让模型别被“平静的 99%”惯坏——先度量失衡比,再决定用什么策略。
- 多数类样本数$N_{\text{major}}$ 表示出现频率高的类别的样本个数,比如 9900 条正常交易。
- 少数类样本数$N_{\text{minor}}$ 表示出现频率低的类别的样本个数,比如 100 条欺诈交易。
- 比值计算将多数类样本数除以少数类样本数,得到失衡比。
- 失衡比含义$r$ 越大代表数据越失衡;r=1 是平衡数据,r=99 意味着少数类每出现 1 次、多数类出现 99 次。
类别权重反比频率
物业给老李定了新规矩:抓到一次小偷奖励 1000 积分,普通巡检记录不积分。理由是:越罕见的事件,做到一次的价值越高。反过来,如果盯一次平静画面就加分,老李会拼命刷平静画面的次数,反而忽略黑影——这正是多数类“训练信号”淹没少数类的机制。
类别权重反比频率把同一逻辑写进损失函数:每个样本对损失的贡献乘以一个权重,权重与该类样本数成反比。少数类样本稀缺,单条样本的损失被放大;多数类样本海量,单条样本被缩小。这样模型不再被多数类的“刷屏”带偏。在 sklearn 中,class_weight='balanced' 会自动按标准公式计算权重,也可以传入字典手动微调。
老李的积分规则执行了一阵,小偷确实抓得多了。但主管发现一个新问题:老李开始草木皆兵,把树叶摇动、猫影都当成小偷上报——误报变多。这说明“权重加分”只管让稀有事件被重视,却管不了“不同错误的不同代价”,于是物业决定升级手册:引入代价矩阵。
- 样本总量$N$ 是训练集中全部样本的个数,比如 10000 条交易记录。
- 类别数量$K$ 是类别总数,二分类时 K=2。
- 第 i 类样本数$N_i$ 是第 i 类的样本个数,少数类可能只有 100 条。
- 反比加权分母 $K \times N_i$ 越大权重越小,样本越少的类权重越高。
- 权重公式$w_i$ 即第 i 类每个样本在损失中的放大倍数,体现“越稀有越重要”。
代价敏感矩阵
物业的《安保手册》升级了:明确两类错误代价不同——漏报(小偷进来了没发现)扣 1000 元绩效,误报(虚惊一场)只扣 10 元。代价不对称,老李的决策自然要变:宁可多看几眼可疑目标,也不轻易放过。他把“判断为安全”的标准从“非常确定”降到“基本确定”,这就是决策阈值迁移。
代价敏感矩阵把“每种错误值多少钱”写成一张表。二分类中,C(0,1) 表示真实类别 0 被预测成 1 的代价(误报),C(1,0) 表示真实类别 1 被预测成 0 的代价(漏报),对角线为正确分类的代价(通常为 0)。模型的目标从“最小化错误数”变成“最小化总代价”,当 C(1,0) 远超 C(0,1) 时,最优决策阈值会左移,更倾向于预测正类。
有了代价手册,老李的误报多了,但漏报大幅减少——对小区安保来说,“虚惊一场”的 10 元远比“真丢了东西”的 1000 元划算。代价敏感矩阵解决的是“哪种错更贵”的问题;接下来,训练环节还有一个更高阶的问题:如何让模型把精力精确花在“难分样本”上?这就是 Focal Loss 的舞台。
- 代价矩阵元$C_{ij}$ 是真实类别 i 被判为类别 j 的代价,漏报和误报可以设不同值。
- 混淆计数$n_{ij}$ 是数据集中真实 i 被判成 j 的样本数,来自混淆矩阵。
- 双重遍历两个求和符号遍历 i 和 j 的所有取值组合,共四种情形。
- 累加总代价把四类情形的代价乘以数量全部累加,得到模型的总代价。
Focal Loss 原理
老李的培训师发现:老李对“大晴天、无人的画面”判断极准,这类样本练一千遍也提升不大;真正让他进步的是那些“路灯下模糊黑影、树叶遮挡”的疑难画面。培训师于是改了一套训练法:已经做对的简单场景降低训练强度,做错或不确定的疑难场景加大训练强度。Focal Loss 就是这套“因材施教”的损失函数。
标准交叉熵对所有样本一视同仁,大量易分样本(多为多数类常见样本)的损失累加起来,会把难得才出现一次的少数类信号彻底淹没。Focal Loss 在交叉熵上乘一个调制因子 (1-p_t)^γ:p_t 是模型对真实类别的预测概率,越接近 1 说明样本越“容易”,因子越小、损失被压得越狠;越接近 0 说明越“难”,因子接近 1、损失几乎不动。
用 Focal Loss 训练后的老李,不再对着空镜头傻看,而是紧盯着那些“说不准”的画面。他抓贼的效率再次提升,误报率还下降了。当然,这套“注意力调节器”有两个旋钮——gamma 和 alpha,该怎么拧,正是下一节的调参策略。
- 真实类概率$p_t$ 是模型对真实类别的预测概率,越接近 1 代表样本越容易分类。
- 交叉熵骨架$-\log(p_t)$ 是标准交叉熵项,预测越错损耗越大,但无法区分难易。
- 调制因子$(1 - p_t)^{\gamma}$ 随 p_t 增大而指数变小,把易分样本的损失压下去。
- 类别天平$\alpha_t$ 为正类样本取 α、负类样本取 1-α,平衡两类样本的损失贡献。
- 焦距参数$\gamma$ 决定调制强度,γ 越大易分样本被压得越狠,γ=0 时退化为加权交叉熵。
调参策略:gamma 与 alpha
培训师给了老李两个旋钮:旋钮 gamma 控制“对熟悉画面多快放下警惕”,旋钮 alpha 控制“对稀有事件的基础重视程度”。如果 gamma 拧得太大,老李对所有“看起来安全”的画面都爱答不理,连正常车辆进出都当可疑,误报爆炸;如果 alpha 调错方向,他压根不觉得小偷值得特别注意。
alpha 的物理意义是“正负类损失的天平支点”。按反比频率的思想初始化:把 alpha 理解为少数类样本的损失权重(多数类为 1-α),则令 alpha 等于多数类占比。当 r=99 时 alpha≈0.99,少数类与多数类的损失贡献比约 99:1,恰好抹平数量差距。注意:不同框架对 alpha 的指定对象不同(有的给正类、有的给补数),调参前务必先看文档确认。
调参顺序建议:固定 alpha 为上述起点,先扫 gamma,再固定最优 gamma 微调 alpha,最后在两者邻域做二维网格搜索。验证指标用 F1 与 PR-AUC,并划分与训练集同分布的验证集,防止过拟合。老李最终把 gamma 拧到 2、alpha 调到 0.25,监控室一片安静,但他心里有数:这是用“适度怀疑”换“不漏真贼”。调参没有银弹,只有带着验证指标反复试验——这正是下一节对比实验要做的事。
- 多数类数量$N_{\text{major}}$ 是多数类样本数,占比越大数据越失衡。
- 总样本数$N_{\text{major}} + N_{\text{minor}}$ 是所有样本数之和,作为归一化分母。
- 比例起点$\alpha$ 等于多数类占比,让少数类单样本损失获得近似反比的补偿。
- 范围与搜索$\alpha$ 落在 (0,1),以此为起点做网格搜索,并配合验证指标选择。
效果对比实验
季度考核时,物业把老李的四种值班策略轮番测试:佛系只看准确率、权重积分制、代价手册制、Focal 训练法。每种策略跑一个月,记录抓到的真贼数和误报次数。光看“大多数日子平安无事”的准确率没用,主管用 F1 分数——把“抓贼能力(召回)”和“不冤枉好人(精确)”捏在一起打分。
实验设计要点:同一份不平衡数据(如 95:5 或 99:1),同一基线模型,分别叠加五种方案——不做处理、类别权重反比频率、代价敏感矩阵与阈值移动、Focal Loss(alpha 与 gamma 网格搜优)、权重加 Focal 的组合。统一用 F1 与 PR-AUC 对比,兼顾训练稳定性。F1 的公式很简单,却比准确率诚实得多。
考核结果显示:在难例多、特征重叠大的数据上,Focal Loss 优于纯权重法;在类间可分、噪声少的数据上,权重法与代价矩阵已经足够。报告最后一行写着:没有一种策略包打天下——先度量不平衡度与代价比,再选方法,才是真正的“调参之道”。
- 精确率 P预测为正类的样本中真正为正类的比例,衡量“抓到的里面有多少真贼”。
- 召回率 R真实正类中被正确找回的比例,衡量“真贼里抓到了几个”。
- 调和平均$2 \times P \times R$ 除以 $P + R$,对低值更敏感,P 和 R 必须同时高。
- F1 对比实验中比较基线、权重、代价矩阵、Focal 各方案的 F1 与 PR-AUC,选出最优。
AI 应用场景
金融风控欺诈检测
阶段:模型训练与评估
解决的问题:欺诈交易占比常低于 0.5%,传统模型为守住整体准确率,把几乎所有交易判为正常,导致重大资金损失。代价敏感学习把“漏掉一笔欺诈”的代价设为远高于“误拦一笔正常交易”,再用 Focal Loss 聚焦那些伪装得像正常交易的难例,两者结合有效提升召回。
具体案例:某支付平台近 12 个月交易 5000 万笔,欺诈率 0.2%。建模团队先按反比频率设置 class_weight='balanced',召回率从 38% 提升到 62%,误报略增;随后引入代价矩阵(漏报代价 1000 元、误报代价 10 元)与 Focal Loss(gamma=2, alpha=0.25)联合训练,召回率达到 84%,每拦截 1 元欺诈的运营成本下降约 60%。
医疗影像罕见病灶筛查
阶段:模型训练与部署
解决的问题:肺结节 CT 中病灶像素只占整图的极小比例,属于像素级不平衡;且结节形态千差万别,很多难例与血管截面极像。Focal Loss 的调制因子天然适配密集检测场景,让模型把梯度集中在“像结节又不是结节”的边界样本上。
具体案例:某医疗 AI 团队训练肺结节检测模型,正负候选框比例约 1:2000。改用 Focal Loss(gamma=2)后,在保持每例两次假阳的条件下,结节检出灵敏度从 78% 提升到 91%;再用 alpha 按反比频率初始化并微调,跨院数据集上的 PR-AUC 提升 12%。
Python 演示
import numpy as npfrom sklearn.datasets import make_classificationfrom sklearn.linear_model import LogisticRegressionfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import classification_report def inverse_freq_weights(y): # 手动实现类别权重反比频率公式 classes, counts = np.unique(y, return_counts=True) n = len(y) k = len(classes) w = {} for c, cnt in zip(classes, counts): w[c] = n / (k * cnt) return w def focal_loss(p, y, gamma=2.0, alpha=0.25): # 用 numpy 实现 Focal Loss 核心计算 p = np.clip(p, 1e-7, 1 - 1e-7) pt = np.where(y == 1, p, 1 - p) at = np.where(y == 1, alpha, 1 - alpha) return -(at * (1 - pt) ** gamma * np.log(pt)).mean() X, y = make_classification(n_samples=2000, n_features=8, n_informative=5, n_redundant=0, weights=[0.95, 0.05], random_state=42)X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y) print('manual class weights:', inverse_freq_weights(y_train)) base = LogisticRegression(max_iter=1000)base.fit(X_train, y_train)print('baseline accuracy:', base.score(X_test, y_test))print(classification_report(y_test, base.predict(X_test), zero_division=0)) weighted = LogisticRegression(class_weight='balanced', max_iter=1000)weighted.fit(X_train, y_train)print('balanced-class-weight model:')print(classification_report(y_test, weighted.predict(X_test), zero_division=0)) prob = weighted.predict_proba(X_test)[:, 1]print('focal loss value on test set:', round(focal_loss(prob, y_test), 4))
w[c] = n / (k * cnt)反比频率公式:样本总数除以「类别数 × 该类样本数」,少数类获得更大权重。weights=[0.95, 0.05]制造 95:5 的不平衡二分类数据,模拟真实场景。train_test_split(..., stratify=y)分层采样,确保训练集和测试集都保留 5% 的少数类。LogisticRegression(class_weight='balanced', ...)让 sklearn 自动按反比频率给两类样本加权。classification_report(y_test, base.predict(X_test), zero_division=0)打印精确率、召回率、F1,观察少数类(标签 1)的真实表现。pt = np.where(y == 1, p, 1 - p)提取模型对真实类别的预测概率 p_t,Focal Loss 的核心输入。return -(at * (1 - pt) ** gamma * np.log(pt)).mean()Focal Loss 核心:交叉熵 × 调制因子 × alpha,再取均值。
常见误区
误区我只要在模型里加一行 `class_weight='balanced'`,不平衡问题就彻底解决了,后面不用再调别的。
正解反比频率权重只补“数量差”,补不了“难易差”和“代价差”。当漏报比误报贵得多,或者少数类样本特别难分时,光靠权重不够,还需要代价矩阵区分错误类型、用 Focal Loss 聚焦难例。就像老李只靠积分奖励抓贼,却控制不了误报率。
为何常见:一行代码的改动太省事,让人误以为问题到此为止,忽略了不平衡问题背后有多种成因。
误区gamma 调大,模型就更关注少数类、更关注难例,所以 gamma 越大效果越强。
正解gamma 过大会把易分样本的损失压到接近零,模型“只盯着怪样本”,在标签噪声大的数据上直接过拟合噪声,F1 反而下降。论文中常用 γ=2,实战建议按 [0, 0.5, 1, 2, 3, 5] 依次扫描,而不是一味调大。
为何常见:“越大越关注难例”的直觉很顺耳,容易让人忽略过度压制易分样本带来的副作用。
误区代价敏感矩阵就是把类别权重换了个写法,两者一回事,学一个就够了。
正解类别权重是给每个类一个放大标量,无法区分“误报”和“漏报”的相对代价;代价矩阵能表达四类预测组合各自的价格,信息量更大。当 C(0,1) 与 C(1,0) 的比值恰好等于权重比时,两者才等价,这只是特例。
为何常见:两者在数学上都表现为“给损失乘个系数”,形式太像,容易误判为同一种方法。
误区模型报告准确率 99%,说明效果已经非常好了,可以直接上线。
正解在 99:1 的数据上,全预测多数类就有 99% 准确率,但少数类召回率为零,等于一个贼都没抓到。要改用 F1、PR-AUC、召回率等对少数类敏感的指标,才能反映模型的真实能力。
为何常见:准确率是最直觉的指标,零学习成本;而 F1 和 PR-AUC 需要理解精确率、召回率的关系,初学者容易偷懒跳过。
误区任何不平衡任务,直接把损失函数换成 Focal Loss 就好,alpha 和 gamma 随便设个默认值。
正解Focal Loss 主要解决“难例/易例失衡”,它有两个超参必须配合调;数据本身噪声大时 gamma 要调小,甚至退回加权交叉熵。若类别可分性差,还应先做特征工程或重采样,损失函数不是万能的。
为何常见:论文效果截图太有说服力,让人忽视超参搜索和数据集前提,误以为换损失函数就能白拿提升。
面试题
Q1. 二分类中多数类占 99%,模型把所有样本都预测为多数类,准确率约是?
- A.约 50% 左右
- B.约 99% 左右← 正确答案
- C.约 1% 左右
- D.没有准确率
答案:B。多数类占 99%,模型全猜多数类时,猜对的就是那 99% 的多数样本,准确率约 99%。就像老李永远写“一切正常”,报告好看但一个贼也没抓住——准确率在极端不平衡下会撒谎,必须辅以 F1、PR-AUC 等指标。
Q2. 类别权重反比频率的核心思想是?
- A.给少数类更大权重← 正确答案
- B.给多数类更大权重
- C.所有类别权重相等
- D.权重与频率成正比
答案:A。反比频率的核心是“越少见的类别单样本权重越高”,用 N/(K×N_i) 放大少数类损失、缩小多数类损失,像物业给抓小偷的积分远高于普通巡检。B、D 方向相反,C 等于不做处理。
Q3. 权重公式 w_i = N / (K × N_i) 中的 N 表示?
- A.第 i 类样本总数
- B.数据中的类别总数
- C.所有样本总数← 正确答案
- D.特征维度数量
答案:C。N 是训练集全部样本的总数,K 是类别数,N_i 是第 i 类样本数。例如共 2000 样本、少数类 100 条,则少数类权重 = 2000/(2×100) = 10,单条少数类样本损失被放大 10 倍。A 是 N_i,B 是 K,D 与公式无关。
Q4. Focal Loss 中调制因子 (1-p_t)^γ 的作用是?
- A.平衡类别的样本数量
- B.压制易分样本损失← 正确答案
- C.加快模型收敛速度
- D.增加网络模型层数
答案:B。p_t 大表示样本易分,调制因子趋向 0,把易分样本的损失压掉,让训练“焦距”对准难例,如培训师不再反复练老李已熟透的场景。它不改变样本数量、不加速收敛、不改变网络结构。
Q5. Focal Loss 中 alpha 的主要作用是?
- A.控制易分样本压制
- B.平衡正负样本贡献← 正确答案
- C.调整模型学习速率
- D.控制特征正则强度
答案:B。alpha 通过正类取 α、负类取 1-α 调节两类样本对损失的贡献比,解决正负样本数量不平衡,是“损失天平”的支点。难易调制由 gamma 负责,学习率与正则化由优化器和权重衰减负责,与 alpha 无关。
Q6. 代价矩阵中 C(0,1) 的含义是?
- A.真实类别 0 判为 1 的代价← 正确答案
- B.真实类别 1 判为 0 的代价
- C.正确分类 0 得到的奖励
- D.模型训练中的损失值
答案:A。C(0,1) 表示真实类别为 0 却预测成 1 的代价,即“误报”;C(1,0) 才是“漏报”。物业手册里漏报扣 1000 元、误报扣 10 元,分别对应 C(1,0) 与 C(0,1)。B 方向写反,C 和 D 不涉及误分类代价语义。
Q7. Focal Loss 中 p_t 的含义是?
- A.模型预测错误的概率值
- B.模型对真实类别的预测概率← 正确答案
- C.样本属于多数类的预测概率
- D.模型输出置信度的阈值
答案:B。p_t 是模型对真实类别的预测概率:y=1 时取 p,y=0 时取 1-p。p_t 越大样本越“容易”,调制因子越小。它随模型输出连续变化,不是 0/1 硬标签,也不指预测错误的概率或某个固定阈值。
Q8. 以下属于代价敏感学习的方法有?
- A.类别权重反比频率← 正确答案
- B.代价敏感矩阵← 正确答案
- C.Focal Loss← 正确答案
- D.随机欠采样
答案:ABC。类别权重、代价矩阵、Focal Loss 都从“损失/代价”层面补偿少数类,属于代价敏感学习;随机欠采样属于数据层面的重采样方法,不改损失函数,而是直接改变训练样本分布,因此不属于代价敏感学习。
Q9. 关于 Focal Loss 的 gamma 取值,说法正确的有?
- A.gamma 等于 0 时退化为普通交叉熵← 正确答案
- B.gamma 取值越大对易分样本压制越强← 正确答案
- C.常用范围一般在 0 到 5 之间← 正确答案
- D.gamma 取值越大模型效果必然越好
答案:ABC。γ=0 时调制因子恒为 1,Focal Loss 退化为加权交叉熵;γ 增大对易分样本压制增强,常用 0~5,论文里 γ=2 表现好。但 γ 过大模型过度忽略易分样本,在噪声数据上 F1 反而下降,D 的“必然越好”过于绝对。
Q10. 极端不平衡场景下,适合用来评估模型的指标有?
- A.F1 分数与 PR-AUC← 正确答案
- B.召回率与精确率权衡← 正确答案
- C.整体分类准确率
- D.平均精度 AP 值← 正确答案
答案:ABD。F1、PR-AUC、召回率与精确率的权衡、平均精度 AP 都对少数类敏感,能反映模型抓少数类的能力。准确率在极端不平衡下会虚高——全猜多数类也有 99%,掩盖模型“一个少数类都抓不到”的事实,因此不适合作为主要评估指标。