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

SMOTE详解

一、什么是SMOTE?为什么要使用它?

1、核心问题:类别不平衡

SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术),在机器学习中,我们经常会遇到“类别不平衡”的数据集。例如:

  • 金融风控:绝大多数交易是正常的,只有极少数是欺诈交易。
  • 医疗诊断:绝大多数样本是健康的,只有少数是患病个体。
  • 工业质检:绝大部分产品是良品,只有少量是次品。

在这些场景下,如果直接用原始数据训练模型,模型会倾向于“讨好”多数类(即把所有样本都预测为多数类),因为这样也能获得很高的准确率。但对于我们真正关心的少数类,模型的预测效果会非常差。

2、传统方法的局限性

在SMOTE提出之前,解决类别不平衡的简单方法主要是:

  • 过采样:随机复制少数类样本。
    • 缺点:容易导致模型过拟合。因为只是简单复制样本,模型学到的信息没有增加,只是反复看了几遍相同的样本,对噪声和异常值会更敏感。
  • 欠采样:随机删除多数类样本。
    • 缺点:会丢失多数类中包含的重要信息,可能影响模型的性能。

3、SMOTE的诞生

SMOTE由Nitesh Chawla等人于2002年提出。它的核心思想非常巧妙:不是简单地复制少数类样本,而是通过“插值”来合成新的、人工的少数类样本。 这种方法可以有效地扩大少数类的决策区域,从而让模型学习到更鲁棒、更泛化的规律。

二、 SMOTE算法原理详解

SMOTE的核心是“插值”。想象一下在二维平面上,我们有两个很接近的少数类样本点,那么在这两个点之间的连线上,新生成的点也很有可能是合理的少数类样本。

1、 算法步骤(假设针对少数类S_min):

  1. 对于少数类中的每一个样本x_i:
    • a. 计算x_i在少数类样本集合中的k个最近邻(通常使用欧氏距离,k通常取5)。
    • b. 从这k个最近邻中,随机选择一个样本,记为x_zi。
  2. 合成新样本:
    • 在x_i和x_zi之间的连线上,随机选择一个点作为新样本。
    • 具体公式为:x_new = x_i + λ * (x_zi - x_i)
    • 其中,λ是一个在[0, 1]区间内随机生成的数。
      • 当λ=0时,x_new就是x_i。
      • 当λ=1时,x_new就是x_zi。
      • 当λ=0.5时,x_new就是x_i和x_zi的中点。
  3. 重复步骤1和2,直到少数类的样本数量达到预期(例如,与多数类样本数量相等)。

三、在Python中的实现

使用imbalanced-learn这个专门的库可以非常方便地实现SMOTE。

1、安装与导入、语法

pip install imbalanced-learn
from imblearn.over_sampling import SMOTE
smote = SMOTE(sampling_strategy='auto',random_state=None,k_neighbors=5,n_jobs=None
)

2、参数详解

参数/方法说明常用值
sampling_strategy核心,控制重采样目标和程度'auto'(默认), float(如0.8), dict(最灵活)
k_neighbors控制生成新样本时考虑的近邻数5(默认),样本少时可调小,样本多噪声少时可调大
random_state确保结果可重现42, None
n_jobs并行计算,加速k近邻搜索-1(用全部核心),大数据集时有用
fit_resample(X, y)最常用方法,一次性完成拟合和重采样返回 X_resampled, y_resampled

3、方法详解

fit(X, y)

  • 作用:仅“拟合”重采样器到数据,计算生成样本所需的统计信息(如每个类需要生成多少样本),但并不实际重采样。
  • 返回值:返回拟合后的重采样器对象本身。
  • 用途:通常不单独使用,而是与 resample方法联用。fit_resample方法等价于先调用 fit再调用 resample。

resample(X, y)

  • 作用:根据 fit方法计算出的信息,执行实际的重采样。
  • 前提:必须先调用 fit方法。
  • 返回值:返回重采样后的 (X_resampled, y_resampled)。

fit_resample(X, y)
这是最核心、最常用的方法。它一次性完成“拟合”和“重采样”两个步骤。
参数:

  • X:特征矩阵,形状为 (n_samples, n_features)的类数组(如 numpy array, pandas DataFrame)。
  • y:目标向量,形状为 (n_samples,)的类数组(如 numpy array, pandas Series)。

返回值:

  • X_resampled:重采样后的特征矩阵。
  • y_resampled:重采样后的目标向量。

内部工作流程:

  • 识别类别:分析 y,确定多数类和少数类。
  • 确定目标:根据 sampling_strategy参数,计算每个少数类需要生成的新样本数量。
  • 生成样本:对于每个需要过采样的少数类:
  • 对于该类中的每个样本,找到其 k_neighbors个最近邻。
  • 根据所需的新样本数量,循环执行:随机选择一个样本,再从其k近邻中随机选择一个近邻,然后在两者连线上随机插值生成一个新样本。
  • 返回结果:将新生成的合成样本与原始数据(包括所有多数类样本和未重采样的少数类)合并,然后返回。
smote = SMOTE(random_state=42)
smote.fit(X_train, y_train)  # 先拟合
X_res, y_res = smote.resample(X_train, y_train) # 再重采样# 这完全等价于:
X_res, y_res = smote.fit_resample(X_train, y_train)

4、实例

