重采样(Resampling) 是处理数据不平衡问题的核心技术之一,通过调整训练数据中不同类别的样本比例,使模型更关注少数类。
重采样的两类核心方法
过采样(Oversampling)
目标:增加少数类样本数量,平衡类别分布。
适用场景:当少数类样本数量较少时(如医疗罕见病诊断、金融欺诈检测)。
随机过采样(Random Oversampling)
- 原理:通过随机复制少数类样本,直接增加其数量。
- 步骤:
- 统计少数类样本数量$N_{\text{minority}}$。
- 从少数类中随机选择样本(允许重复选择),直到其数量与多数类平衡。
- 优点:简单快速,适用于小规模数据。
- 缺点:
- 容易导致模型过拟合(重复样本降低了泛化能力)。
- 对噪声样本敏感(可能放大噪声的影响)。
代码示例:
from sklearn.utils import resample # 假设 minority_df 是少数类样本,majority_df 是多数类样本 minority_upsampled = resample(minority_df, replace=True, # 允许重复采样 n_samples=len(majority_df), random_state=42) balanced_df = pd.concat([majority_df, minority_upsampled])
SMOTE(Synthetic Minority Oversampling Technique)
- 原理:通过线性插值生成新的合成样本,而非简单复制。
- 对每个少数类样本$x_i$,随机选择其最近的 k个同类邻居。
- 在$x_i$和邻居之间随机选择一个点,生成新样本。
- 步骤:
- 计算少数类样本的k 近邻(通常 k=5)。
- 在样本与邻居的连线上随机插值生成新样本。
- 优点:缓解过拟合问题,生成多样化的新样本。
- 缺点:
- 可能生成不合理的样本(尤其在类别边界模糊时)。
- 对高维数据效果可能下降。
代码示例:
from imblearn.over_sampling import SMOTE smote = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42) X_resampled, y_resampled = smote.fit_resample(X, y)
ADASYN(Adaptive Synthetic Sampling)
- 原理:动态调整生成样本的数量,优先在分类边界附近生成样本。
- 根据少数类样本的密度分布,对难以分类的样本生成更多合成数据。
- 步骤:
- 计算每个少数类样本需要生成的新样本数量(密度低的区域生成更多)。
- 使用类似SMOTE的插值方法生成样本。
- 优点:更关注分类边界,提升模型对复杂分布的捕捉能力。
- 缺点:可能放大噪声的影响。
代码示例:
from imblearn.over_sampling import ADASYN adasyn = ADASYN(sampling_strategy='auto', n_neighbors=5, random_state=42) X_resampled, y_resampled = adasyn.fit_resample(X, y)
其他高级过采样方法
- Borderline-SMOTE:仅对处于类别边界的少数类样本生成新数据。
- SVMSMOTE:使用SVM支持向量机识别边界样本后再生成数据。
欠采样(Undersampling)
目标:减少多数类样本数量,平衡类别分布。
适用场景:当多数类样本数量极大时(如用户流失预测、网络入侵检测)。
随机欠采样(Random Undersampling)
- 原理:随机删除多数类样本,直到类别平衡。
- 步骤:
- 统计多数类样本数量$N_{\text{majority}}$。
- 随机选择$N_{\text{minority}}$ 个多数类样本保留,其余删除。
- 优点:简单高效,降低计算成本。
- 缺点:
- 可能丢失重要信息(尤其是多数类内部的关键模式)。
- 对噪声敏感(可能保留噪声样本)。
代码示例:
from sklearn.utils import resample # 假设 majority_df 是多数类样本 majority_downsampled = resample(majority_df, replace=False, # 不允许重复采样 n_samples=len(minority_df), random_state=42) balanced_df = pd.concat([minority_df, majority_downsampled])
NearMiss
- 原理:基于距离选择与少数类样本最相关的多数类样本。
- NearMiss-1:保留与每个少数类样本最近的多数类样本。
- NearMiss-2:保留与每个少数类样本最远的多数类样本。
- NearMiss-3:为每个少数类样本保留一定数量的最近多数类样本。
- 优点:保留与少数类相关的关键多数类样本。
- 缺点:计算复杂度较高(需计算样本间距离)。
代码示例:
from imblearn.under_sampling import NearMiss near_miss = NearMiss(version=3, n_neighbors=3) X_resampled, y_resampled = near_miss.fit_resample(X, y)
Tomek Links
- 原理:删除多数类中与少数类样本形成Tomek Link的样本。
- 若两个不同类别的样本互为最近邻,则称为Tomek Link,通常位于类别边界。
- 步骤:
- 找到所有Tomek Link对。
- 删除其中的多数类样本。
- 优点:清理类别边界,提升模型对边界的区分能力。
- 缺点:单独使用可能欠采样不足,需结合其他方法。
代码示例:
from imblearn.under_sampling import TomekLinks tl = TomekLinks() X_resampled, y_resampled = tl.fit_resample(X, y)
其他高级欠采样方法
- Cluster Centroids:对多数类样本聚类后,用聚类中心代替原始样本。
- ENN(Edited Nearest Neighbours):删除被多数近邻包围的多数类样本。
组合方法(Hybrid Approaches)
结合过采样和欠采样,兼顾信息保留与计算效率。
- SMOTE + Tomek Links:
- 使用SMOTE生成少数类样本。
- 用Tomek Links清理边界噪声。
- SMOTE + ENN:
- 生成合成样本。
- 删除噪声样本。
代码示例:
from imblearn.combine import SMOTEENN smote_enn = SMOTEENN(smote=SMOTE(sampling_strategy='auto'), enn=EditedNearestNeighbours()) X_resampled, y_resampled = smote_enn.fit_resample(X, y)
重采样的注意事项
- 避免数据泄露:先拆分训练集和测试集,再对训练集重采样(测试集必须保持原始分布)。
- 评估指标选择:使用F1-Score、AUC-ROC等对不平衡数据更敏感的指标。
- 过采样与欠采样的权衡:过采样适合小规模数据,但可能过拟合;欠采样适合大规模数据,但可能丢失信息。
- 领域知识结合:例如在金融欺诈检测中,需谨慎生成合成样本,避免破坏交易模式。