0%

欠采样undersampling,过采样oversampling

又称为 上采样 下采样

数据不平衡问题

默认阈值(比如二分类正反例中0.5)导致模型输出倾向于数据多的类别

解决办法

  1. 调整分类阈值,偏向数据少的类别
  2. 选择ROC或F1作为评估标准
  3. 过采样、欠采样

过采样

将样本数量少的类别生成的样本数量和数量多的类别一样多,合成新的样本来缓解类不平衡

注:随机过采样采用简单复制样本增加少数类样本,导致模型不够泛化

欠采样

从数量多的类别中抽取与等量的样本数据,抛弃一些样本来缓解类不平衡

SMOTE

经典过采样

人工合成数据(Synthetic Minority Over-sampling Technique)

分析数量较少类别的样本数据,基于“插值”来为少数类合成新样本,并添加到数据集

  1. 确定采样倍率 N(N为整数,N>=1)
  2. 计算少数类 样本x(i)到本样本欧式距离,得到x(i)的k个近邻
  3. 随机选择近邻x^, xnew = x + rand(0,1)*(x^-x),重复N次,得到N个新样本
  4. 对所有少数类样本x(i)执行1,2操作,合成NT个新样本

欠采样(Undersampling)和过采样(Oversampling)是处理不平衡数据集的常见方法,用于解决正负样本数量差异较大的情况。欠采样是减少多数类样本的数量,而过采样是增加少数类样本的数量。

以下是使用Python实现欠采样和过采样的示例代码,分别使用imbalanced-learn库来演示:

首先,确保已安装 imbalanced-learn 库,可以通过以下命令安装:

1
pip install imbalanced-learn

接下来,使用下面的代码示例:

  1. 欠采样示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from imblearn.under_sampling import RandomUnderSampler
from collections import Counter
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt

# 创建一个不平衡的示例数据集
X, y = make_classification(n_samples=1000, weights=[0.99], random_state=42)

# 统计类别分布
counter = Counter(y)
print("Original class distribution:", counter)

# 进行欠采样
undersample = RandomUnderSampler(sampling_strategy=0.5, random_state=42)
X_resampled, y_resampled = undersample.fit_resample(X, y)

# 统计欠采样后的类别分布
counter_resampled = Counter(y_resampled)
print("Resampled class distribution:", counter_resampled)

# 绘制类别分布图
plt.bar(counter_resampled.keys(), counter_resampled.values())
plt.xlabel('Class')
plt.ylabel('Count')
plt.title('Resampled Class Distribution')
plt.show()
  1. 过采样示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from imblearn.over_sampling import RandomOverSampler

# 创建一个不平衡的示例数据集
X, y = make_classification(n_samples=1000, weights=[0.99], random_state=42)

# 统计类别分布
counter = Counter(y)
print("Original class distribution:", counter)

# 进行过采样
oversample = RandomOverSampler(sampling_strategy=0.5, random_state=42)
X_resampled, y_resampled = oversample.fit_resample(X, y)

# 统计过采样后的类别分布
counter_resampled = Counter(y_resampled)
print("Resampled class distribution:", counter_resampled)

# 绘制类别分布图
plt.bar(counter_resampled.keys(), counter_resampled.values())
plt.xlabel('Class')
plt.ylabel('Count')
plt.title('Resampled Class Distribution')
plt.show()

在上述代码中,我们使用make_classification函数创建了一个不平衡的示例数据集,然后分别使用RandomUnderSamplerRandomOverSampler进行欠采样和过采样。最后,绘制了欠采样和过采样后的类别分布图。

请注意,实际应用中您可能需要调整采样策略、超参数等来满足具体问题的需求。