import pandas as pd
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
from imblearn.over_sampling import SMOTE # 注意导入路径是 imblearn# 1. 创建一个高度不平衡的数据集(仅用于演示)
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2,n_redundant=10, n_clusters_per_class=1,weights=[0.99], flip_y=0, random_state=1)# 查看原始数据分布
print("原始数据集类别分布:", pd.Series(y).value_counts()) # 大概是 990:10# 2. 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)# 3. 应用SMOTE(仅在训练集上应用!绝对不要在测试集上应用!)
sm = SMOTE(random_state=42)
X_train_resampled, y_train_resampled = sm.fit_resample(X_train, y_train)# 查看过采样后的训练集分布
print("SMOTE后训练集类别分布:", pd.Series(y_train_resampled).value_counts())# 4. 训练模型并评估
# 在原始不平衡数据上训练(作为对比)
model_imbalanced = RandomForestClassifier(random_state=42)
model_imbalanced.fit(X_train, y_train)
y_pred_imb = model_imbalanced.predict(X_test)# 在SMOTE平衡后的数据上训练
model_balanced = RandomForestClassifier(random_state=42)
model_balanced.fit(X_train_resampled, y_train_resampled)
y_pred_bal = model_balanced.predict(X_test)# 5. 比较结果
print("\n--- 在不平衡数据上训练的模型表现 ---")
print(confusion_matrix(y_test, y_pred_imb))
print(classification_report(y_test, y_pred_imb))print("\n--- 在SMOTE平衡数据上训练的模型表现 ---")
print(confusion_matrix(y_test, y_pred_bal))
print(classification_report(y_test, y_pred_bal))

关键注意事项:

  • 仅在训练集上应用SMOTE:SMOTE的本质是通过生成新样本来扩充训练集,因此它必须只在训练集上进行。如果在整个数据集(包含测试集)上应用,会导致数据泄露,严重高估模型性能。fit_resample方法只应使用训练集的数据。
  • 先分割,再重采样:这是必须遵守的工作流。

四、 SMOTE的优缺点总结

优点:

  1. 有效缓解过拟合:相比随机过采样,通过生成“新”样本,降低了过拟合风险。
  2. 增加决策区域:通过扩充少数类,使得分类器能够学习到更广泛的少数类模式。
  3. 简单有效:概念清晰,实现简单,在多数情况下效果显著。

缺点和局限:

  1. 可能生成噪声:如果少数类的分布不连续或存在噪声点,SMOTE可能会在多数类区域内生成不合理的样本,反而干扰分类器。
  2. 可能放大噪声:如果选择的近邻本身是噪声点,那么新生成的样本也会是噪声。
  3. 忽略多数类信息:SMOTE只关注少数类,没有利用多数类的分布信息,有时会导致类别重叠区域扩大。
  4. 对高维数据效果下降:在高维空间中,“最近邻”的概念会变得不稳定(维度灾难)。

五、 最佳实践与建议

  1. 不要盲目使用:首先尝试在不平衡数据上训练一个模型作为基线。有时,简单的模型(如树模型)或调整类别权重(如class_weight=‘balanced’)可能就足够了。
  2. 结合多种技术:可以尝试将SMOTE与欠采样结合(如SMOTE + Tomek Links),或者使用其改进算法(如Borderline-SMOTE, ADASYN)。
  3. 使用正确的评估指标:在类别不平衡问题中,准确率是无效的。应重点关注:
    • 精确率
    • 召回率
    • F1-Score
    • AUC-ROC曲线AUC-PR曲线(尤其是不平衡严重时,PR曲线更敏感)
    • 混淆矩阵
  4. 进行交叉验证:使用SMOTE时,交叉验证的设置要小心。必须确保重采样过程只在训练折叠中进行,而不是在整个数据集上。imblearn提供了Pipeline来与sklearn的交叉验证无缝结合。
http://www.dtcms.com/a/606691.html

相关文章:

  • 16.【NXP 号令者RT1052】开发——实战-FlexPWM 输出
  • Datawhale coze-ai-assistant task2
  • NESTJS - RSA加解密
  • 自己服务器可以做网站如何做家教网站赚钱
  • 开发外贸网站开发企业官网的建设
  • 一、Rabbit MQ 初级
  • 单位网站建设费用神马搜索推广
  • 【MySQL】MySQL内置函数--日期函数字符串函数数学函数其他相关函数
  • 数据结构 力扣 练习
  • 2018年网站建设发言凯里网站开发
  • XML 和 JSON -----几种重要模式
  • 【读论文】基于LLM增强的全双工对话
  • 怎么做网站不被发现崇明网站开发
  • Java后端常用技术选型 |(二)工具类篇
  • FPGA教程系列-Vivado IP核BMG核
  • 【1.11】基于FPGA的costas环开发5——环路滤波器模块开发
  • 济南行知网站建设南京淄博网站建设工作室
  • 网站木马 代码网站建设新手
  • 汕头市国外网站建设公司百度关键词优化查询
  • 业务流低代码平台:从理念到实战
  • DebugView 学习笔记(8.9):什么是调试输出?为什么它是现场排障的“读心术”
  • RSS 语法:全面解析与优化指南
  • php能做手机网站吗口碑营销成功的案例
  • 【每日一面】BOM 是什么
  • 稀土抑烟剂在透明膜上的应用:安全与环保的双重保障
  • 郑州网站建设中心wordpress2016
  • 最新企业网站制作短链接网站
  • 建设部标准规范网站网页设计与制作教程考试试卷
  • 基于Python+OpenCV实现双目立体视觉的图像匹配与测距
  • duckdb使用详解