当前位置: 首页 > news >正文

SMOTE实战:用Python轻松搞定数据不平衡问题(附完整代码)

SMOTE实战:用Python轻松搞定数据不平衡问题(附完整代码)

在机器学习项目中,数据不平衡问题就像一位不请自来的客人——它总是悄无声息地出现,却能让你的模型表现大打折扣。想象一下,你正在构建一个信用卡欺诈检测系统,但欺诈交易只占总样本的0.1%。这种情况下,即使模型把所有交易都预测为"正常",也能达到99.9%的准确率——这显然不是我们想要的结果。

SMOTE(合成少数类过采样技术)正是为解决这类问题而生。不同于简单的复制少数类样本,SMOTE通过智能地生成新样本,在保持数据分布特性的同时有效平衡数据集。本文将带你从零开始,用Python的imbalanced-learn库实现完整的SMOTE流程,包括数据可视化、参数调优和实战技巧。

1. 环境准备与数据加载

工欲善其事,必先利其器。我们需要准备以下工具包:

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import make_classification from imblearn.over_sampling import SMOTE from collections import Counter

为了演示效果,我们创建一个高度不平衡的模拟数据集:

# 生成不平衡数据集 X, y = make_classification(n_classes=2, class_sep=2, weights=[0.9, 0.1], n_informative=3, n_redundant=1, flip_y=0, n_features=20, n_clusters_per_class=1, n_samples=1000, random_state=42)

查看类别分布:

print(f"原始数据分布: {Counter(y)}") # 输出: Counter({0: 900, 1: 100})

可视化展示:

plt.figure(figsize=(10,6)) sns.countplot(x=y) plt.title('类别分布直方图', fontsize=15) plt.xlabel('类别', fontsize=12) plt.ylabel('数量', fontsize=12) plt.show()

2. SMOTE基础实现

SMOTE的核心思想是在少数类样本的"特征空间邻居"之间生成新样本。具体实现仅需几行代码:

# 初始化SMOTE sm = SMOTE(random_state=42) # 应用SMOTE X_res, y_res = sm.fit_resample(X, y) # 查看新分布 print(f"过采样后分布: {Counter(y_res)}") # 输出: Counter({0: 900, 1: 900})

可视化对比:

plt.figure(figsize=(12,5)) plt.subplot(1,2,1) sns.scatterplot(x=X[:,0], y=X[:,1], hue=y) plt.title('原始数据分布') plt.subplot(1,2,2) sns.scatterplot(x=X_res[:,0], y=X_res[:,1], hue=y_res) plt.title('SMOTE处理后分布') plt.tight_layout() plt.show()

关键参数说明:

参数默认值说明
sampling_strategy'auto'重采样后的少数类比例
k_neighbors5生成新样本时考虑的邻居数
random_stateNone随机种子

3. 高级调优技巧

3.1 控制采样比例

有时我们不需要完全1:1的平衡,可以通过sampling_strategy参数控制:

# 只将少数类增加到多数类的50% sm = SMOTE(sampling_strategy=0.5, random_state=42) X_res, y_res = sm.fit_resample(X, y) print(f"50%平衡后分布: {Counter(y_res)}") # 输出: Counter({0: 900, 1: 450})

3.2 结合欠采样

SMOTE常与随机欠采样结合使用(SMOTEENN):

from imblearn.combine import SMOTEENN smote_enn = SMOTEENN(random_state=42) X_res, y_res = smote_enn.fit_resample(X, y) print(f"SMOTEENN处理后分布: {Counter(y_res)}")

3.3 处理高维数据

对于高维数据,可先使用PCA降维再应用SMOTE:

from sklearn.decomposition import PCA pca = PCA(n_components=5) X_pca = pca.fit_transform(X) sm = SMOTE(random_state=42) X_res, y_res = sm.fit_resample(X_pca, y)

4. 实战案例:信用卡欺诈检测

让我们用真实场景演示完整流程。首先加载Kaggle信用卡欺诈数据集:

df = pd.read_csv('creditcard.csv') X = df.drop('Class', axis=1) y = df['Class'] print(f"欺诈比例: {sum(y)/len(y)*100:.4f}%") # 输出: 欺诈比例: 0.1727%

