数据分析样本不均衡,怎么处理样本问题
在做信贷逾期预警模型时,我遇到一个典型场景:风险样本只占全部样本的1.8%。模型还没训练,团队里就有人建议把负样本复制几倍。我拦住了这个动作。样本不均衡看上去是一个数据预处理问题,但我后来意识到,它背后藏着业务定义、数据采集机制、模型评估和上线监控的多层问题。如果一上来就重采样,很可能得到一个纸面分数很高、上线后却失控的模型。下面是我在风控、流失预测、工业质检等项目中积累的判断框架和实战取舍。
先说核心结论:样本不均衡本身不是一个必须被“修正”的统计问题,而是一个决策问题。当业务只关心总体准确率时,不均衡可能不需要处理;当业务要精准识别少数类时,你要解决的是少数类在模型输出与真实决策中的错配关系。
我处理过的多数项目都遵循同一个流程:先定义业务损失矩阵,再分析少数类样本为什么少,接着用 PR-AUC 和业务阈值建立评估基线,最后在数据、算法、阈值和部署四个层面依次处理。这个顺序不能颠倒。
很多团队把样本比例拉平当成目标,其实是一种误导。真实场景中正负样本比例由客观世界决定,模型输出的先验也只是训练数据的先验。即使你把训练数据过采样到 1:1,模型给出的概率也未必校准。真正需要校准的是业务决策阈值。我的经验是:把“漏报成本/误报成本”作为第一优先级,样本比例只是影响损失函数的中间变量。
样本不均衡最常见的三个场景,我都在实际项目中碰到过。下面这三个例子,可以解释为什么没有一个统一样本处理方案。
2020年我在一个信贷反欺诈项目中做过申请评分卡。欺诈样本占比长期在 0.9% 左右,而且每隔几个月欺诈手法就会换一批。最开始团队用随机森林直接训练,发现模型几乎没有输出大于 0.5 的概率。后来把阈值降到 0.1,召回率也只有 23%,误报率却到了 18%。
真正的问题是欺诈样本与正常申请在“收入、金额、职业”这些传统字段上高度重叠。我们后来引入设备指纹和关联网络特征,才让 PR-AUC 从 0.18 升到 0.34。这个经验让我明白:样本不均衡的缓解不能只在采样层解决,特征空间的可分性才是前提。
另一个是某电信公司流失预警项目。流失用户占 3.2%,但流失事件与用户当前套餐、近期投诉次数强相关。最初用随机过采样,模型在验证集上召回率达到 0.27,可上线两周后每周的实时召回率波动巨大。
后来排查发现,过采样时把不同月份的样本混在一起,导致模型学到了“8月套餐用户流失”这种季节性伪规律。换成按月份分层的训练集,并只在训练集内部做 SMOTE 后,波动才降下来。时间序列数据中的随机过采样,会造成严重的数据泄漏。
在工业质检项目中,缺陷样本占比只有 2.5%,但缺陷又分为 20 多个子类,某些子类只有 30 多张图片。直接做 SMOTE 会在像素空间生成带伪影的图片,误检率反而升高。
我们最后拆成“先做正常样本的异常检测,再做缺陷子类分类”的两级结构,效果比任何重采样都好。这说明极端不平衡时,也许不应该把它当作二分类问题。
这三个场景说明:如果你只看到比例悬殊就开始复制样本,很容易忽略“样本少”背后的机制。可能是数据采集偏差、标注成本高,也可能是真实分布本身如此。不了解机制,处理方法就没有依据。

下面这五个误区,是我在模型评审中反复见过的。每一个都曾让项目付出额外成本。
复制少数类样本不会带来任何新信息,只会放大原有样本的噪声。如果少数类本身标注错误,复制会让错误权重成倍增加。过采样只能解决“模型看不到少数类”的问题,不能解决“少数类不可分”的问题。在信贷反欺诈项目中,我们对 200 条欺诈样本做过 10 倍过采样,结果模型在训练集上 F1 是 0.62,验证集只有 0.11。
准确率在多数类占 97% 时会严重失真。一个把所有人都预测为多数类的模型,准确率也能到 97%。AUC 看的是排序能力,但业务生产需要一个具体阈值。AUC 很高,不代表在业务阈值下少数类召回率可接受。

