解决不均匀样本下的分类

AuthorTime
Wu_b2019.6.29

在不均匀样本下训练分类器,容易造成分类器将样本直接判别为大样本,从而降低损失,没有动力继续优化参数。针对这个问题,可以由以下几个方法进行优化:

  • 随机采样+集成学习相结合
  • 修改大小样本在计算loss时的权重
  • 欠采样
  • 过采样
  • 综合采样

1 随机采样+集成学习

这个是在面试过程中想到的,不过考虑到其不稳定性就没说出来了。

1.1 算法

这里主要是参考了随机森林的基本思想,基本步骤如下:

  • 首先针对大样本,进行部分数据的放回随机采样,形成多个与小样本数量相同的子样本(按照题目是500个)。
  • 将这多个子样本与小样本进行组合,并作为分类器的不同训练集,形成多个子分类器
  • 利用集成学习的方法,通过投票法对多个子分类器的输出进行整合,最后将票数最高的结果作为分类器的最终输出
1.2 存在问题
  • 尽管该方法是最简单的,但是由于对大样本进行随机抽样,容易丢失部分原来大样本的数据信息
  • 如果采用的是对于小样本进行随机抽样,那么由于重复的样本数过多容易造成过拟合
1.3 改进方法

采用BalanceCascade,即在上述放回随机采样的基础上进行修改

  • 同样通过放回随机采样得到一个子样本,并通过该子样本训练第一个子分类器
  • 将第一个子分类器分类错误的样本放回
  • 重复以上两个步骤,直到达到一定的分类器数量或其他的停止条件

2 修改大小样本在计算loss时的权重

不过这种方法主要是对于算法的内容进行了修改,而不是题目中数据预处理

2.1 算法

这里主要是对于训练中loss的计算公式进行了更改,增大小样本计算loss的权重,减小大样本计算loss的权重,最直接的方法就是直接将权重值设为所对应样本数量的倒数。

像常见计算loss的方法,如交叉熵,可以直接加上样本数量的倒数作为权重

2.2 存在问题
  • 这里其实不是对于样本数据进行预处理,而是对于算法的loss进行加权计算
  • 对于权重的设置问题,样本数量的倒数是比较简单的操作,但是合理性仍需要进一步的验证。因此寻找一个合理的权重是一个大问题。
2.3 类似方法

同样也是非数据预处理的做法,通过修改分类判别的阈值来实现,如小样本的概率阈值可根据样本的占比相应下调,而不是原有的0.5:0.5

3 欠采样

3.1 Near-miss算法

这里欠采样主要有以下四种方法:

  • Near-miss-1:选择到最近的三个样本平均距离最小的多数类样本(500个)
  • Near-miss-2:选择到最远的三个样本平均距离最小的多数类样本(500个)
  • Near-miss-3:为每个少数类样本选择给定数目的最近多数类样本(500个)
  • 最远距离:选择到最近的三个样本平均距离最大的多样类样本(500个)
3.1.1 存在的问题
  • 总体而言,以上四种方法的计算量偏大
  • Near-miss-1由于是参考的是最近的三个样本的距离,是局部的,容易收到离群点的影响
3.1.2 评估
  • 总体而言,Near-miss-2的效果是最好的,这一点在下述文章中有提到

    Haibo He, Member, IEEE, and Edwardo A. Garcia. Learning from Imbalanced Data

3.2 Tomek links方法
3.2.1 算法

对于属于不同样本的两个点x,y,我们找不到第三个点z,使得z到x的距离或者到y的距离,小于x和y之间的距离。这样的xy就形成了一个Tomek link,欠采样即将每一个Tomek link中属于多样类的样本抛弃。

3.2.2 评估
  • 首先,计算量还是比较大
  • 其次,清除的数据数量有限。按照目前9000,500,500的数据量,最多只能清除1000个多样类的样本。
3.3 ENN算法
3.3.1 算法

基于knn算法,对于多样类样本中的每个点,如果k个最近邻的点一半都是另外的类,则将该数据抛弃(或者k个最近邻的点全部都是另外的类)

3.3.2评估
  • 首先还是计算量偏大,需要遍历多样类样本中的每一个点
  • 其次是清除的数据量有限,针对本次题目中18:1:1的数据比例,很难将大样本的数据所占比例下降到合适的范围

4 过采样

这里我们针对于两个只有500数据量的小样本类进行数据的人工合成

4.1 SMOTE算法
4.1.1算法
  • 首先针对两个小样本类中的每一个样本x寻找k个最近邻
  • 根据样本分布的比例,从k个最近邻中随机选择n个样本y(这里n根据题目,选择9000/500=18)
  • 新样本z = x + a*(y-x),这里a从0-1的均匀分布中随机取值
