在机器学习领域,数据是模型训练的基础,而数据的分布情况往往会对模型的性能产生重要影响。
不平衡样本数据是我们在实际项目中经常会遇到的问题,它可能导致模型对多数类过度拟合,而对少数类的预测能力不足。
本文将详细介绍不平衡样本数据的常见场景、处理方法以及在实践中需要注意的问题,帮助你在模型训练前有效地进行数据再分配。
1. 常见场景
不平衡样本数据是指在分类问题中,不同类别的样本数量存在显著差异的情况。
以下是一些常见的不平衡样本数据场景:
- 金融领域:在信用卡欺诈检测中,正常交易的数量远远超过欺诈交易的数量。正常交易可能占总交易的99%以上,而欺诈交易仅占1%左右。这种不平衡的数据分布使得模型容易偏向于预测正常交易,而忽略欺诈交易。
- 医疗领域:在疾病诊断中,某些罕见疾病的患者数量远少于常见疾病的患者数量。例如,在癌症筛查中,正常人群的数量可能比癌症患者多几十倍甚至上百倍。如果直接使用不平衡的数据训练模型,可能导致模型对罕见疾病的诊断能力不足。
- 网络安全领域:在入侵检测系统中,正常网络访问的流量通常远大于异常流量。正常流量可能占总流量的99%以上,而异常流量仅占1%左右。这种不平衡的数据分布使得模型容易偏向于预测正常流量,而忽略异常流量。
- 电商领域:在客户流失预测中,大多数客户是活跃的,而流失的客户数量相对较少。如果直接使用不平衡的数据训练模型,可能导致模型对流失客户的预测能力不足。
2. 应对策略
在模型训练前,面对不平衡的样本数据,我们通常使用以下几种方法进行处理。
2.1. 欠采样(Undersampling)
欠采样是指从多数类中随机抽取部分样本,使得多数类和少数类的样本数量达到平衡。
这种方法的优点是简单易实现,缺点是可能会丢失一些重要的信息,尤其是当多数类的样本数量较多时。
当数据集较大且多数类的样本数量远多于少数类时,可以使用欠采样方法。
例如,在信用卡欺诈检测中,正常交易的数量远远超过欺诈交易的数量,可以通过欠采样减少正常交易的样本数量,使数据集达到平衡。
比如,下面的代码生成了一个数据集,其中包含了不平衡的两类数据:
from sklearn.datasets import make_classification from imblearn.under_sampling import RandomUnderSampler # 生成不平衡数据 X, y = make_classification( n_classes=2, class_sep=2, weights=[0.99, 0.01], n_informative=3, n_redundant=1, flip_y=0, n_features=20, n_clusters_per_class=1, n_samples=1000, random_state=10, ) # 欠采样 rus = RandomUnderSampler(random_state=42) X_resampled, y_resampled = rus.fit_resample(X, y) print("原始数据中各类样本数量:", sum(y == 0), sum(y == 1)) print("欠采样后各类样本数量:", sum(y_resampled == 0), sum(y_resampled == 1))
欠采样之后,两类数据的数量都是10
:
原始数据中各类样本数量: 990 10 欠采样后各类样本数量: 10 10
2.2. 过采样(Oversampling)
过采样是指通过复制少数类样本或生成新的少数类样本来增加少数类的样本数量,使多数类和少数类的样本数量达到平衡。
常见的过采样方法有随机过采样和SMOTE
(合成少数类过采样技术)。
少数类样本数量较少且数据集较小或中等大小时,可以使用过采样方法。
例如,在医疗领域,某些罕见疾病的患者数量较少,可以通过过采样增加少数类样本数量,使数据集达到平衡。
下面的示例中,数据集仍然使用上一节中生成的测试数据,只是将采样方式做一个修改:
from imblearn.over_sampling import SMOTE # 过采样 smote = SMOTE(random_state=42) X_resampled, y_resampled = smote.fit_resample(X, y) print("原始数据中各类样本数量:", sum(y == 0), sum(y == 1)) print("过采样后各类样本数量:", sum(y_resampled == 0), sum(y_resampled == 1))
运行之后,两类数据的数量都变成了990
:
原始数据中各类样本数量: 990 10 过采样后各类样本数量: 990 990
2.3. 混合采样(Hybrid Sampling)
混合采样是指同时使用欠采样和过采样方法来处理不平衡样本数据。
通常先对多数类进行欠采样,再对少数类进行过采样,以达到更好的平衡效果。
当数据集较大且多数类和少数类的样本数量差异较大时,可以使用混合采样方法。
例如,在网络安全领域,正常网络访问的流量远大于异常流量,可以通过混合采样方法使数据集达到平衡。
下面的示例结合了过采样与欠采样(SMOTE+ENN
)
from imblearn.combine import SMOTEENN # 混合采样 smoteen = SMOTEENN(random_state=42) X_resampled, y_resampled = smoteen.fit_resample(X, y) print("原始数据中各类样本数量:", sum(y == 0), sum(y == 1)) print("混合采样后各类样本数量:", sum(y_resampled == 0), sum(y_resampled == 1))
运行结果:
原始数据中各类样本数量: 990 10 混合采样后各类样本数量: 878 990
2.4. 类别权重调整(Class Weight Adjustment)
类别权重调整是指在模型训练过程中,为不同类别的样本分配不同的权重,使得模型在训练时更加关注少数类样本。
这种方法不需要对数据进行采样,而是通过调整权重来平衡类别之间的差异。
当数据集较大且不希望对数据进行采样时,可以使用类别权重调整方法。
例如,在电商领域,客户流失预测中,大多数客户是活跃的,而流失的客户数量较少,可以通过类别权重调整方法使模型更加关注流失客户。
代码示例:
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from sklearn.datasets import make_classification # 生成不平衡数据 X, y = make_classification( n_samples=1000, n_features=20, n_classes=2, weights=[0.9, 0.1], n_informative=3, n_redundant=1, flip_y=0, random_state=42, ) # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # 类别权重调整 weights = {0: 1, 1: 100} # 为少数类分配更高的权重 clf = RandomForestClassifier(class_weight=weights, random_state=42) clf.fit(X_train, y_train) # 评估模型 y_pred = clf.predict(X_test) print(classification_report(y_test, y_pred))
运行结果如下:
类别权重调整方法可以不采样,直接训练,但是要给少数数据赋予更高的权重:weights = {0: 1, 1: 100}
。
2.5. 其他方法
除了上述方法外,还有一些其他方法可以处理不平衡样本数据,例如:
- 集成学习方法:如
EasyEnsemble
和BalanceCascade
,通过构建多个子数据集并训练多个模型来提高少数类的预测能力。 - 异常检测方法:将少数类视为异常样本,使用异常检测算法进行建模。
- 数据增强方法:通过对少数类样本进行数据增强(如图像旋转、缩放等)来增加少数类样本的数量。
3. 注意事项
在处理不平衡样本数据时,需要重点注意再分配数据时可能带来的问题。
使用欠采样方法时,可能会丢失一些重要的信息,尤其是当多数类的样本数量较多时。
因此,在使用欠采样方法时,需要谨慎选择采样比例,尽量保留重要的信息。
使用过采样方法可能会导致模型对少数类样本过拟合,尤其是在少数类样本数量较少时。
为了避免过拟合,可以结合交叉验证等方法对模型进行评估和调整。
此外,不同的模型对不平衡样本数据的敏感度不同。
例如,决策树模型对不平衡样本数据的敏感度较低,而逻辑回归模型对不平衡样本数据的敏感度较高。
在选择模型时,需要根据数据的特点和问题的需求进行选择。
最后,在评估模型性能时,不能仅仅使用准确率作为评估指标,因为准确率可能会受到不平衡样本数据的影响。
可以使用召回率、F1分数、ROC曲线下面积等指标来评估模型的性能。
4. 总结
本文介绍了欠采样、过采样、混合采样、类别权重调整和其他几种处理不平衡样本数据的方法,并通过 scikit-learn
示例代码展示了这些方法的实现过程。
在处理不平衡样本数据时,还需要注意信息丢失、过拟合、模型选择和评估指标等问题。
希望本文能够帮助大家更好地理解和应用这些方法,提高模型的性能。