You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python分类前如何平衡类别?求助类不平衡处理方法与库

嘿,我太懂你这种挫败感了——类别不平衡绝对是分类任务里最磨人的问题之一,哪怕用了StratifiedKFold保证每折的类别分布,结果还是拉胯的情况太常见了。别担心,咱们从数据处理、算法调整、评估指标三个维度来拆解解决方案,都是实战里能用的硬货:

一、先搞定数据:重采样方法(imblearn库是核心)

你之前没找到合适的库?那imblearn绝对是你的救星——它是专门针对不平衡数据集的工具库,和sklearn完美兼容。注意:所有重采样操作只能在训练集上做,绝对不能碰测试集! 不然会严重数据泄露。

  • 过采样(给少数类“凑数”):最常用的是SMOTE,它会在少数类样本的特征空间里生成新的合成样本,避免简单重复带来的过拟合。
    示例代码:

    from imblearn.over_sampling import SMOTE
    # 只在训练集上应用
    X_train_resampled, y_train_resampled = SMOTE(random_state=42).fit_resample(X_train, y_train)
    

    如果担心边界样本干扰,可以试试SMOTETomek(结合SMOTE和Tomek Links移除噪声样本)。

  • 欠采样(给多数类“瘦身”):当数据集特别大的时候,欠采样效率更高,比如RandomUnderSampler随机去掉多数类样本,或者NearMiss保留和少数类更相关的多数类样本。
    示例代码:

    from imblearn.under_sampling import RandomUnderSampler
    X_train_resampled, y_train_resampled = RandomUnderSampler(random_state=42).fit_resample(X_train, y_train)
    
  • 混合采样:比如SMOTEENN,先过采样少数类,再用ENN算法移除那些被误分类的样本,兼顾数量平衡和样本质量。

二、调整算法:让模型“重视”少数类

不想改数据的话,直接给分类器加类别权重或者用专门针对不平衡数据的模型:

  • 给sklearn分类器加class_weight:大部分sklearn的分类器都支持class_weight参数,比如'balanced'会自动根据类别比例调整权重,让模型更关注少数类。
    示例:

    from sklearn.linear_model import LogisticRegression
    from sklearn.ensemble import RandomForestClassifier
    # 逻辑回归
    lr = LogisticRegression(class_weight='balanced', random_state=42)
    # 随机森林,还可以用balanced_subsample在每棵树的采样阶段调整权重
    rf = RandomForestClassifier(class_weight='balanced_subsample', random_state=42)
    
  • 用树模型的专属参数:XGBoost、LightGBM、CatBoost这些进阶树模型都有针对不平衡数据的参数:

    • XGBoost:scale_pos_weight = 多数类样本数 / 少数类样本数
    • LightGBM:is_unbalance=True 或者 scale_pos_weight
    • CatBoost:auto_class_weights='Balanced'
三、换个评估指标:别再盯着准确率了!

类别不平衡时,准确率完全是个“骗人”的指标——比如99%的样本是多数类,模型全猜多数类也能有99%的准确率,但完全没抓到少数类。你应该用这些指标:

  • F1分数:精确率和召回率的调和平均,兼顾查准和查全
  • 召回率(Recall):衡量少数类被正确识别的比例,对不平衡任务尤为重要
  • PR-AUC:精确率-召回率曲线下的面积,比ROC-AUC更能反映不平衡数据下的模型性能
  • sklearn里可以用classification_report一键输出这些指标:
    from sklearn.metrics import classification_report
    print(classification_report(y_test, y_pred))
    
最后补个实战小例子(结合StratifiedKFold)

把重采样和交叉验证结合起来,避免数据泄露:

from sklearn.model_selection import StratifiedKFold
from imblearn.over_sampling import SMOTE
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score

# 初始化分层交叉验证
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
smote = SMOTE(random_state=42)

# 循环每一轮交叉验证
for train_idx, test_idx in skf.split(X, y):
    X_train, X_test = X.iloc[train_idx], X.iloc[test_idx]
    y_train, y_test = y.iloc[train_idx], y.iloc[test_idx]
    
    # 只对训练集做过采样
    X_train_resampled, y_train_resampled = smote.fit_resample(X_train, y_train)
    
    # 训练带权重的模型
    model = RandomForestClassifier(class_weight='balanced', random_state=42)
    model.fit(X_train_resampled, y_train_resampled)
    
    # 用F1分数评估
    y_pred = model.predict(X_test)
    print(f"当前折F1分数: {f1_score(y_test, y_pred):.4f}")

先从调整评估指标开始,看看模型的真实表现,再尝试数据重采样或者调整模型权重,应该能看到明显的提升!

内容的提问来源于stack exchange,提问作者dblanco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:39:27