文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

应对机器学习中类不平衡的10种技巧

2024-12-24 15:55

关注

示例:检测信用卡欺诈交易。如下图所示,欺诈交易大约为400,而非欺诈交易大约为90000。

 

类不平衡是机器学习中的常见问题,尤其是在分类问题中。不平衡数据可能会长时间妨碍我们的模型准确性。

类不平衡出现在许多领域,包括:

类失衡问题

当每个类别中的样本数量大致相等时,大多数机器学习算法效果最佳。这是因为大多数算法都是为了最大化精确度和减少误差而设计的。

然而,如果数据集不平衡,那么在这种情况下,仅仅通过预测多数类就可以获得相当高的准确率,但是无法捕捉少数类,这通常是创建模型的首要目的。

信用卡欺诈检测示例

假设我们有一个信用卡公司的数据集,我们必须找出信用卡交易是否是欺诈性的。

但是这里有个陷阱……欺诈交易相对罕见,只有6%的交易是欺诈行为。

现在,在你还没有开始之前,你是否能想到问题应该如何解决?想象一下,如果你根本不花时间训练模型。相反,如果你只编写了一行总是预测“没有欺诈性交易”的代码,该怎么办?

  1. def transaction(transaction_data): 
  2.     return 'No fradulent transaction' 

好吧,你猜怎么着?你的“解决方案”将具有94%的准确性!

不幸的是,这种准确性令人误解。

所有这些非欺诈性的交易,你都将拥有100%的准确性。

那些欺诈性的交易,你的准确性为0%。

仅仅因为大多数交易不是欺诈性的(不是因为你的模型很好),你的总体准确性就很高。

这显然是一个问题,因为许多机器学习算法都旨在最大程度地提高整体准确性。在本文中,我们将看到处理不平衡数据的不同技术。

数据

我们将在本文中使用信用卡欺诈检测数据集,你可以从此处找到该数据集。

https://www.kaggle.com/mlg-ulb/creditcardfraud

加载数据后,显示数据集的前五行。

 

 

  1. check the target variable that is fraudulet and not fradulent transactiondata['Class'].value_counts()# 0 -> non fraudulent 
  2. # 1 -> fraudulent 

 

 

  1. # visualize the target variable 
  2. g = sns.countplot(data['Class']) 
  3. g.set_xticklabels(['Not Fraud','Fraud']) 
  4. plt.show() 

 

你可以清楚地看到数据集之间存在巨大差异。9000次非欺诈性交易和492次欺诈性交易。

指标陷阱

新开发人员用户在处理不平衡数据集时遇到的一个主要问题与用于评估其模型的指标有关。使用更简单的指标,比如准确度得分,可能会产生误导。在具有高度不平衡类的数据集中,分类器总是在不进行特征分析的情况下“预测”最常见的类,并且它的准确率很高,显然不是正确的。

让我们做这个实验,使用简单的XGBClassifier和无特征工程:

  1. # import linrary 
  2. from xgboost import XGBClassifier 
  3. xgb_model = XGBClassifier().fit(x_train, y_train)# predictxgb_y_predict = xgb_model.predict(x_test)# accuracy scorexgb_score = accuracy_score(xgb_y_predict, y_test)print('Accuracy score is:', xbg_score)OUTPUT 
  4. Accuracy score is: 0.992 

我们可以看到99%的准确度,我们得到的是非常高的准确度,因为它预测大多数类别为0(非欺诈性)。

重采样技术

一种处理高度不平衡数据集的广泛采用的技术称为重采样。它包括从多数类中删除样本(欠采样)和/或从少数类中添加更多示例(过采样)。

 

尽管平衡类有很多好处,但是这些技巧也有缺点。

过采样最简单的实现是复制少数群体类别的随机记录,这可能会导致过度捕捞。

欠采样最简单的实现涉及从多数类中删除随机记录,这可能会导致信息丢失。

让我们用信用卡欺诈检测示例来实现它。

