不平衡学习的方法 Learning from Imbalanced Data

2023-12-05 04:48

本文主要是介绍不平衡学习的方法 Learning from Imbalanced Data,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前做二分类预测的时候,遇到了正负样本比例严重不平衡的情况,甚至有些比例达到了50:1,如果直接在此基础上做预测,对于样本量较小的类的召回率会极低,这类不平衡数据该如何处理呢?

不平衡数据的定义


顾名思义即我们的数据集样本类别极不均衡,以二分类问题为例,数据集中的多数类 为 S m a x S_{max} Smax,少数类为 S m i n S_{min} Smin,通常情况下把多数类样本的比例为 100 : 1 100:1 100:1 1000 : 1 1000:1 1000:1,甚至是 10000 : 1 10000:1 10000:1这种情况下为不平衡数据。

为什么不平衡学习


因为传统的学习方法以降低总体分类精度为目标,将所有样本一视同仁,同等对待,造成了分类器在多数类的分类精度较高而在少数类的分类精 度很低。例如上面正负样本50:1的例子,算法就算全部预测为另一样本,准确率也会达到98%(50/51),因此传统的学习算法在不平衡数据集中具有较大的局限性。

不平衡学习的方法


解决方法主要分为两个方面。

  • 第一种方案主要从数据的角度出发,主要方法为抽样,既然我们的样本是不平衡的,那么可以通过某种策略进行抽样,从而让我们的数据相对均衡一些;
  • 第二种方案从算法的角度出发, 考虑不同误分类情况代价的差异性对算法进行优化,使得我们的算法在不平衡数据下也能有较好的效果。

采样


随机采样


采样算法通过某一种策略改变样本的类别分布,以达到将不平衡分布的样本转化为相对平衡分布的样本的目的,而随机采样是采样算法中最简单也最直观易 懂的一种方法。随机采样主要分为两种类型,分别为随机欠采样和随机过采样两种。
随机欠采样顾名思义即从多数类 S m a x S_{max} Smax中随机选择少量样本 E E E再合 并原有少数类样本作为新的训练数据集,新数据集为 S m i n + E S_{min}+E Smin+E,随机欠采样有两种类型分别为有放回和无放回两种,无放回欠采样在对多数类某样本被采 样后不会再被重复采样,有放回采样则有可能。
随机过采样则正好相反,即通过多次有放回随机采样从少数类 S m i n S_{min} Smin中抽取数据集 E E E,采样的数量要大 于原有少数类的数量,最终的训练集为 S m a x + E S_{max}+E Smax+E
显然,随机采样是通过改变多数类或者少数类的样本比例达到修改样本分类分布的目的,其中也存在着诸多的问题,例如随机欠采样,由于丢失了一些样本,造成一些信息的缺失,如果未被采样的样本具有重要的信息呢?而过采样扩大了数据集,训练模型的复杂度会加大,而且有可能造成过拟合的情况。


SMOTE算法

SMOTE全称是Synthetic Minority Oversampling Technique即合成少数类过采样技术,SMOTE算法的基本思想SMOTE算法的基本思想是对少数类样本进行分 析并根据少数类样本人工合成新样本添加到数据集中,具体如图2所示,算法流程如下。

  1. 对于少数类中每一个样本 x x x,以欧氏距离为标准计算它到少数类样本集 S m i n S_{min} Smin中所有样本的距离,得到其k近邻。
  2. 根据样本不平衡比例设置一个采样比例以确定采样倍率 N N N,对于每一个少数类样本 x x x,从其k近邻中随机选择若干个样本,假设选择的近邻为 x ^ \hat{x} x^
  3. 对于每一个随机选出的近邻 x ^ \hat{x} x^,分别与原样本按照如下的公式构建新的样本。
    x n e w = x + r a n d ( 0 , 1 ) ∗ ( x ^ − x ) x_{new} = x + rand(0,1)*(\hat{x}-x) xnew=x+rand(0,1)(x^x)
