不平衡数据

前言

在机器学习的经典假设中往往假设训练样本各类别数目是均衡的,但在实际场景中,训练样本数据往往都是不均衡(不平衡)的。比如在图像二分类问题中,一个极端的例子是,训练集中有 95 个正样本,但是负样本只有 5 个。这种类别数据不均衡的情况下,如果不做不平衡样本的处理,会导致模型在数目较少的类别上出现欠学习现象,即可能在测试集上完全丧失对负样本的预测能力。

除了常见的分类、回归任务,类似图像语义分割、深度估计等像素级别任务中也是存在不平衡样本问题的。

解决不平衡样本问题的处理方法一般有两种:

  1. 从“数据层面”入手:分为数据采样法和类别平衡采样法。
  2. 从“算法层面”入手:代价敏感方法。

注意本文只介绍不平衡样本的处理思想和策略,不涉及具体代码,在实际项目中,需要针对具体任务,结合不平衡样本的处理策略来设计具体的数据集处理或损失函数代码,从而解决对应问题。

一,数据层面处理方法

数据层面的处理方法总的来说分为数据扩充和采样法,数据扩充会直接改变数据样本的数量和丰富度,采样法的本质是使得输入到模型的训练集样本趋向于平衡,即各类样本的数目趋向于一致。

数据层面的采样处理方法主要有两种策略:

  1. 数据重采样方法,发生在数据预处理阶段,会改变整体训练集的数目和分布。
  2. 类别平衡采样方法,发生在数据加载阶段(这里的加载是指加载到模型中,不是指从硬盘中读取文件),通过设置采样策略来使得不同类别样本送入模型训练总的次数是近似的。

1.1,数据扩充

所谓数据不平衡,其实就是某些类别的数据量太少,那就直接增加一些呗,简单直接。如果有的选,那肯定是优先选择重新采取数据的办法了,当然大部分时候我们都没得选,这个时候最有效的办法自然是通过数据增强来扩充数据了。

数据增强的手段有多种,常见的如下:

  • 水平 / 竖直翻转
  • 90°,180°,270° 旋转
  • 翻转 + 旋转(旋转和翻转其实是保证了数据特征的旋转不变性能被模型学习到,卷积层面的方法可以参考论文 ACNet)
  • 亮度,饱和度,对比度的随机变化
  • 随机裁剪(Random Crop)
  • 随机缩放(Random Resize)
  • 加模糊(Blurring)
  • 加高斯噪声(Gaussian Noise)

值得注意的是数据增强手段的使用必须结合具体任务而来,除了前三种以外,其他的要慎重考虑。因为不同的任务场景下数据特征依赖不同,比如高斯噪声,在天池铝材缺陷检测竞赛中,如果高斯噪声增加不当,有些图片原本在采集的时候相机就对焦不准,导致工件难以看清,倘若再增加高斯模糊属性,部分图片样本基本就废了。

参考文章  如何针对数据不平衡做处理

虽然目前深度学习框架中都自带了一些数据增强函数,但更多更强的数据增强手段可以使用一些图像增强库,比如 imgaug 这个 python 库。

模型训练过程中,pytorch 框架如何在数据构建 pipeline 阶段使用 imgaug 库可以参考文章  数据增强-imgaug
另一篇文章的意思:

深度学习训练数据不平衡问题,怎么解决? - 知乎

保存 R、G、B 通道、滤波、锐化以后的图片副本

1.2,数据(重)采样

简单的数据重采样方法分为数据上采样over-samplingup-sampling,也叫数据过采样) 或 也叫数据欠采样数据下采样(under-sampling 、down-sampling )。

1,对于样本数目较少的类别,可用数据过采样方法over-sampling),即通过复制方法使得该类图像数目增至与样本最多类的样本数一致。

对于不平衡的类别,我们使用拷贝现有样本的方法随机增加观测数量。理想情况下这种方法给了我们足够的样本数,但过采样可能导致过拟合训练数据。