在电信流失案例里,我们把 3 月和 4 月的数据打乱后过采样,模型学到的是“月份”这个代理变量。真实部署时,5 月的新流失用户并没有被历史月份标记。正确做法是:如果数据有时间顺序,必须按时间窗口切分,并在每个训练窗口内部做采样。
少数类有 5000 条样本、特征维度 20,这叫不均衡,但不叫小样本。真正的小样本是每个类别只有几十条。对前者,重采样和阈值移动通常有效;对后者,需要迁移学习、异常检测或半监督方法。很多人没区分,导致用了过度复杂的方法。
SMOTE 在连续特征、类别重叠度低时效果不错,但在高维稀疏特征或 One-Hot 编码场景下容易产生无意义的插值样本。特征维度越高,近邻之间的“距离”越不可靠,合成样本的质量越差。如果业务特征以类别型为主,先用降维或目标编码,再考虑 SMOTE。
在决定使用哪种方法之前,我会先回答四个问题。这四个问题的答案决定了后续所有处理路径。
不要先问样本比例,先问一次漏报造成多少损失,一次误报造成多少损失。例如信贷风控中,漏放一个欺诈客户可能损失 2 万元,误拒一个正常客户的渠道成本是 200 元,损失比约 100:1。成本比越悬殊,阈值应该越偏向少数类。如果成本矩阵不知道,任何采样比例都是拍脑袋。
我把缺失机制分成三类,处理方式完全不同:
| 缺失机制 | 含义 | 示例 | 推荐动作 |
|---|---|---|---|
| MCAR | 样本是否缺失完全随机 | 用户留资信息偶发遗漏 | 可常规过采样/欠采样 |
| MAR | 缺失与已观测特征相关 | 被历史规则拦截的申请,观察不到坏结果 | 修正样本选择偏差,补充完整观测 |
| NMAR | 缺失与未观测因素相关 | 用户停止使用App,后续行为数据中断 | 引入外部数据或人工回访,不能只靠采样 |
如果两类样本完全可分,不均衡根本不影响分类。如果高度重叠,过采样和权重都只是辅助,必须增加特征。一个简单的验证方法:训练一个随机森林,看少数类样本的 OOB 或交叉验证召回率。如果召回率很低,先做特征工程,再谈采样。
对于有顺序依赖的数据,必须使用时间序列切分。随机分层采样会把未来的样本泄漏到训练集,导致上线后效果大打折扣。我通常要求验证集是“最近 N 天”,训练集是“之前的日子”,并且过采样只能在训练集内部发生。
这套判断逻辑,能避免你一头扎进采样参数调优。
2023 年我负责一个 B 端客户流失预警项目。样本总数 50 万,流失客户 1.4 万,占比 2.8%。业务动作是客户成功团队打电话挽回,漏掉一个流失客户相当于未来一年收入损失约 200 元,误判一个非流失客户带来 5 元短信成本和 1 分钟人工复核成本,错误成本比约 40:1。
验证集使用最近 30 天数据,避免未来信息进入训练。我们先建立逻辑回归基线,再对比四种处理策略:随机过采样、SMOTE、代价敏感学习,以及“阈值移动+特征重构+分层采样”组合策略。下表是脱敏后的结果,用于说明相对差异。
| 方法 | 精确率 | 召回率 | F1 | PR-AUC |
|---|---|---|---|---|
| 基线(不处理) | 0.18 | 0.12 | 0.14 | 0.21 |
| 随机过采样(5倍) | 0.25 | 0.22 | 0.23 | 0.28 |
| SMOTE | 0.28 | 0.26 | 0.27 | 0.31 |
| 代价敏感学习 | 0.12 | 0.35 | 0.18 | 0.27 |
| 阈值移动+特征重构 | 0.30 | 0.32 | 0.31 | 0.36 |
观察一:SMOTE 在离线指标上最好,但对“最近一周新流失的客户”召回率只有 0.19。原因在于,合成样本是在历史特征空间插值,而新流失客户的行为模式已经发生变化。
观察二:代价敏感学习把召回率推到 0.35,但精确率跌到 0.12。按业务成本计算,客服团队每天要处理大量无效回访,综合成本反而高于基线。追求单一指标,常常会毁掉业务 ROI。
观察三:过采样倍数在 4-5 倍时达到最优,超过后验证 AUC 和 F1 双双下降。过采样会让模型在训练集上记住少数类样本,但对时间演化后的新样本没有泛化能力。


