news 2026/7/13 8:26:15

数据分析中,如何处理数据的不平衡问题?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据分析中,如何处理数据的不平衡问题?

数据不平衡问题处理指南

一、问题本质

数据不平衡指分类任务中各类别样本数量差异悬殊,例如:

场景多数类少数类不平衡比
信用卡欺诈检测正常交易 99.8%欺诈 0.2%500:1
罕见病诊断健康 99.5%患病 0.5%200:1
设备故障预测正常 99%故障 1%100:1
网络入侵检测正常流量 97%攻击 3%32:1

核心危害:模型被多数类主导,对少数类"视而不见"——准确率 99% 可能毫无意义(全预测为多数类即可达到)。

准确率陷阱: 欺诈检测中,全预测"正常" → 准确率 99.8%,但召回率 0% 真正目标:在保持整体性能的同时,提升对少数类的识别能力

二、评估指标先行

处理不平衡前,必须选择正确的评估指标:

指标公式/含义适用场景
Precision(精确率)TP / (TP + FP)误报代价高(如冤枉好人)
Recall(召回率)TP / (TP + FN)漏报代价高(如漏掉欺诈)
F1-Score2×P×R / (P+R)需要平衡 P 和 R
Fβ-Score加权调和平均β>1 偏召回,β<1 偏精确
PR-AUCPrecision-Recall 曲线下面积不平衡数据首选
ROC-AUCTPR-FPR 曲线下面积不平衡严重时可能过于乐观
fromsklearn.metricsimportclassification_report,precision_recall_curve,auc# 不平衡数据必须看的报告print(classification_report(y_test,y_pred,target_names=['多数类','少数类']))# PR-AUC(不平衡数据更可靠)precision,recall,_=precision_recall_curve(y_test,y_proba)pr_auc=auc(recall,precision)print(f"PR-AUC:{pr_auc:.4f}")

三、三大处理策略

数据不平衡处理 ├── 一、数据层面 — 重采样(改变数据分布) │ ├── 欠采样(减少多数类) │ └── 过采样(增加少数类) ├── 二、算法层面 — 代价敏感学习(改变学习策略) │ ├── 类别权重调整 │ └── 代价敏感算法 └── 三、集成层面 — 结合重采样与集成学习 ├── BalancedBagging ├── EasyEnsemble └── RUSBoost

策略一:数据层面 — 重采样

1. 欠采样(Undersampling)— 减少多数类
fromimblearn.under_samplingimportRandomUnderSampler,TomekLinks,NearMiss# 随机欠采样rus=RandomUnderSampler(sampling_strategy=0.5,random_state=42)# 少数:多数 = 1:2X_res,y_res=rus.fit_resample(X_train,y_train)# NearMiss — 保留距少数类最近的多数类样本(更智能)nm=NearMiss(version=3,n_neighbors_ver3=3)X_res,y_res=nm.fit_resample(X_train,y_train)# Tomek Links — 只移除与少数类最近且重叠的多数类样本(温和欠采样)tl=TomekLinks(sampling_strategy='majority')X_res,y_res=tl.fit_resample(X_train,y_train)
方法优点缺点
RandomUnderSampler简单快速丢失多数类信息
NearMiss保留边界信息计算距离开销大
TomekLinks温和,信息损失小降采样幅度有限
2. 过采样(Oversampling)— 增加少数类
fromimblearn.over_samplingimportRandomOverSampler,SMOTE,ADASYN,BorderlineSMOTE# 随机过采样(简单复制)ros=RandomOverSampler(sampling_strategy=0.5,random_state=42)X_res,y_res=ros.fit_resample(X_train,y_train)# SMOTE — 合成少数类样本(最常用)fromimblearn.over_samplingimportSMOTE smote=SMOTE(sampling_strategy=0.5,k_neighbors=5,random_state=42)X_res,y_res=smote.fit_resample(X_train,y_train)# BorderlineSMOTE — 只在边界区域合成(更精准)bsmote=BorderlineSMOTE(kind='borderline-1',random_state=42)X_res,y_res=bsmote.fit_resample(X_train,y_train)# ADASYN — 自适应合成,更关注难分类的少数类样本adasyn=ADASYN(sampling_strategy=0.5,random_state=42)X_res,y_res=adasyn.fit_resample(X_train,y_train)

SMOTE 原理图解:

