原谅把你带走的雨天
在渐渐模糊的窗前
每个人最后都要说再见
原谅被你带走的永远
微笑着容易过一天
也许是我已经 老了一点
那些日子你会不会舍不得
思念就像关不紧的门
空气里有幸福的灰尘
否则为何闭上眼睛的时候
又全都想起了
谁都别说
让我一个人躲一躲
你的承诺
我竟然没怀疑过
反反覆覆
要不是当初深深深爱过
我试着恨你
却想起你的笑容
🎵 陈楚生/单依纯《原谅》
在机器学习和数据科学中,数据集的不平衡是一个常见的问题。当一个数据集中的某一类样本数量远远超过其他类时,模型往往会偏向多数类,从而影响分类器的性能。为了解决这一问题,研究人员提出了多种技术,其中过采样和欠采样是两种最常用的方法。本文将详细介绍过采样和欠采样的概念、原理以及在实际应用中的注意事项。
什么是不平衡数据集?
不平衡数据集是指某些类的样本数量显著多于其他类的情况。假设有一个二分类问题,其中类别0有950个样本,而类别1只有50个样本。由于类别0的样本数量远远多于类别1,模型在训练时更容易学习到类别0的特征,忽略类别1,从而导致分类性能下降。
过采样(Oversampling)
过采样是一种通过增加少数类样本数量来平衡数据集的方法。其主要思想是生成新的少数类样本,使少数类的样本数量增加到与多数类相同或相近。
常见的过采样方法
随机过采样(Random Oversampling):
通过随机复制少数类样本来增加其数量。这种方法简单易行,但可能导致过拟合,因为它没有引入新的信息。
from imblearn.over_sampling import RandomOverSamplerros = RandomOverSampler(random_state=42)
X_resampled, y_resampled = ros.fit_resample(X_train, y_train)
SMOTE(Synthetic Minority Over-sampling Technique):
通过在少数类样本之间插值生成新的样本。SMOTE不仅复制少数类样本,还生成新的合成样本,从而减少了过拟合的风险。
from imblearn.over_sampling import SMOTEsmote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
ADASYN(Adaptive Synthetic Sampling Approach for Imbalanced Learning):
ADASYN是对SMOTE的改进,它根据样本的分类难度自适应地生成合成样本。分类难度大的样本生成更多的新样本,分类难度小的样本生成较少的新样本。
from imblearn.over_sampling import ADASYNadasyn = ADASYN(random_state=42)
X_resampled, y_resampled = adasyn.fit_resample(X_train, y_train)
欠采样(Undersampling)
欠采样是一种通过减少多数类样本数量来平衡数据集的方法。其主要思想是减少多数类样本的数量,使其与少数类的样本数量接近,从而达到平衡数据集的目的。
常见的欠采样方法
随机欠采样(Random Undersampling):
随机删除多数类样本,使其数量减少到与少数类相同或相近。虽然简单,但可能会丢失大量有用信息,导致模型性能下降。
from imblearn.under_sampling import RandomUnderSamplerrus = RandomUnderSampler(random_state=42)
X_resampled, y_resampled = rus.fit_resample(X_train, y_train)
集成欠采样(Cluster Centroids):
通过聚类算法将多数类样本聚类为若干个簇,并用簇的中心代替原始样本,从而减少多数类样本的数量。
from imblearn.under_sampling import ClusterCentroidscc = ClusterCentroids(random_state=42)
X_resampled, y_resampled = cc.fit_resample(X_train, y_train)
Tomek Links:
通过删除与少数类样本最接近的多数类样本对(Tomek链接),从而减少多数类样本数量。这种方法不仅减少了多数类样本,还清除了数据集中的噪声样本。
from imblearn.under_sampling import TomekLinkstl = TomekLinks()
X_resampled, y_resampled = tl.fit_resample(X_train, y_train)
过采样与欠采样的选择
选择过采样还是欠采样取决于具体的数据集和问题:
-
过采样适用于:
- 少数类样本特别少,直接删除多数类样本会导致信息丢失过多。
- 数据集足够小,生成合成样本不会显著增加计算开销。
-
欠采样适用于:
- 多数类样本特别多,随机复制少数类样本会导致过拟合。
- 数据集足够大,删除部分多数类样本不会导致信息丢失过多。
在实际应用中,有时可以结合过采样和欠采样的方法,进一步提高模型性能。例如,先通过欠采样减少多数类样本数量,再通过过采样增加少数类样本数量,从而达到更好的平衡效果。
实战案例:结合过采样和欠采样
以下是一个结合过采样和欠采样的方法来平衡数据集的示例:
from imblearn.combine import SMOTETomek
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from collections import Counter# 生成一个不平衡的数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2, n_redundant=10, n_clusters_per_class=1, weights=[0.9, 0.1], flip_y=0, random_state=42)# 查看数据分布
print(f"原始数据集类别分布: {Counter(y)}")# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)# 使用SMOTETomek进行过采样和欠采样
smote_tomek = SMOTETomek(random_state=42)
X_resampled, y_resampled = smote_tomek.fit_resample(X_train, y_train)# 查看过采样和欠采样后的数据分布
print(f"过采样和欠采样后数据集类别分布: {Counter(y_resampled)}")
结论
过采样和欠采样是处理不平衡数据集的两种重要技术。过采样通过增加少数类样本数量来平衡数据集,而欠采样则通过减少多数类样本数量来达到同样的目的。根据具体问题和数据集的特点,选择合适的方法可以显著提高模型的性能。在实际应用中,结合使用这两种方法往往可以取得更好的效果。希望本文能帮助你理解并掌握过采样和欠采样的基本原理和实现方法,为你的机器学习项目提供支持。如果你有任何问题或建议,欢迎在评论区留言!