破解机器学习中的“不平衡陷阱”:五种策略教你挽救偏斜数据集
【精选优质专栏推荐】
- 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用
- 《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看
- 《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解
- 《网安渗透工具使用教程(全)》 —— 一站式工具手册
- 《CTF 新手入门实战教程》 —— 从题目讲解到实战技巧
- 《前后端项目开发(新手必知必会)》 —— 实战驱动快速上手
每个专栏均配有案例与图文讲解,循序渐进,适合新手与进阶学习者,欢迎订阅。
文章目录

引言
新手机器学习从业者几乎都会立刻意识到一个事实:并非所有数据集都是平等的。
这现在对你来说也许显而易见,但在你开始处理真实世界的机器学习项目之前,是否考虑过这一点?举个例子,在一种只有 1% 的人群患有的罕见疾病中,如果一个预测模型始终预测“无病”,它虽然 99% 正确,但能算有用吗?显然不能。
在机器学习中,数据集不平衡会成为模型性能的障碍,且常常难以克服。许多常见算法默认假设各类别在数据分布中被近似均衡地表示。而在不平衡数据上训练的模型通常会严重偏向多数类,从而导致少数类被低估——而少数类往往正是需要重点关注的部分。
这种严重偏斜的数据集在现实中非常普遍,从罕见疾病研究(数据稀少且难以获取)到金融欺诈检测(大部分交易并非欺诈)。本文的目标是介绍 5 种可靠的策略,用于处理类别不平衡问题。
1. 重采样技术(Resampling Techniques)
重采样通过增加少数类样本或移除多数类样本来平衡类别。
常见的少数类过采样方法包括生成新的少数类样本。
随机过采样(Random Oversampling)是一种简单方法,通过复制现有少数类样本生成新样本。但熟悉机器学习基础的人会立刻意识到其过拟合风险。更先进的做法是使用 SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术),该方法通过在现有少数类样本之间插值来生成新样本。
同样地,多数类欠采样的策略是删除部分多数类样本。
随机欠采样(Random Under-Sampling)就是随机丢弃多数类的一些样本,但这可能导致信息丢失。为了减轻这种损失,可以使用更复杂的欠采样方法,如 Tomek Links 或邻域清理规则(Neighborhood Cleaning Rule, NCR),它们会删除与少数类过于接近或重叠的多数类样本,从而在减少噪声的同时保留重要信息,并使类别边界更加清晰。
下面是使用 imbalanced-learn 库进行 SMOTE 和随机欠采样的简单示例:
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import RandomUnderSampler
# 假设 X 为特征矩阵,y 为目标向量
# SMOTE 过采样
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X, y)
# 随机欠采样
rus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X, y)
每种方法都有其优缺点。过采样可能导致过拟合,尤其是在使用简单复制时;而欠采样可能会丢失有价值的信息。通常结合两种技术可以获得更好的结果。
2. 算法集成方法(Algorithmic Ensemble Methods)
集成方法通过组合多个模型来生成一个更强的整体模型,对不平衡数据问题尤其有用,特别是当目标类别是少数类时。
一种常见的集成方法是 Bagging(自助聚合)。其核心思想是从数据中随机创建多个子集,在每个子集上训练一个模型,然后结合这些模型的预测结果。随机森林(Random Forest)是 Bagging 的一种常见实现方式,常用于不平衡数据。随机森林通过在不同数据子集上创建多棵决策树并聚合它们的输出,有效防止过拟合并提升模型的泛化性能。
另一种方法是 Boosting(提升)。该方法按顺序训练多个模型,每个新模型都会努力纠正前一模型的错误。对于处理不平衡数据,Boosting 尤其强大。例如,梯度提升(Gradient Boosting)可以自我学习,使模型更关注那些容易被错误分类的少数类样本,从而自动调整模型行为。
以下是在 Python 中实现随机森林和梯度提升的示例:
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
# 随机森林
rf_classifier = RandomForestClassifier(n_estimators=100, class_weight='balanced_subsample')
rf_classifier.fit(X_train, y_train)
# 梯度提升
gb_classifier = GradientBoostingClassifier(n_estimators=100)
gb_classifier.fit(X_train, y_train)
在上面的代码中,n_estimators 定义了树或提升阶段的数量,而 class_weight 参数在随机森林中用于调整类别权重,以应对不平衡数据。
这些方法本身就具备一定的抗不平衡能力,因为它们通过结合多个模型或聚焦难分类样本来提升性能。通常即便不使用重采样,它们也能获得不错的效果,而与重采样技术结合使用时效果往往更佳。
3. 调整类别权重(Adjust Class Weights)
类别加权(class weighting)是一种在模型训练中给少数类分配更高权重的技术,使模型在优化过程中更加关注那些代表性不足的类别。
在一些机器学习库(如 scikit-learn)中,可以直接设置类别权重。当数据集中某个类别出现的频率远高于其他类别时,模型会对少数类的错误分类施加更高的惩罚,从而平衡学习过程。
例如,在逻辑回归中可以这样设置类别权重:
from sklearn.linear_model import LogisticRegression
from sklearn.utils.class_weight import compute_class_weight
import numpy as np
# 计算权重
class_weights = compute_class_weight('balanced', classes=np.unique(y), y=y)
weight_dict = dict(zip(np.unique(y), class_weights))
# 应用权重到模型
lr_classifier = LogisticRegression(class_weight=weight_dict)
lr_classifier.fit(X_train, y_train)
通过调整类别权重,我们改变了模型在误分类时的惩罚方式。需要注意的是,这些权重不会改变模型的预测过程本身,而是影响模型在优化阶段对损失函数的计算方式。
不过要避免对少数类加权过高,否则模型可能会过度偏向该类,甚至“遗忘”其他类别。
4. 使用合适的评估指标(Use Appropriate Evaluation Metrics)
在处理不平衡数据时,仅仅使用“准确率”往往具有误导性。一个总是预测多数类的模型可能准确率很高,但完全无法识别少数类。
更合适的指标包括:
- Precision(精确率):预测为正样本的结果中有多少是真的正样本。
- Recall(召回率):所有真实正样本中有多少被模型识别出来。
- F1-score(F1 值):精确率和召回率的调和平均,平衡两者。
- AUC-ROC(受试者工作特征曲线下面积):衡量模型在不同阈值下区分类别的能力,对类别不平衡不敏感。
混淆矩阵(Confusion Matrix)同样非常有用,它能直观展示模型的预测情况,包括真阳性、假阳性、真阴性和假阴性。
下面是这些指标的计算示例:
from sklearn.metrics import precision_recall_fscore_support, roc_auc_score, confusion_matrix
# 假设 y_true 为真实标签, y_pred 为模型预测结果
precision, recall, f1, _ = precision_recall_fscore_support(y_true, y_pred, average='binary')
auc_roc = roc_auc_score(y_true, y_pred)
conf_matrix = confusion_matrix(y_true, y_pred)
print(f"Precision: {precision}, Recall: {recall}, F1: {f1}")
print(f"AUC-ROC: {auc_roc}")
print("Confusion Matrix:")
print(conf_matrix)
选择指标时应基于具体问题:
- 若假阳性代价高(如误判为欺诈),应关注精确率;
- 若漏判代价高(如漏诊疾病),应关注召回率;
- F1 值和 AUC-ROC 通常提供更平衡的整体评估。
5. 生成合成样本(Generate Synthetic Samples)
合成样本生成是一种更高级的平衡数据技术,通过为少数类生成人工样本来扩充数据集。
SMOTE(Synthetic Minority Over-sampling Technique)是常用算法。它通过选取一个少数类样本,并寻找其 k 个最近邻,然后在该样本与邻居之间插值生成新样本。
实现示例如下:
from imblearn.over_sampling import SMOTE
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X, y)
进阶版本如 ADASYN(Adaptive Synthetic) 和 Borderline-SMOTE 会专注于少数类易被误分类的区域生成样本,从而提升边界学习效果。
不过,生成合成样本也存在风险。若使用不当,可能引入噪声或生成不现实的样本。因此,必须验证这些新样本在实际业务语境中是否合理。
总结
处理不平衡数据是许多机器学习任务中的关键步骤。本文介绍了五种常用方法:
- 重采样(Resampling)
- 集成方法(Ensemble Methods)
- 类别权重调整(Class Weighting)
- 合适的评估指标(Evaluation Metrics)
- 合成样本生成(Synthetic Sample Generation)
需要注意,没有通用的解决方案。不同的数据集、业务目标和评估标准需要不同的策略。通常,混合使用多种方法或调整参数能获得最佳效果。
掌握这些应对不平衡数据的技术,能让你在机器学习项目中构建更可靠、更具实用价值的模型。
更多推荐
所有评论(0)