1. 不平衡分类问题概述在机器学习实践中我们经常会遇到类别分布严重不均衡的数据集。比如在信用卡欺诈检测中正常交易可能占99.9%而欺诈交易仅占0.1%。这种极端不平衡的数据分布会给模型训练带来显著挑战。传统分类算法在这种场景下往往表现不佳因为它们默认假设类别分布大致平衡并且以整体准确率为优化目标。在不平衡数据上一个简单的总是预测多数类的策略就能获得很高的准确率但这显然不是我们想要的结果。关键问题当少数类样本不足时模型难以学习到有效的分类边界导致对少数类的识别率召回率极低。2. 重采样技术基础原理2.1 过采样技术过采样通过增加少数类样本来平衡数据集主要有两种方式随机过采样简单复制少数类样本优点实现简单不引入新信息缺点容易导致过拟合因为完全相同的样本被多次使用SMOTE合成少数类过采样技术工作原理对每个少数类样本x从其k近邻中随机选择一个样本x然后在x和x的连线上随机生成新样本数学表达x_new x λ(x - x)其中λ∈[0,1]是随机数优势增加了样本多样性缓解了过拟合问题2.2 欠采样技术欠采样通过减少多数类样本来平衡数据集常见方法包括随机欠采样随机删除多数类样本优点简单高效缺点可能丢失重要信息Tomek Links定义如果两个不同类样本互为最近邻则构成一个Tomek Link作用移除这些边界样本可以使分类边界更清晰ENN编辑最近邻方法移除那些被其k近邻多数误分类的样本效果能有效清理噪声数据和边界模糊样本3. 组合采样技术详解3.1 为什么需要组合采样单独使用过采样或欠采样各有局限单纯过采样可能导致模型对少数类过拟合单纯欠采样可能丢失多数类的重要信息组合两者可以发挥各自优势先过采样少数类确保有足够样本学习决策边界再欠采样多数类去除噪声和冗余样本3.2 手动组合实现使用imbalanced-learn库的Pipeline可以灵活组合各种采样方法from imblearn.pipeline import Pipeline from imblearn.over_sampling import SMOTE from imblearn.under_sampling import RandomUnderSampler # 定义模型和采样策略 model DecisionTreeClassifier() over SMOTE(sampling_strategy0.1) # 少数类增加到多数类的10% under RandomUnderSampler(sampling_strategy0.5) # 多数类减少到少数类的2倍 # 构建管道先过采样→再欠采样→最后建模 pipeline Pipeline(steps[ (over, over), (under, under), (model, model) ])3.3 参数调优经验采样比例选择过采样比例通常设为0.1-0.5相对多数类的比例欠采样后多数类样本数建议是少数类的1.5-2倍可通过网格搜索寻找最优比例SMOTE的k近邻参数默认k5对于高维数据可适当增大使用k折交叉验证避免过拟合与模型参数的协同决策树的max_depth需要与采样比例配合调整逻辑回归需要适当增加正则化强度4. 预定义组合方法实践4.1 SMOTETomek 实现from imblearn.combine import SMOTETomek # 默认配置SMOTE平衡后移除所有类的Tomek links resampler SMOTETomek(tomekTomekLinks(sampling_strategyall)) # 替代配置只移除多数类的Tomek links更保守 resampler SMOTETomek(tomekTomekLinks(sampling_strategymajority))4.2 SMOTEENN 实现from imblearn.combine import SMOTEENN from imblearn.under_sampling import EditedNearestNeighbours # 默认配置SMOTE平衡后ENN清理所有类 resampler SMOTEENN() # 替代配置ENN只清理多数类 resampler SMOTEENN(ennEditedNearestNeighbours(sampling_strategymajority))4.3 性能对比实验我们在一个1:100的极端不平衡数据集上测试不同方法10折交叉验证重复3次方法平均ROC AUC训练时间(s)基准模型0.7621.2随机过欠采样0.8143.5SMOTE随机欠采样0.8335.1SMOTETomek0.8156.8SMOTEENN0.8297.2从结果可以看出所有重采样方法都提升了模型性能SMOTE随机欠采样取得了最好效果SMOTEENN虽然计算成本较高但性能稳定5. 实际应用中的注意事项5.1 数据泄露问题在交叉验证中必须确保采样只在训练折叠中进行from sklearn.model_selection import cross_val_score # 错误做法先全局采样再交叉验证 X_resampled, y_resampled resampler.fit_resample(X, y) # 会导致数据泄露 scores cross_val_score(model, X_resampled, y_resampled, cvcv) # 正确做法将采样器放入Pipeline pipeline Pipeline([(resampler, resampler), (model, model)]) scores cross_val_score(pipeline, X, y, cvcv)5.2 类别权重替代方案对于计算资源有限的情况可以考虑使用类别权重代替采样# 决策树中的类别加权 model DecisionTreeClassifier(class_weightbalanced) # 逻辑回归中的类别加权 model LogisticRegression(class_weight{0:1, 1:10})5.3 高维数据特殊处理当特征维度很高时如文本数据需要调整SMOTE策略先使用PCA/T-SNE降维后再应用SMOTE增大SMOTE的k近邻参数如k10使用SMOTE变体如Borderline-SMOTE6. 进阶技巧与优化方向6.1 动态采样策略根据模型训练过程中的表现动态调整采样比例from imblearn.pipeline import Pipeline from sklearn.model_selection import GridSearchCV param_grid { resampler__sampling_strategy: [0.1, 0.2, 0.3], model__max_depth: [3, 5, 7] } pipeline Pipeline([ (resampler, SMOTE()), (model, DecisionTreeClassifier()) ]) grid GridSearchCV(pipeline, param_grid, scoringroc_auc) grid.fit(X, y)6.2 集成学习方法结合采样技术与集成学习from imblearn.ensemble import BalancedRandomForestClassifier model BalancedRandomForestClassifier( n_estimators100, sampling_strategyauto, replacementTrue )6.3 自定义采样策略实现自定义的采样逻辑from imblearn.base import BaseSampler class MySampler(BaseSampler): def _fit_resample(self, X, y): # 自定义采样逻辑 return X_resampled, y_resampled7. 不同场景下的方案选择根据数据特点和业务需求选择合适策略计算资源充足使用SMOTEENN组合配合网格搜索优化参数考虑集成方法实时性要求高简单随机过采样欠采样使用类别权重替代采样选择线性模型极端不平衡1%分层采样确保少数类代表使用ADASYN替代SMOTE考虑异常检测算法在实际项目中我通常会先尝试SMOTE随机欠采样的组合因为它通常在效果和效率之间取得了不错的平衡。对于特别关键的应用则会进行更全面的方法比较和参数调优。