处理流程:

  1. 数据标准化

    from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X)
  2. 应用SMOTE

    sm = SMOTE(random_state=42) X_res, y_res = sm.fit_resample(X_scaled, y)
  3. 模型训练与评估

    from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report X_train, X_test, y_train, y_test = train_test_split( X_res, y_res, test_size=0.3, random_state=42) model = RandomForestClassifier(random_state=42) model.fit(X_train, y_train) y_pred = model.predict(X_test) print(classification_report(y_test, y_pred))

常见报错解决方案:

  • MemoryError:减小数据集规模或使用SMOTEratio参数
  • ValueError: Expected n_neighbors <= n_samples:减少k_neighbors
  • NaN values detected:先处理缺失值再应用SMOTE

5. 替代方案与进阶技巧

当SMOTE效果不佳时,可以考虑以下替代方案:

  • ADASYN:根据样本密度自适应生成新样本

    from imblearn.over_sampling import ADASYN ada = ADASYN(random_state=42) X_res, y_res = ada.fit_resample(X, y)
  • BorderlineSMOTE:专注于边界样本

    from imblearn.over_sampling import BorderlineSMOTE bsmote = BorderlineSMOTE(random_state=42) X_res, y_res = bsmote.fit_resample(X, y)

评估指标选择建议:

场景推荐指标
欺诈检测召回率
医学诊断F1分数
客户流失精确率

在实际项目中,我发现结合多种采样技术往往能取得更好效果。例如,可以先使用SMOTE增加少数类样本,再用Tomek Links清理边界噪声。这种组合策略在我的一个客户流失预测项目中,将F1分数从0.62提升到了0.78。

http://www.cnnetsun.cn/news/1436132.html

相关文章:

  • 松灵机器人二次开发实战:从零搭建Ubuntu环境到ROS包部署(避坑指南)
  • Mi-Create:零基础打造个性化小米穿戴表盘的终极指南
  • SecGPT-14B开源模型实战:中小企业低成本构建专属网络安全智能助手
  • 2026 大型企业网盘选型指南:为何说“同步性能”比“存储空间”更决定成败?
  • 高校科研数据总是丢?教育行业选企业网盘必须死磕的 3 个硬指标(含 5 款主流实测)
  • 丹青识画GPU算力调度:K8s Device Plugin管理书法渲染GPU资源
  • SILVACO TCAD实战:从网格划分到掺杂定制的SPAD器件结构构建
  • 用MATLAB手把手教你仿真3发4收毫米波雷达阵列信号(附完整代码)
  • 避免数据丢失!RK3399系统固件备份与恢复的5个关键步骤(含常见问题解答)
  • Linux驱动开发:环境准备与报错处理
  • AI写春联教程:5分钟上手春联生成模型,零基础也能创作吉祥对联
  • 从零开始:手把手教你用ROS Melodic在Ubuntu 18.04上跑通VINS-Mono(避坑指南)
  • 3分钟掌握Open Interpreter:本地代码执行AI助手的终极指南
  • Z-Image Atelier 自动化测试集成:基于软件测试理论的生成结果验证框架
  • GTE-Base-ZH助力AIGC内容审核:语义相似度匹配实战
  • FastAPI 实战进阶:从零构建高性能用户认证与数据交互API
  • STM32U5定时器实战:用CUBEMX配置TIM从模式实现电机同步控制(附避坑指南)
  • Python Tkinter实战:用20行代码打造你的第一个GUI计算器(附完整源码)
  • GME-Qwen2-VL-2B-Instruct应用开发:Node.js后端服务搭建与API封装
  • 留几手辣评:如今程序员拼命做“上吊绳”,卖个好价钱,然后把自己勒死
  • CLIP-GmP-ViT-L-14惊艳案例:X光片→放射科报告关键句/异常部位定位文本
  • 用Vivado仿真玩转数字存储:从移位寄存器到真双口RAM的FPGA原型验证
  • VMware Workstation Pro 17 安装与激活全攻略
  • FPGA硬件实现三线制SPI协议适配方案
  • Kazumi技术解密:自定义规则驱动的跨平台动漫聚合方案
  • Vue3视频播放器实战:如何用vue3-video-play实现学习视频防快进与断点续播
  • 手把手教你用PyTorch实现轴承故障诊断(代码可直接跑)
  • Windows11下MINIO的快速部署与配置指南
  • CloudCompare点云滤波实战:三种植被去除技术的对比与应用
  • D9: Day2 复盘:Docker 部署踩的坑和解决方案