多数类: ○ 少数类: ● 合成样本: ✦ ○ ○ ○ ○ ○ ○ → ○ ✦ ○ ○ ●──● ○ ○ ●──✦──● ○ ○ ○ ✦ ○ ○ ○ ○ ○ 在两个少数类样本连线上随机插值生成新样本
方法优点缺点
RandomOverSampler简单复制样本 → 过拟合
SMOTE合成新样本,泛化更好可能生成噪声样本
BorderlineSMOTE聚焦决策边界边界样本少时效果受限
ADASYN自适应难度对噪声敏感
3. 混合采样(推荐)
fromimblearn.combineimportSMOTETomek,SMOTEENN# SMOTE + Tomek Links:先过采样再清理重叠combo=SMOTETomek(sampling_strategy=0.5,random_state=42)X_res,y_res=combo.fit_resample(X_train,y_train)# SMOTE + ENN:先过采样再清理噪声(更激进)combo2=SMOTEENN(sampling_strategy=0.5,random_state=42)X_res,y_res=combo2.fit_resample(X_train,y_train)

策略二:算法层面 — 代价敏感学习

1. 类别权重调整
fromsklearn.ensembleimportRandomForestClassifierfromsklearn.linear_modelimportLogisticRegressionfromsklearn.svmimportSVC# 方式1:class_weight='balanced' — 自动按反比例加权rf=RandomForestClassifier(class_weight='balanced',random_state=42)lr=LogisticRegression(class_weight='balanced',random_state=42)# 方式2:手动指定权重weights={0:1,1:50}# 少数类权重 50 倍rf=RandomForestClassifier(class_weight=weights,random_state=42)# 方式3:XGBoost 的 scale_pos_weightimportxgboostasxgb neg_count=(y_train==0).sum()pos_count=(y_train==1).sum()model=xgb.XGBClassifier(scale_pos_weight=neg_count/pos_count,# 自动平衡max_depth=6,n_estimators=200,random_state=42)
2. 自定义损失函数
importxgboostasxgbimportnumpyasnpdefweighted_logloss(y_pred,y_true):"""少数类漏报惩罚更重"""y_true=y_true.get_label()weight=np.where(y_true==1,10.0,1.0)# 少数类权重 10 倍grad=weight*(y_pred-y_true)hess=weight*y_pred*(1-y_pred)returngrad,hess model=xgb.XGBClassifier(obj=weighted_logloss,n_estimators=200)

策略三:集成层面 — 专用不平衡集成算法

fromimblearn.ensembleimport(BalancedBaggingClassifier,BalancedRandomForestClassifier,EasyEnsembleClassifier,RUSBoostClassifier)# BalancedBagging — 每棵树训练前自动欠采样bbc=BalancedBaggingClassifier(estimator=RandomForestClassifier(n_estimators=10),n_estimators=50,sampling_strategy=0.5,random_state=42)# BalancedRandomForest — 随机森林的不平衡版本brf=BalancedRandomForestClassifier(n_estimators=200,sampling_strategy='auto',random_state=42)# EasyEnsemble — 多组欠采样 + 多个基分类器 + 投票eec=EasyEnsembleClassifier(n_estimators=10,sampling_strategy=0.5,random_state=42)# RUSBoost — 欠采样 + Boostingrusb=RUSBoostClassifier(n_estimators=200,sampling_strategy=0.5,random_state=42)

四、完整实战流水线

fromsklearn.model_selectionimporttrain_test_splitfromsklearn.metricsimportclassification_report,f1_scorefromimblearn.pipelineimportPipeline# 注意:用 imblearn 的 Pipelinefromimblearn.combineimportSMOTETomekfromsklearn.ensembleimportRandomForestClassifier# 1. 划分数据(重采样只在训练集上做!)X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,stratify=y,random_state=42# stratify 保证测试集分布一致)# 2. 构建流水线pipeline=Pipeline([('resampling',SMOTETomek(sampling_strategy=0.5,random_state=42)),('classifier',RandomForestClassifier(n_estimators=200,class_weight='balanced_subsample',max_depth=10,random_state=42,n_jobs=-1))])# 3. 训练pipeline.fit(X_train,y_train)# 4. 评估y_pred=pipeline.predict(X_test)print(classification_report(y_test,y_pred,target_names=['多数类','少数类']))

关键原则:重采样只在训练集上做,测试集保持原始分布!


五、阈值调整(零成本提升)

不修改模型,只调整分类阈值:

fromsklearn.metricsimportprecision_recall_curve# 获取预测概率y_proba=model.predict_proba(X_test)[:,1]# 默认阈值 0.5 → 降低阈值可提升召回率importnumpyasnp y_pred_custom=(y_proba>=0.3).astype(int)# 降低阈值到 0.3# 自动寻找最优阈值(最大化 F1)precisions,recalls,thresholds=precision_recall_curve(y_test,y_proba)f1_scores=2*precisions*recalls/(precisions+recalls+1e-8)best_threshold=thresholds[np.argmax(f1_scores)]print(f"最优阈值:{best_threshold:.4f}")y_pred_optimal=(y_proba>=best_threshold).astype(int)

六、策略选择决策树

数据不平衡比? ├── < 5:1(轻度) │ └── class_weight='balanced' + 阈值调整(最简单) ├── 5:1 ~ 50:1(中度) │ ├── 样本量充足 → SMOTE / SMOTETomek + 类别权重 │ └── 样本量不足 → BorderlineSMOTE + 集成方法 ├── > 50:1(重度) │ ├── 多数类样本极多 → BalancedRandomForest / EasyEnsemble │ └── 少数类样本极少 → ADASYN + 代价敏感 + 阈值调整 └── 极端不平衡(< 0.1%) └── 异常检测思路(One-Class SVM / Isolation Forest)而非分类

七、常见误区与注意事项

误区正确做法
在全量数据上做重采样再划分先划分,再对训练集重采样,测试集保持原始分布
只看准确率评估模型使用 F1 / PR-AUC / Recall 等不平衡友好指标
过采样到完全平衡(1:1)适度平衡即可(1:2 ~ 1:5),完全平衡易过拟合
SMOTE 在高维数据上效果差高维时先降维再 SMOTE,或用 ADASYN
忽略业务代价根据漏报/误报的业务代价选择指标和阈值
只用单一策略组合策略效果最佳:重采样 + 类别权重 + 阈值调整
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 8:25:43

JAVA无人共享系统24小时自助高尔夫系统源码支持小程序+公众号+APP+H5

JAVA无人共享系统24小时自助高尔夫系统源码&#xff1a;重构高尔夫产业智慧运营新生态一、行业痛点与技术破局&#xff1a;无人共享高尔夫系统的价值重构在高尔夫产业数字化与智能化转型的浪潮中&#xff0c;这项被誉为“绿色鸦片”的绅士运动正面临运营成本高企、场地利用率不…

作者头像 李华
网站建设 2026/7/13 8:21:48

测试工程师Linux命令实战:从日志分析到性能监控完整指南

作为一名测试工程师&#xff0c;你是否曾经遇到过这样的场景&#xff1a;生产环境突然出现性能问题&#xff0c;你需要快速登录服务器查看日志&#xff0c;却对一堆Linux命令感到手足无措&#xff1f;或者面试时被问到Linux操作&#xff0c;只能尴尬地说“不太熟悉”&#xff1…

作者头像 李华
网站建设 2026/7/13 8:20:23

装修为什么总会超支?恶意增项真的无法避免吗?

作者&#xff1a;太原家装设计师阿朱 直接回答 装修超支90%以上并非业主乱买&#xff0c;而是前期漏项、低价引流、隐性增项导致&#xff0c;并非无法避免。根据杭州市消保委《2025年度家装消费维权报告》数据显示&#xff0c;家装投诉中合同增项争议占比31.2%&#xff0c;排…

作者头像 李华
网站建设 2026/7/13 8:20:20

AssetStudio纹理导出实战:解析PVRTC、ETC、ASTC压缩格式与解码原理

1. 项目概述&#xff1a;为什么我们需要深入理解纹理格式转换&#xff1f;如果你曾经尝试过从游戏或应用资源包中提取纹理&#xff0c;尤其是在移动平台的项目里&#xff0c;大概率会遇到一些以.assets或.bundle结尾的文件&#xff0c;用常规的图片查看器打开却是一堆乱码。这时…

作者头像 李华
网站建设 2026/7/13 8:19:09

如何免费解锁网易云音乐NCM格式:3步快速转换为MP3的完整指南

如何免费解锁网易云音乐NCM格式&#xff1a;3步快速转换为MP3的完整指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他设备播放而烦恼吗&#xff1f;你是否曾经想过&#xff0c;为什么…

作者头像 李华