@创建于:2022.03.30 @修改于:2022.03.30
1、样本不均衡解决办法
样本(类别)样本不平衡(class-imbalance)指的是分类任务中不同类别的训练样例数目差别很大的情况,一般地,样本类别比例(Imbalance Ratio)(多数类vs少数类)明显大于1:1(如4:1)就可以归为样本不均衡的问题。现实中,样本不平衡是一种常见的现象,如:金融欺诈交易检测,欺诈交易的订单样本通常是占总交易数量的极少部分,而且对于有些任务而言少数样本更为重要。
不均衡解决方法可以归结为:通过某种方法使得不同类别的样本对于模型学习中的Loss(或梯度)贡献是比较均衡的。
1.1 数据样本
1.1.1 欠采样、过采样
最直接的处理方式就是样本数量的调整了,常用的可以:
- 欠采样:减少多数类的数量(如随机欠采样、NearMiss、ENN)。- 过采样:尽量多地增加少数类的的样本数量(如随机过采样、以及2.1.2数据增强方法),以达到类别间数目均衡。
1.1.2 数据增强
-
单样本增强(主要用于图像) 主要有几何操作、颜色变换、随机擦除、添加噪声等方法产生新的样本,可参见imgaug开源库。 -
多样本增强 是通过组合及转换多个样本,主要有Smote类(可见imbalanced-learn.org/stable/references/over_sampling.html)、SamplePairing、Mixup等方法在特征空间内构造已知样本的邻域值样本。 -
基于深度学习的数据增强 生成模型如变分自编码网络(Variational Auto-Encoding network, VAE)和生成对抗网络(Generative Adversarial Network, GAN),其生成样本的方法也可以用于数据增强。这种基于网络合成的方法相比于传统的数据增强技术虽然过程更加复杂, 但是生成的样本更加多样。
1.2 目标(损失)函数
损失函数层面主流的方法也就是常用的代价敏感学习(cost-sensitive),为不同的分类错误给予不同惩罚力度(权重),在调节类别平衡的同时,也不会增加计算复杂度。
1.2.1 class weight
scikit模型的’class weight‘方法
clf2 = LogisticRegression(class_weight={0:1,1:10})
1.2.2 OHEM
OHEM(Online Hard Example Mining)算法的核心是选择一些hard examples(多样性和高损失的样本)作为训练的样本,针对性地改善模型学习效果。对于数据的类别不平衡问题,OHEM的针对性更强。
1.2.3 Focal loss
Focal loss的核心思想是在交叉熵损失函数(CE)的基础上增加了类别的不同权重以及困难(高损失)样本的权重(如下公式),以改善模型学习效果。
focal loss的两个重要性质: 1、当一个样本被分错的时候,pt是很小的,因此调制系数就趋于1,也就是说相比原来的loss是没有什么大的改变的。当pt趋于1的时候(此时分类正确而且是易分类样本),调制系数趋于0,也就是对于总的loss的贡献很小。 2、当γ=0的时候,focal loss就是传统的交叉熵损失,当γ增加的时候,调制系数也会增加。
focal loss的两个性质算是核心,其实就是用一个合适的函数去度量难分类和易分类样本对总的损失的贡献。
1.3 模型算法
1.3.1 采样+集成学习
通过重复组合少数类样本与抽样的同样数量的多数类样本,训练若干的分类器进行集成学习。
1.3.2 异常检测
类别不平衡很极端的情况下(比如少数类只有几十个样本),将分类问题考虑成异常检测(anomaly detection)问题可能会更好。
1.4 决策及评估指标
对于类别不均衡下的模型评估,可以采用AUC、AUPRC(更优)评估模型表现。AUC的含义是ROC曲线的面积,其数值的物理意义是:随机给定一正一负两个样本,将正样本预测分值大于负样本的概率大小。AUC对样本的正负样本比例情况是不敏感,即使正例与负例的比例发生了很大变化,ROC曲线面积也不会产生大的变化。
2、Weighted cross entropy and Focal loss
import numpy as np
def Wce(logits,label,weight):
'''
:param logits: net's output, which has reshaped [batch size,num_class]
:param label: Ground Truth which is ont hot encoing and has typr format of [batch size, num_class]
:param weight: a vector that describes every catagory's coefficent whose shape is (num_class,)
:return: a scalar
'''
loss = np.dot(np.log2(logits)*label,np.expand_dims(weight,axis=1)) + \
np.log2(logits) * (1-label)
return loss.sum()
import numpy as np
def focal_loss(logits, label, a, r):
'''
:param logits: [batch size,num_classes] score value
:param label: [batch size,num_classes] gt value
:param a: generally be 0.5
:param r: generally be 0.9
:return: scalar loss value of a batch
'''
p_1 = - a*np.power(1-logits,r)*np.log2(logits)*label
p_0 = - (1-a)*np.power(logits,r)*np.log2(1-logits)*(1-label)
return (p_1 + p_0).sum()
Focal Loss Weighted cross entropy and Focal loss
|