SMOTE过采样实现过程详解
引言
SMOTE(Synthetic Minority Over-sampling Technique,合成少数类过采样技术)是一种常用的处理类别不平衡问题的方法。下面我将详细解释oversampler=SMOTE(random_state=0)
和os_x_train,os_y_train=oversampler.fit_resample(x_train_w,y_train_w)
这两行代码的实现过程。
1. SMOTE的基本原理
SMOTE通过在少数类样本之间进行插值来生成新的合成样本,而不是简单地复制现有样本。其主要思想是:
对于每一个少数类样本,找到它的k个最近邻(通常是欧氏距离)
在这些近邻中随机选择一个样本
在这两个样本之间的连线上随机选择一个点作为新的合成样本
2. 代码实现过程详解
2.1 SMOTE初始化
oversampler = SMOTE(random_state=0)
random_state=0
:设置随机种子,确保每次运行结果可复现默认参数:
k_neighbors=5
:查找最近邻的数量sampling_strategy='auto'
:默认将少数类样本数量增加到与多数类相同
2.2 数据重采样过程
os_x_train, os_y_train = oversampler.fit_resample(x_train_w, y_train_w)
fit_resample()
方法的执行步骤如下:
步骤1:分析类别分布
统计
y_train_w
中各个类别的样本数量确定少数类(样本数量最少的类别)和多数类
计算需要生成的合成样本数量(默认使少数类样本数量等于多数类)
步骤2:生成合成样本
对于每一个少数类样本:
查找k近邻:
计算该样本与所有其他少数类样本的距离(默认使用欧氏距离)
找出距离最近的k个样本(默认k=5)
随机选择邻居:
从k个近邻中随机选择一个样本
使用
random_state
确保可复现性
生成合成样本:
在两个样本之间随机选择一个点
新样本的计算公式:
新样本 = 原始样本 + random(0,1) * (邻居样本 - 原始样本)
random(0,1)
表示0到1之间的随机数
步骤3:构建新数据集
将原始少数类样本与新生成的合成样本合并
保持多数类样本不变
返回新的特征矩阵
os_x_train
和标签向量os_y_train
2.3 示例说明
假设原始数据集:
多数类(类别0):1000个样本
少数类(类别1):100个样本
执行SMOTE后:
类别0保持不变(1000个样本)
类别1增加到1000个样本(原始100个 + 新生成900个合成样本)
3. SMOTE的参数详解
参数 | 说明 | 默认值 |
---|---|---|
| 用于生成新样本的最近邻数量 | 5 |
| 重采样策略 | 'auto' |
| 随机种子 | None |
| 并行计算使用的CPU核心数 | None |
sampling_strategy
可选值:
'auto':将少数类样本数量增加到与多数类相同
'minority':仅对少数类进行过采样
float:指定少数类样本数量与多数类的比例(如0.5表示达到多数类的一半)
dict:指定每个类别需要达到的样本数量
4. SMOTE的优缺点
优点:
避免简单复制导致的过拟合
在特征空间内合理扩展少数类样本
适用于高维数据
缺点:
可能生成噪声样本(当少数类样本分布不连续时)
对高维稀疏数据效果可能不佳
可能忽略类别内部的子类别结构
5. 使用建议
先进行数据探索,了解少数类样本的分布
尝试不同的
k_neighbors
值(3-10)结合欠采样方法使用(如SMOTE + Tomek Links)
对于高维数据,考虑先进行降维
6. 可视化示例
from imblearn.over_sampling import SMOTE
import matplotlib.pyplot as plt
import numpy as np# 创建不平衡数据集
X = np.random.randn(100, 2)
y = np.array([0]*90 + [1]*10)# 应用SMOTE
smote = SMOTE(random_state=42)
X_res, y_res = smote.fit_resample(X, y)# 可视化
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.scatter(X[y==0, 0], X[y==0, 1], label="Majority")
plt.scatter(X[y==1, 0], X[y==1, 1], label="Minority")
plt.title("Original Data")plt.subplot(1, 2, 2)
plt.scatter(X_res[y_res==0, 0], X_res[y_res==0, 1], label="Majority")
plt.scatter(X_res[y_res==1, 0], X_res[y_res==1, 1], label="Minority (SMOTE)")
plt.title("After SMOTE")
plt.legend()
plt.show()
这个示例展示了SMOTE如何通过在少数类样本之间生成新样本来平衡数据集。