没有普适方案,但有一个可复用的决策框架。我把情况分成五类,你可以按自己的样本比例和业务约束对号入座。
不需要重采样。先用原始数据训练,再用阈值搜索找到符合业务成本的分类阈值。如果两类错误成本差异大,可以在损失函数中加入类别权重。
这个区间内,随机过采样和 SMOTE 都能提升少数类召回率,但要注意过拟合。先用 3 倍 SMOTE,观察验证集 PR-AUC 是否下降;如果下降,改用代价敏感学习或类别权重。
这是最常用的区间。我建议先做特征工程,再用 EasyEnsemble 或 SMOTE+Boost 这类集成方法。模型投票后做阈值搜索,候选阈值为 0.2 到 0.5 之间的 5-10 个点。不要单用随机过采样,方差太大。
此时数据量足够大,建议在 XGBoost 或 LightGBM 中使用 scale_pos_weight 参数,效果通常比手动过采样好。同时可以训练一个孤立森林或自编码器做召回候选集,再用回归模型精排。
直接考虑异常检测或单类分类。二分类模型在几十条少数类样本上很难学到稳定边界。异常检测会产生异常分数,再通过人工规则圈定重点样本,比硬训练分类器更可靠。

如果样本带有时间戳,我要求训练集只能包含验证集之前的数据。过采样、SMOTE 都必须在训练集内部完成,不能把未来的样本复制到过去。上线后,还要监控“每周新样本少数类召回率”是否稳定。
当漏报成本大于误报成本时,不要只聚焦召回率。我通常先和业务方约定一个可接受误报率,比如“误报率不能超过 5%”。然后在这个约束下搜索阈值,找到最高的召回率。这样做比单纯调 class_weight 更贴近业务。
不要一上来就用复杂集成。先用逻辑回归或默认参数的 XGBoost,用 PR-AUC 评估;然后逐步增加采样、权重、特征工程。每增加一环都要确认验证集指标有实质性提升,否则就不加。
每一种方法都有成本、风险和适用边界。我的核心判断标准是:离线效果、上线稳定性和可解释性三者必须放在一起权衡。下面这个表是我常用的选型参考。
| 方法 | 实施成本 | 过拟合风险 | 可解释性 | 对分布漂移鲁棒性 | 适用场景 |
|---|---|---|---|---|---|
| 随机过采样 | 低 | 高 | 高 | 低 | 快速基线 |
| SMOTE | 中 | 中 | 中 | 中 | 连续特征、重叠度低 |
| 代价敏感学习 | 中高 | 中 | 低 | 中 | 业务成本可量化 |
| 阈值移动 | 低 | 低 | 高 | 中 | 已有模型、快速调整 |
| EasyEnsemble | 高 | 低 | 低 | 高 | 样本量大、比例极低 |
| 异常检测 | 高 | 低 | 低 | 中高 | 极端不均衡、标注较少 |
随机过采样虽然简单,但复制样本会增加训练集规模,导致训练时间变长,并让模型对复制样本分配过高的权重。如果后续要做特征重要性分析,还会出现“某些重复样本主导特征贡献”的假象。
SMOTE 在连续特征上效果好,但在高维稀疏特征或 One-Hot 编码特征上,容易在类别之间生成伪样本。所以使用前要降维,或者对类别特征做目标编码。
代价敏感学习需要业务成本矩阵足够精确,否则模型会把所有样本都推向“成本小”的类别。比如误报成本设定过低,模型会输出极低的异常概率,业务阈值失效。
阈值移动简单有效,但只在模型本身对少数类有较好排序能力时有效。如果模型把少数类全部排到很后面,调整阈值也没有用。
EasyEnsemble 通过训练多个欠采样模型并集成,减少了随机欠采样的方差,训练成本较高。生产环境同时跑多个模型,需要额外维护。如果你的团队已经有一套简单规则流程,不建议为了离线效果牺牲系统稳定性。
异常检测适合极端不均衡,但模型输出的是异常分数而非概率,业务人员接受度低,需要额外校准。同时,异常检测对规则解释性差,比如孤立森林很难说明“为什么这个客户是异常点”。