2,而对于样本数较多的类别,可使用数据欠采样Under-sampling,也叫数据欠采样)方法。对于深度学习和计算机视觉领域的任务来说,下采样并不是直接随机丢弃一部分图像,正确的下采样策略是: 在批处理训练时(数据加载阶段 dataloader),对于样本较多的类别,严格控制每批(batch)随机抽取的图像数目,使得每批读取的数据中正负样本是均衡的(类别均衡)。以二分类任务为例,假设原始数据分布情况下每批处理训练正负样本平均数量比例为 9:1,如仅使用下采样策略,则可在每批随机挑选训练样本时每 9 个正样本只取 1 个作为该批训练集的正样本,负样本选择策略不变,这样可使得每批读取的训练数据中正负样本时平衡的。

随机删除观测数量足够多的类,使得两个类别间的相对比例是显著的。虽然这种方法使用起来非常简单,但很有可能被我们删除了的数据包含着预测类的重要信息。

数据过采样和欠采样示意图如下所示。

数据采样方法总结

数据过采样和欠采样本质的简单理解就是“增加图片”和“删图片”: - 过采样:重复正比例数据,实际上没有为模型引入更多形式数据,过分强调正比例数据,会放大正比例噪音对模型的影响。 - 欠采样:丢弃大类别的部分数据,和过采样一样会存在过拟合的问题。

同时两种数据重采样方法都是会改变数据原始分布的,比如数据过采样增加较小类别的样本数,数据欠采样减少较大类别的样本数,有可能产生模型过拟合等问题

这里的较小类别的意思是样本数目较少的类别,较大类别即样本数目较多的类别。

以上内容都是对解决类别不平衡问题中数据采样方法的策略描述,但想要在实际任务中解决问题,还要求我们加深对任务(task)的分析、对数据的理解分析,以及要求我们有更多的数据处理、数据采样的代码经验,即良好的策略 + 熟练的工具。

需要注意的是,因为仅仅使用数据上采样策略有可能会引起模型过拟合问题,所以在实际任务中, 更为保险的数据采样策略往往是将上采样和下采样结合起来使用
其他帖子介绍

深度学习中,针对不平衡数据集(各类别严重失衡),所采取的重采样技术的具体手段有哪些? - 知乎

给类别少的多分配一点采样权重,给类别多得多分点采样权重。 

1.3,类别平衡采样

前面的数据重采样策略是着重于类别样本数量,而另一类采样策略则是直接着重于类别本身,不改变数据总体样本数,即类别平衡采样方法。其简单策略是把样本按类别分组,每个类别生成一个样本列表,训练过程中随机选择 1 个或几个类别,然后从每个类别所对应的样本列表中随机选择样本,这样可保证每个类别参与训练的机会比较均衡。

上述类别平衡方法过于简单,实际应用中有很多限制,比如在类别数很多的多分类任务中(如 ImageNet 数据集)。由此,在类别平衡采样的基础上,国内海康威视研究院提出了一种“类别重组采样”的平衡方法

类别重组法是在《解析卷积神经网络》这本书中看到的,可惜没在网上找到原论文和代码,但这个方法感觉还是很有用的,且也比较好复现。

如下图所示,类别重组方法步骤如下:

类别重组法步骤示意图 

  1. 对原始样本的每个类别的样本分别排序好,计算每个类别的样本数目,并记录样本数最多的那个类别的样本数量 max_num
  2. 基于最大样本数 max_num 产生一个随机数列表,然后用此列表中的随机数对各自类别的样本数求余,得到对应索引值列表 index_listrandom.shuffle(list(range(max_num)))
  3. 根据该索引值列表 index_list,从该类的图像数据中提取图像,生成该类的图像随机列表。
  4. 最后吧所有类别的随机列表连接在一起后一起随机打乱次序,即可得到最终的图像列表,可以发现最终的这个图像随机列表中每个类别的样本数目是一致的(样本数较少的类别,图像会存在多次采样)。然后每轮(epoch)都对此列表进行遍历数据用于模型训练,如此重复。

以上方法整体还是比较复现的,结合具体任务来设计代码就行,这里给出一个简单的生成一段范围为 [1, 10] 的随机整数列示例代码。