4.1.2 评估
  • 计算量比较大
  • 增强了小样类样本在整体样本中的占比
  • 容易增加类之间的重叠性,模糊了正负类边界(尤其是处于多样类样本中的少样类)
  • 产生的新样本很可能是一些没有提供信息的样本
4.2 Border-line SMOTE算法
4.2.1算法

针对SMOTE算法的不足而进行完善的一种新算法。

  • 首先将少样类样本进行分类
    • k近邻都是多样类,则为噪声,不用于生成样本
    • k近邻一半以上是少样类,安全点,不用于生成样本
    • k近邻一半以上是多样类,危险点,用于生成样本
  • 将上述的安全点利用上述SMOTE算法一样生成新样本
4.2.2 评估
  • 计算量比较大
  • 可以加强处模糊样本的存在感
4.3 ADASYN算法
4.3.1算法

ADASYN是一种自适应综合采样的方法:

  • 根据最后样本平衡度需求,计算需要的样本数G
  • 计算每个小样类样本K近邻中大样本的比例r
  • 计算每个小样本的r在所有小样本类r和的比例:R = r/sum®
  • 得到每个小样类样本需要得到G*R个样本
  • 在每个小样类样本x周围k个邻居选择一个小众样本y,利用线性插值法x_new = x+a*(y-x),a为0-1均匀分布随机采样得到
4.3.2 评估
  • 计算量大
  • 不能抵抗噪声的干扰
4.4 KM-SMOTE算法
4.4.1算法

将K-means聚类和SMOTE相结合:

  • 选择小样本类进行K-means聚类,聚成K类,并记录每一类的簇心c
  • 对于每一类中,利用簇心和每一个原始数据x进行插值:x_new = c + (c-x)*rand(0,1)
4.4.2 评估
  • 不会出现泛边界的数据

5 综合采样

综合采样主要是将对于小样本类的过采样和对于多样本类的欠采样结合起来,主要有:

  • SMOTE+Tomek links
  • SMOTE+ENN

这样既增加了小众样本的数量,且减少了不同类别之间的样本重叠

6 总结

上述方法主要是分成五大块,分别是随机抽样+集成学习、loss惩罚函数的权重调动、欠采样、过采样、综合采样五种。分别对应从简单到复杂,其性能也随着计算量的增大而增大。

根据本次的需求看来,可能选择针对于少样类的欠采样,或使用综合采样比较好。

7 参考

imbalanced-learn库

### 解决 Adam 优化器样本均衡问题的方法 #### 使用重采样技术 针对样本均衡的情况,可以应用重采样的方法来调整同类别的样本数量。具体来说,可以通过欠采样多数类或过采样少数类的方式使各类别之间的比例更加平衡。这种方法有助于防止模型偏向于占主导地位的类别,从而改善整体性能[^1]。 #### 应用代价敏感学习 另一种有效的策略是引入代价敏感机制,在损失函数中赋予同误分类成本给各个类别。当使用 Adam 进行参数更新时,这种做法能促使网络更多关注那些原本被忽视的小概率事件,进而缓解因数据分布倾斜带来的负面影响[^2]。 #### 动态加权方案 为了进一步增强对平衡数据集下训练效果的影响,还可以考虑实施基于实例难度或者类别频率计算得出的动态权重分配方式。这仅可以在一定程度上抑制常见模式过度拟合的现象发生,而且有利于挖掘稀有特征并促进其表达,最终达到更好的收敛状态。 #### 自适应学习率调节 考虑到 Adam 已经具备了自适应特性,即根据同参数维度的历史梯度信息自动调整各自的学习速率;因此在此基础上继续探索更为灵活高效的学习率调控手段也是可行之策之一。比如结合 OneCycleLR 或者 CosineAnnealingWarmRestarts 等周期性变化规律来进行全局范围内的微调操作,以此确保在整个迭代过程中始终维持适宜的速度前进而至于陷入局部极小值陷阱之中[^3]。 ```python import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data.sampler import WeightedRandomSampler # 定义转换规则 transform = transforms.Compose([transforms.ToTensor(),]) # 加载 MNIST 数据集作为示例 dataset_train = datasets.MNIST(root='./data', train=True, download=True, transform=transform) # 计算每个类别的样本数 class_sample_count = [0] * len(dataset_train.classes) for _, target in dataset_train: class_sample_count[target] += 1 # 设置权重向量 weights = 1 / torch.tensor(class_sample_count, dtype=torch.float) # 创建 sampler 对象 sampler = WeightedRandomSampler(weights=weights, num_samples=len(dataset_train), replacement=True) # 构建 DataLoader 并指定 sampler 参数 train_loader = torch.utils.data.DataLoader( dataset_train, batch_size=64, shuffle=False, sampler=sampler ) # 初始化模型与优化器 model = ... # 用户定义的具体架构 optimizer = optim.Adam(model.parameters()) # 开始训练循环... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值