![SMOTE算法](https://img-blog.csdnimg.cn/img_convert/2e83ac3267d6de585a014a5e63e0821c.png) 图2 SMOTE算法
SMOTE算法摈弃了随机采样复制样本的做法,使得算法的性能有所提升,但由于每个少数样本都会产生新样本,也会产生样本重叠的问题,下面介绍其改进算法:

Borderline-SMOTE算法


在Borderline-SMOTE中,若少数类样本的每个样本 x i x_i xi求k近邻,记作 S i − k n n S_i-knn Siknn,且 S i − k n n S_i-knn Siknn属于整个样本集合 S S S而不再是少数类样本,若满足
k 2 < ∣ s i − k n n ∩ s m a x ∣ < k \frac{k}{2}<|s_{i-knn}\cap s_{max}|<k 2k<siknnsmax<k
即k近邻中超过一半是多数样本。
则将样本 x i x_i xi加入DANGER集合,显然DANGER集合代表了接近分类边界的样本,将DANGER当作SMOTE种子样本的输入生成新样本。特别地,当上述条件取右边界,即k近邻中全部样本都是多数类时此样本不会被选择为种样本生成新样本,此情况下的样本为噪音。

![图3 Borderline-SMOTE算法](https://img-blog.csdnimg.cn/img_convert/6a4d264f3db46516d2142a16b6a184fa.png) 图3 Borderline-SMOTE算法

Informed Undersampling

前面讲了关于过采样的的算法,那么下面就是欠采样算法informed undersampling,informed undersampling采样技术主要有两种方法分别是EasyEnsemble算法和BalanceCascade算法。
EasyEnsemble算法如下图4所示,此算法类似于随机森林的Bagging方法,它把数据划分为两部分,分别是多数类样本和少数类样 本,对于多数类样本 S m a j S_maj Smaj,通过n次有放回抽样生成n份子集,少数类样本分别和这n份样本合并训练一个模型,这样可以得到n个模型,最终的模型是 这n个模型预测结果的平均值

![Informed Undersampling](https://img-blog.csdnimg.cn/img_convert/3de204f29ed70c73e101be94d97a86a7.png)

BalanceCascade算法是一种级联算法,BalanceCascade从多数类 S m a x S_{max} Smax中有效地选择N且满 足 ∣ N ∣ = ∣ S m i n ∣ \mid N \mid=\mid S_{min} \mid N=Smin,将N和 S m i n S_{min} Smin合并为新的数据集进行训练,新训练集对每个多数类样本 x i x_i xi进行预测 若预测对则 S m a x = S m a j − x i S_{max}=S_{maj}-x_i Smax=Smajxi。依次迭代直到满足某一停止条件,最终的模型是多次迭代模型的组合。
核心思想:使用之前已形成的集成分类器来为下一次训练选择多类样本,然后再进行欠抽样。

代价敏感学习


代价敏感学习算法(Cost-Sensitive Learning)主要从算法层面上解决不平衡数据学习,代价敏感学习方法的核心要素是代价矩阵,我们注意到在实际的应用中不同类型的误分类情况导致的代价是不一样的,例如在医疗中,“将病 人误疹为健康人”和“将健康人误疹为病人”的代价不同,因此 我们定义代价矩阵如下图所示。

![代价矩阵](https://img-blog.csdnimg.cn/img_convert/c8f8eb96f9c3f8070bd5ab1a7b67cef2.png) 代价矩阵

代价敏感学习方法


基于以上代价矩阵的分析,代价敏感学习方法主要有以下三种实现方式

  1. 从学习模型出发,着眼于对某一具体学习方法的改造,使之能适应不平衡数据下的学习,研究者们针对不同的学习模型如感知机,支持向量机,决策 树,神经网络等分别提出了其代价敏感的版本。以代价敏感的决策树为例,可从三个方面对其进行改进以适应不平衡数据的学习,这三个方面分别是决策阈值的选择 方面、分裂标准的选择方面、剪枝方面,这三个方面中都可以将代价矩阵引入,具体实现算法可参考参考文献中的相关文章。
  2. 从贝叶斯风险理论出发,把代价敏感学习看成是分类结果的一种后处理,按照传统方法学习到一个模型,以实现损失最小为目标对结果进行调整,优化公式如下所示。此方法的优点在于它可以不依赖所用具体的分类器,但是缺点也很明显它要求分类器输出值为概率。
    H ( x ) = arg ⁡ min ⁡ i ( ∑ j ∈ { + , − } P ( j ∣ x c ( i , j ) ) H(x) = \arg \min_{i}(\sum_{j\in \{+,-\}}P(j|xc(i,j)) H(x)=argimin(j{+,}P(jxc(i,j))
  3. 从预处理的角度出发,将代价用于权重的调整,使得分类器满足代价敏感的特性,下面讲解一种基于Adaboost的权重更新策略。

AdaCost算法

让我们先来简单回顾一下Adaboost算法,如下图6所示。Adaboost算法通过反复迭代,每一轮迭代学习到一个分类器,并根据当前分类器 的表现更新样本的权重,如图中红框所示,其更新策略为正确分类样本权重降低,错误分类样本权重加大,最终的模型是多次迭代模型的一个加权线性组合,分类越 准确的分类器将会获得越大的权重。

Adaboost算法

AdaCost算法修改了Adaboost算法的权重更新策略,其基本思想是对于代价高的误分类样本大大地提高其权重,而对于代价高的正确分类样 本适当地降低其权重,使其权重降低相对较小。总体思想是代价高样本权重增加得大降低得慢。其样本权重按照如下公式进行更新。其 中 β + \beta_+ β+ β − \beta_- β分别表示样本被正确和错误分类情况下 β \beta β的取值。
D t + 1 ( i ) = D t ( i ) exp ⁡ ( − α t h t ( x i ) y i β i ) Z t \frac{D_{t+1}(i) = D_t(i)\exp (-\alpha_t h_t(x_i)y_i\beta_i)}{Z_t} ZtDt+1(i)=Dt(i)exp(αtht(xi)yiβi)
β + = − 0.5 C i + 0.5 \beta_+ = -0.5C_i+0.5 β+=0.5Ci+0.5
β − = 0.5 C i + 0.5 \beta_- = 0.5C_i+0.5 β=0.5Ci+0.5

不平衡学习的评价方法


正确率和F值


这里写图片描述
Precidsion = tp/(tp+fn)
Recall = tp/(tp+fn)
F-Measure = (1+β)²RecallPrecision / (β²*Recall+Precision)
β取值一般为1;
Accuracy = (tp+tn)/(pc+nc);
ErrorRate = 1- accuracy

正确率和F值的计算都是基于混淆矩阵(Confusion Matrix)的,混淆矩阵如下图7所示,每行代表预测情况,每列代表实际类别,TP,FP,FN,TN分别代表正类正确分类数量,预测为正类但是真实为负类,预测为负类但是真实为正类,负类正确分类数量。

G-Mean

G-Mean是另外一个指标,也能评价不平衡数据的模型表现,其计算公式如下。
G − m e a n = T P T P + F N ∗ T N T N + F P G-mean = \sqrt {\frac{TP}{TP+FN}* \frac{TN}{TN+FP}} Gmean=TP+FNTPTN+FPTN
下面将会介绍TP、TN等

ROC曲线和AUC

为了介绍ROC曲线首先引入两个是,分别是FP_rate和TP_rate,它们分别表示1-负类召回率和正类召回率,显然模型表示最好的时候 FP_rate=0且TP_rate=1,我们以FP_rate为横坐标,TP_rate为纵坐标可以得到点(FP_rate,TP_rate),通过调 整模型预测的阈值可以得到不同的点,将这些点可以连成一条曲线,这条曲线叫做接受者工作特征曲线(Receiver Operating Characteristic Curve,简称ROC曲线)如下图8所示。显然A点为最优点,ROC曲线越靠近A点代表模型表现越好,曲线下面积(Area Under Curve, AUC)越大,AUC是衡量模型表现好坏的一个重要指标。

![ROC](https://img-blog.csdnimg.cn/img_convert/ef63428ab4de7a4e02bcf62b25c2a638.png) ROC曲线

Ps:为啥每个公式后面会有一个竖线???

参考文献:http://www.cs.utah.edu/~piyush/teaching/ImbalancedLearning.pdf

python sklearn数据预处理:
http://blog.csdn.net/shine19930820/article/details/50915361

这篇关于不平衡学习的方法 Learning from Imbalanced Data的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/456208

相关文章

Python判断for循环最后一次的6种方法

《Python判断for循环最后一次的6种方法》在Python中,通常我们不会直接判断for循环是否正在执行最后一次迭代,因为Python的for循环是基于可迭代对象的,它不知道也不关心迭代的内部状态... 目录1.使用enuhttp://www.chinasem.cnmerate()和len()来判断for

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

四种Flutter子页面向父组件传递数据的方法介绍

《四种Flutter子页面向父组件传递数据的方法介绍》在Flutter中,如果父组件需要调用子组件的方法,可以通过常用的四种方式实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录方法 1:使用 GlobalKey 和 State 调用子组件方法方法 2:通过回调函数(Callb

一文详解Python中数据清洗与处理的常用方法

《一文详解Python中数据清洗与处理的常用方法》在数据处理与分析过程中,缺失值、重复值、异常值等问题是常见的挑战,本文总结了多种数据清洗与处理方法,文中的示例代码简洁易懂,有需要的小伙伴可以参考下... 目录缺失值处理重复值处理异常值处理数据类型转换文本清洗数据分组统计数据分箱数据标准化在数据处理与分析过

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha

golang1.23版本之前 Timer Reset方法无法正确使用

《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避... 目录golang1.23 之前 Reset ​到底有什么问题golang1.23 之前到底应该如何正确的

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Python调用另一个py文件并传递参数常见的方法及其应用场景

《Python调用另一个py文件并传递参数常见的方法及其应用场景》:本文主要介绍在Python中调用另一个py文件并传递参数的几种常见方法,包括使用import语句、exec函数、subproce... 目录前言1. 使用import语句1.1 基本用法1.2 导入特定函数1.3 处理文件路径2. 使用ex

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复