import random
# 生成一段范围为[0, 9]的随机整数列表
# sample(L, n) 函数: 从序列L中随机抽取n个元素,并将n个元素以list形式返回。
# 也可用 random.shuffle(L) 函数原地打乱列表
random_list = random.sample(range(0, 10), 10)
print(random_list)

类别重组法对有点很明显,在设计好重组代码函数后,只需要原始图像列表即可,所有操作都在内存中在线完成,易于实现且更通用。其实仔细深究可以发现,海康提出的这个类别重组法和前面的数据采样方法是很类似的,其本质都是通过采样(sampler)策略让类别不均衡的各类数据在每轮训练中出现的次数是一致的。 

二,算法(损失函数)层面处理方法

类别不平衡问题的本质是导致样本数目较少的类别出现“欠学习”这一机器学习现象,直观表现是较小样本的损失函数权重占比也较少。一个很自然的解决办法是增加小样本错分的惩罚代价,并将此代价直接体现在目标函数(损失函数)里,这就是“代价敏感”的方法。“代价敏感”方法的本质可以理解为调整模型在小类别上的注意力。

知友- TY Sun 的补充,Focal Loss 和修改损失函数权重在工业界并不是那么有效,因为工业界 task 的数据集标准往往都不如学术界  imagenet 等数据集那么准确。 

2.1,Focal Loss

Focal Loss 是在二分类问题的交叉熵(CE)损失函数的基础上引入的,主要是为了解决 one-stage 目标检测中正负样本比例严重失衡的问题,该损失函数降低了大量简单负样本在训练中所占的权重,也可理解为一种困难样本挖掘,经实践证明 Focal Loss 在 one-stage 目标检测中还是很有效的,但是在多分类中不一定有效。

1. 正难3. 正易,$\gamma$ 衰减
2. 负难,$\alpha$ 衰减4. 负易,$\alpha、\gamma$衰减

 更多理解参考 focal loss 论文

2.2,损失函数加权

除了 Focal Loss 这种高明的损失函数策略外,针对图像分类问题,还有一种简单直接的损失函数加权方法,即在计算损失函数过程中,对每个类别的损失做加权处理,具体的 PyTorch 实现方式如下:

weights = torch.FloatTensor([1, 1, 8, 8, 4]) # 类别权重分别是 1:1:8:8:4
# pos_weight_weight(tensor): 1-D tensor,n 个元素,分别代表 n 类的权重,
# 为每个批次元素的损失指定的手动重新缩放权重,
# 如果你的训练样本很不均衡的话,是非常有用的。默认值为 None。
criterion = nn.BCEWithLogitsLoss(pos_weight=weights).cuda()

采样通常是在数据加载过程中进行的

在深度学习中,采样通常是在数据加载过程中进行的,特别是在使用 DataLoader 这类工具时。DataLoader 是 PyTorch 中一个非常重要的组件,用于高效加载数据。它可以与 Sampler 对象配合使用,来定义数据的抽取方式,确保每个训练周期中数据的呈现顺序和分组方式符合特定的需求。

采样的几种情形:

  1. 批处理采样(Batch Sampling):

    • 随机采样(Random Sampling):数据集中的样本被随机抽取,不按照固定顺序。这有助于模型训练时的泛化能力,避免因数据顺序引入的偏差。
    • 顺序采样(Sequential Sampling):按照数据集中的原始顺序加载数据。这在某些场景下有用,如时间序列数据的处理。
  2. 不均衡数据集采样:

    • 为了处理类别不平衡的数据集,采样策略可能会调整,以便从较少的类别中更频繁地抽取样本。这可以是通过过采样少数类或欠采样多数类来实现。
  3. 分布式训练采样:

    • 在使用多个进程或者多个设备进行训练时,采样器能确保每个训练节点或设备获得不重叠的数据子集。

DataLoader 中使用采样器:

在 PyTorch 中,DataLoader 接受一个 Sampler 对象作为参数,这个对象定义了从数据集中抽取样本的策略。例如,使用 SubsetRandomSampler 来从数据集中随机抽取一部分数据作为训练集或测试集。