样本不均衡的处理不是一道数学题,而是一道业务题。你必须先搞清楚少数类样本为什么少,以及模型错误会造成什么后果,否则任何采样技巧都是隔靴搔痒。
如果你正在处理类似问题,我建议你按这一套动作走:第一,先做三类诊断,定义成本矩阵、分析缺失机制、选择正确的评估指标;第二,从最简基线开始,逐步叠加采样、权重、阈值和异常检测方法;第三,用时间切分的验证集和试点上线检验真实效果。
把离线分数和线上业务反馈连起来,你才能判断这轮“处理”到底有没有价值。下一次面对样本不均衡时,不要急着复制样本,先回答:你的决策目标是什么?少数类的缺失是怎样发生的?验证集是否真实反映了部署环境?这三个问题想清楚,方案会自动浮现。
最近在做一个信用卡欺诈检测项目,欺诈交易只占1%,我训练了一个分类模型,准确率达到99%,但老板让我提高召回率时我却发现模型把所有交易都判成了正常交易,根本抓不到欺诈。这让我很困惑,难道99%的准确率不是说明模型很好吗?样本不均衡时到底应该看哪些指标才能真实反映模型效果?
首先要明白,在正负比例极度悬殊时,准确率几乎完全由多数类决定。比如10000条样本中只有100条正例,即便模型永远预测为负类,准确率也是99%,这个指标没有提供任何关于少数类识别能力的信息。我的经验是:立即转向混淆矩阵、精确率、召回率、F1分数、AUC-ROC以及PR曲线。
对于业务来说,精确率和召回率往往更重要,因为它们直接对应误报和漏报的成本。场景精确率召回率业务解读 客服外呼低高抓得多但误伤多,会浪费人力 刑事侦查高低抓得准但可能漏掉线索 所以在评估时要先定义业务成本矩阵,把TP、FP、FN分别乘以实际成本,得出总代价,这个代价比任何单一指标都更能说服管理层。
千万别把准确率当成铁律,它只是参考。
我在做一个电商平台用户流失预测,流失用户占比只有8%。听说处理样本不均衡有三种常见方法:过采样、欠采样和SMOTE。我把每种方法都试了一遍,发现效果时好时坏,有时候过采样后模型过拟合很严重,有时候欠采样把所有重要信息都丢了。真的很纠结,这些方法到底有什么本质区别?在真实业务中要如何选择?
先说结论:没有万能方法,取决于数据量、噪声程度和业务成本。三种方法的本质区别在于如何调整训练样本分布:欠采样删除多数类样本,适合数据量大、多数类冗余多的场景,计算快,但可能丢弃重要模式;过采样复制少数类样本,简单直接,但容易过拟合,尤其当少数类本身多样性不足时;
SMOTE在少数类之间插值生成新样本,能增加多样性,但对高维数据和噪声敏感。我踩过一个坑:在用户行为数据上做SMOTE,生成了一些实际中不可能出现的组合,比如‘新用户+已连续登录30天’,导致线上A/B测试效果很差。所以后来我通常会遵循几条原则:第一,先做数据清洗和特征工程,不要一开始就采样;
第二,用交叉验证在不同随机种子下比较采样方法;第三,在少数类样本极少(比如少于100条)时,单纯过采样意义不大,考虑收集更多数据或使用异常检测;第四,对最终模型做人工抽检,特别是SMOTE生成样本的业务合理性。另外,类别权重可以视为一种‘软过采样’,效果往往比硬采样更稳定。
我的推荐排序是:类别权重 > 过采样/SMOTE > 欠采样,但必须根据具体模型验证。
我最近在做一个移动端广告反作弊的模型,作弊样本占比竟然只有0.05%,正负比例将近1:2000。我试了过采样、SMOTE,还把类别权重调得很大,模型在验证集上看起来还能用,但一到线上就频繁误报,导致很多真实用户被拦截。遇到这种极端不均衡问题,光靠采样已经解决不了了吗?有没有更系统的方法?
极端不均衡(比如>1:1000)时,我建议放弃‘分类思维’,转向‘异常检测’或‘排序思维’。第一手经验:在做反欺诈时,我把问题从‘是否为欺诈’改成了‘哪些交易最可疑’,用无监督的孤立森林或自编码器建模,先筛出异常子集,再交给规则引擎或第二层监督模型。这样能大幅降低误报率。
另一个有效策略是‘分而治之’:把少数类按照某种业务维度拆分,再对每个子集单独建模。比如反作弊中,把作弊行为分为垃圾注册、撞库、刷单三类,分别训练模型,比一个总模型更可控。此外,可以使用‘概率校准’来调整决策阈值。
具体做法是:训练模型后,不默认用0.5作为阈值,而是根据业务目标在验证集上搜索最佳阈值,让召回率和精确率满足业务要求。举个案例:我们曾把一个100:1的问题用XGBoost加阈值下探到约0.3,召回率从10%提升到45%,误报率只增加1.5%。
最后,还有一招是人工数据合成,比如基于生成对抗网络生成少数类样本,但需要谨慎,因为GAN训练不稳定且可解释性差。我的专家判断:不要迷失在算法里,先定义‘漏掉一个少数类’和‘误报一个多数类’各值多少钱,然后选择最大化商业价值的策略。
我一直用类别权重来解决样本不平衡,但朋友说还有Focal Loss、Dice Loss这些损失函数方法,说比采样更优雅。我试着用了一下Focal Loss,发现调参很麻烦,gamma设大了模型反而不收敛。这些损失函数真的值得用吗?和采样方法相比有什么优势?具体在什么场景下应该用它们?
损失函数层面的方法本质上是在改变模型对难易样本的注意力。Focal Loss就是在交叉熵基础上加入调制因子(1-p_t)^γ,让模型更关注难分样本,减少易分样本的损失贡献。它最早用于目标检测,但在表格数据上也能用。
我的经验是:Focal Loss适合‘少数类中有大量难分样本’的场景,比如图像检测中密集小物体;而对于表格数据,如果样本量不大,gamma调得过高(比如>2)容易导致训练不稳定,甚至把噪声看成难例。
此外,还有Dice Loss,在医学图像分割中常用,它能直接优化精确率和召回率的谐波均值,不过对超参数也很敏感。我的建议是:在大多数结构化数据场景中,先使用类别权重往往性价比最高;如果模型已经收敛但少数类指标仍不满意,再尝试Focal Loss。
还有个折中方案:把采样和Focal Loss结合,比如对少数类做过采样后再用Focal Loss,但我测试过,对提升帮助有限,反而增加了复杂度。所以专家判断是:损失函数方法不是银弹,它适合特定模型和特定场景,需要在对模型原理有把握的前提下使用。
另外,一定要用早停法(early stopping)和多组随机种子验证稳定性,避免因为损失函数改变带来的偶然结果。


读者评论
文章把样本不均衡从数据预处理提升到业务决策层面,这个视角很关键。尤其是强调先定义损失矩阵再谈采样,避免了盲目调参。
时间序列数据不能随机过采样这一点提醒得很到位,实际项目中确实容易忽略数据泄漏问题,导致上线后效果波动。
SMOTE不是万能药,在高维稀疏特征下效果差,结合具体案例说明很有说服力,对实战有参考价值。