我们将首先将类0和类1分开。

  1. # class count 
  2. class_count_0, class_count_1 = data['Class'].value_counts() 
  3. # Separate classclass_0 = data[data['Class'] == 0] 
  4. class_1 = data[data['Class'] == 1]# print the shape of the class 
  5. print('class 0:', class_0.shape) 
  6. print('class 1:', class_1.shape 

 

1.随机欠采样

欠采样可以定义为删除多数类的观察值。这是在多数类和少数类被平衡之前进行的。

当你拥有大量数据时,欠采样可能是一个不错的选择,比如数百万行。但是欠采样的一个缺点是我们可能删除了有价值的信息。

 

 

  1. class_0_under = class_0.sample(class_count_1) 
  2. test_under = pd.concat([class_0_under, class_1], axis=0) 
  3. print("total class of 1 and0:",test_under['Class'].value_counts())# plot the count after under-sampeling 
  4. test_under['Class'].value_counts().plot(kind='bar', title='count (target)'

2.随机过采样

过采样可以定义为向少数类添加更多副本。当你没有大量数据要处理时,过采样可能是一个不错的选择。

欠采样时要考虑的一个弊端是,它可能导致过拟合并导致测试集泛化不佳。

  1. class_1_over = class_1.sample(class_count_0, replace=True
  2. test_over = pd.concat([class_1_over, class_0], axis=0) 
  3. print("total class of 1 and 0:",test_under['Class'].value_counts())# plot the count after under-sampeling 
  4. test_over['Class'].value_counts().plot(kind='bar', title='count (target)'

 

使用不平衡学习python模块平衡数据

在科学文献中已经提出了许多更复杂的重采样技术。

例如,我们可以将多数类的记录聚类,并通过从每个聚类中删除记录来进行欠采样,从而寻求保留信息。在过采样中,我们可以为这些副本引入较小的变化,从而创建更多样的合成样本,而不是创建少数群体记录的精确副本。

让我们使用Python库 imbalanced-learn应用其中一些重采样技术。它与scikit-learn兼容,并且是scikit-learn-contrib项目的一部分。

  1. import imblearn 

3.使用imblearn进行随机欠采样

RandomUnderSampler通过为目标类别随机选择数据子集来平衡数据的快速简便方法。通过随机选择有或没有替代品的样本对多数类别进行欠采样。

  1. # import library 
  2. from imblearn.under_sampling import RandomUnderSampler 
  3. rus = RandomUnderSampler(random_state=42, replacement=True)# fit predictor and target variable 
  4. x_rus, y_rus = rus.fit_resample(x, y)print('original dataset shape:', Counter(y)) 
  5. print('Resample dataset shape', Counter(y_rus)) 

 

4.使用imblearn进行随机过采样

解决不平衡数据的一种方法是在少数群体中生成新样本。最幼稚的策略是通过随机采样替换当前可用的采样来生成新的采样。随机过采样提供了这样一个方案。

  1. # import library 
  2. from imblearn.over_sampling import RandomOverSampler 
  3. ros = RandomOverSampler(random_state=42) 
  4. # fit predictor and target variablex_ros, y_ros = ros.fit_resample(x, y)print('Original dataset shape', Counter(y)) 
  5. print('Resample dataset shape', Counter(y_ros)) 

 

5.欠采样:Tomek链接

Tomek链接是一对非常接近的实例,但类别相反。删除每对多数类的实例会增加两个类之间的空间,从而有助于分类过程。

如果两个样本是彼此的最近邻,则存在Tomek的链接

 

在下面的代码中,我们将用于ratio='majority'对多数类进行重新采样。

  1. # import library 
  2. from imblearn.under_sampling import TomekLinks 
  3. tl = RandomOverSampler(sampling_strategy='majority'
  4. # fit predictor and target variablex_tl, y_tl = ros.fit_resample(x, y)print('Original dataset shape', Counter(y)) 
  5. print('Resample dataset shape', Counter(y_ros)) 

 

6. Synthetic Minority Oversampling Technique (SMOTE)

该技术为合成少数过采样技术。

SMOTE(合成少数过采样技术)的工作原理是从少数类中随机选取一个点并计算该点的k近邻。合成点被添加到所选的点和它的相邻点之间。

 

SMOTE算法通过以下四个简单步骤工作:

  1. # import library 
  2. from imblearn.over_sampling import SMOTE 
  3. smote = SMOTE()# fit predictor and target variablex_smote, y_smote = smote.fit_resample(x, y)print('Original dataset shape', Counter(y)) 
  4. print('Resample dataset shape', Counter(y_ros)) 

 

7. NearMiss

NearMiss是欠采样技术。与其使用距离重新采样少数类,不如将多数类等同于少数类。

  1. from imblearn.under_sampling import NearMiss 
  2. nm = NearMiss()x_nm, y_nm = nm.fit_resample(x, y)print('Original dataset shape:', Counter(y)) 
  3. print('Resample dataset shape:', Counter(y_nm)) 

 

8.更改性能指标

评估不平衡数据集时,准确性不是最佳的度量标准,因为它可能会产生误导。

可以提供更好洞察力的指标是:

换句话说,如果你从每个类中随机选择一个观察值,你的模型能够正确“排序”它们的概率有多大?

9.惩罚算法(成本敏感训练)

下一个策略是使用惩罚性学习算法,该算法会增加少数类分类错误的成本。

这项技术的一种流行算法是Penalized-SVM。

在训练过程中,我们可以使用参数class_weight='balanced'来惩罚少数类的错误,惩罚量与代表性不足的程度成正比。

如果我们想为支持向量机算法启用概率估计,我们还希望包含参数probability=True。

让我们在原始不平衡数据集上使用Penalized-SVM训练模型:

  1. load library 
  2. from sklearn.svm import SVC 
  3. # we can add class_weight='balanced' to add panalize mistake 
  4. svc_model = SVC(class_weight='balanced', probability=True
  5. svc_model.fit(x_train, y_train)svc_predict = svc_model.predict(x_test)# check performanceprint('ROCAUC score:',roc_auc_score(y_test, svc_predict)) 
  6. print('Accuracy score:',accuracy_score(y_test, svc_predict)) 
  7. print('F1 score:',f1_score(y_test, svc_predict)) 

 

10.更改算法

尽管在每个机器学习问题中,尝试各种算法都是一个很好的经验法则,但是对于不平衡的数据集而言,这尤其有利。

决策树经常在不平衡的数据上表现良好。在现代机器学习中,树集成(随机森林,梯度增强树等)几乎总是胜过单个决策树,因此我们将直接跳到:

基于树的算法通过学习 if / else 问题的层次结构来工作。这可以强制解决两个类。

  1. load library 
  2. from sklearn.ensemble import RandomForestClassifier 
  3. rfc = RandomForestClassifier()# fit the predictor and targetrfc.fit(x_train, y_train)# predictrfc_predict = rfc.predict(x_test)# check performanceprint('ROCAUC score:',roc_auc_score(y_test, rfc_predict)) 
  4. print('Accuracy score:',accuracy_score(y_test, rfc_predict)) 
  5. print('F1 score:',f1_score(y_test, rfc_predict)) 

 

欠采样的优点和缺点

优点

缺点

过采样的优缺点

优点

缺点

你可以在我的GitHub存储库中检查代码的实现。

https://github.com/benai9916/Handle-imbalanced-data/tree/master

结论

总而言之,在本文中,我们已经看到了处理数据集中的类不平衡的各种技术。处理不平衡数据时,实际上有很多方法可以尝试。希望本文对你有所帮助。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