from torch.utils.data import DataLoader, SubsetRandomSampler 
# 假设 dataset 是你的数据集对象 
sampler = SubsetRandomSampler(indices) # indices 是你选择的样本索引列表
dataloader = DataLoader(dataset, batch_size=4, sampler=sampler)

总结来说,采样是数据加载过程中非常关键的一个环节,特别是当你需要特定的数据加载策略来优化训练过程或处理特定类型的数据集(如不平衡数据)时。DataLoader 通过提供灵活的采样器接口,使得这一过程更加简便和高效。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Keel是一个用于分类、聚类和预处理不平衡数据的软件工具包。在数据挖掘和机器学习中,不平衡数据问题是普遍存在的,也是一个具有挑战性的问题。不平衡数据指的是分类问题中不同类别的样本数目差别很大,例如,在一个二分类问题中,正例数据只占整个数据集的一小部分。 不平衡数据可能导致分类器的性能下降,因为分类器可能会偏向于预测样本更多的类别。Keel提供了一些解决不平衡数据的方法,例如基于数据重采样的方法、基于阈值的方法、基于成本敏感的方法等。这些方法可以使分类器更加公平地对待不同类别的样本,提高分类器的性能。 Keel也提供了一些评估不平衡数据分类器性能的指标,例如混淆矩阵、ROC曲线、AUC值等。这些指标可以帮助研究人员更好地评估他们的分类器,并作出改进。Keel还提供了一个用户友好的图形界面,使得使用者可以方便地处理和分析不平衡数据问题。 总之,Keel是一个非常有用的工具,可以帮助研究人员和从事数据挖掘和机器学习的工程师更好地处理不平衡数据问题。它提供了一系列的解决方案和评估指标,使得使用者可以更加有效地处理和分析自己的数据,并得到更好的结果。 ### 回答2: Keel是一种用于进行机器学习数据挖掘实验的软件平台。在Keel中,经常会出现不平衡数据的情况。不平衡数据指的是在数据集中,某些类别的样本数量远远少于其他类别的样本数量。例如,在一个二元分类问题中,其中正例样本有100个,负例样本有1000个,这就是一个典型的不平衡数据集。 不平衡数据对于机器学习算法的性能有很大的影响。在不平衡数据中,常见的做法是使用采样方法来平衡数据。常见的采样方法有欠采样和过采样。欠采样指的是从多数类中随机选择一些样本加入到少数类中,来平衡数据。过采样则是通过随机生成少数类的一些样本来增加样本数量。此外,还可以通过改变代价矩阵来解决不平衡数据的问题,使得算法更加注重少数类的分类,并减少误分率。 在Keel中,处理不平衡数据的常见方法是使用“imbalanced data”模块,其中包括了各种采样方法和代价矩阵的操作。同时Keel也提供了数据可视化工具,可以清晰地展示数据的分布情况,帮助用户选择合适的方法解决不平衡数据的问题。需要注意的是,不同的采样方法和代价矩阵会对算法的分类性能造成不同的影响,需要用户在实际应用中进行不断的尝试和优化。 ### 回答3: Keel是一个专门用于数据挖掘和机器学习的软件,它提供了丰富的算法和工具来辅助用户进行数据分析。在实际的数据处理过程中,会存在不平衡数据的情况,即正负样本比例不一致,这样会导致模型的预测效果不佳。Keel针对不平衡数据问题提供了以下几种解决方案: 1. 合成正样本:通过一些数据生成的算法,生成一些与原始正样本类似但又有所差别的合成正样本,增加正样本数量,从而提高模型预测准确率。 2. 对负样本进行欠采样:对许多重复的或相似的负样本进行随机采样,减少负样本数量,使得正负样本比例更加平衡,提高模型的预测品质。 3. 对正样本进行过采样:通过复制或变换原始正样本,增加正样本数量,从而使正负样本比例更加平衡,提高模型预测能力。 4. 调整分类阈值:通过修改分类模型中的阈值(即决策边界),使得模型对样本的分类更准确,提高模型的预测效果。 总之,Keel针对不平衡数据问题提供了多种解决方案,可根据具体情况选择最有效的方法,提高数据分析的准确度和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值