Long-tail distribution problem in image datasets.
在ImageNet、COCO等常用视觉数据集中,由于经过人工预筛选,图像中的不同目标类别的数量是接近的。而在实际的视觉应用中,数据集大多服从长尾分布(long-tail distribution),即少数类别(称为head class)占据绝大多数样本,多数类别(称为tail class)仅有少量样本。一个典型的长尾分布数据集(Open Brands商标数据集)如下图所示。
定义数据集的不平衡率(imbalance ratio)为类别的最大数量和最小数量之比。目前常用的一些长尾分布数据集如下:
- CIFAR100-LT:对CIFAR100的每类训练样本下采样得到的,不平衡率可以取$10,50,100$;测试集保持不变。
- ImageNet-LT:从ImageNet中按照Pareto分布采样得到,包含$1000$类别的$19$k张图像,最多的类别具有$1280$张图像,而最少的仅有$5$张图像,不平衡率为$256$。
- iNaturalist 2018:自然物种分类数据集,包含$8142$类别的$437513$张图像,包含长尾分布和细粒度检测问题,不平衡率为$500$。
- LVIS:大规模实例分割数据集,对超过$1000$类物体进行了约$200$万个高质量的实例分割标注,包含$164$k张图像。
本文介绍一些解决图像数据集中长尾分布问题的方法:
- 重采样 Re-sampling:通过对head class进行欠采样或对tail class进行过采样,人为地构造类别均衡的数据集。包括Random under/over-sampling, Class-balanced sampling, Meta Sampler等。
- 重加权 Re-weighting:在损失函数中对不同类别样本的损失设置不同的权重,通常是对tail class对应的损失设置更大的权重。其中在$\log$运算之外调整损失函数的本质是在调节样本权重或者类别权重(如Inverse Class Frequency Weighting, Cost-Sensitive Cross-Entropy Loss, Focal Loss, Class-Balanced Loss)。在$\log$运算之内调整损失函数的本质是调整logits得分$z$,从而缓解对tail类别的负梯度(如Equalization Loss, Equalization Loss v2, Logit Adjustment Loss, Balanced Softmax Loss, Seesaw Loss)。
- 其他方法:一些方法将长尾分布问题解耦为特征的表示学习和特征的分类。一些方法按照不同类别的样本数量级对类别进行分组(如BAGS)。
1. 重采样 Re-sampling
重采样(re-sampling)的思想是通过对head class进行欠采样或对tail class进行过采样,人为地让模型学习时接触到的训练样本是类别均衡的,从而一定程度上减少对head class的过拟合。不过由于tail class的少量数据往往被反复学习,缺少足够多的样本从而容易过拟合;而head class又往往得不到充分学习。
常用的重采样方法包括:
- Random over-sampling:对tail class进行过采样,这种方法容易过拟合。
- Random under-sampling:对head class进行欠采样,这种方法会降低模型在head class上的性能。
- Class-balanced sampling:控制重采样时每个类别$j$被采样的概率相同:
- Progressively-balanced sampling:训练前期偏向类别不平衡采样,训练后期偏向类别平衡采样;缺点是每轮训练都要重新采样构成数据集:
- PReversed sampling:控制重采样时每个类别$j$被采样的概率与该类别样本数量成反比例:
- Meta Sampler:通过元学习学习不同类别的最佳采样率:
在pytorch中,可以为DataLoader
传入采样器sample
,从而实现不同类别的重采样(本质是调整样本权重)。下面给出一个实现Class-balanced采样的例子:
class_label = dataset.targets
class_count = np.array([len(np.where(class_label==c)[0]) for c in np.unique(class_label)])
weight = 1./class_count
samples_weight = np.array([weight[i] for i in class_label])
samples_weight = torch.from_numpy(samples_weight)
samples_weight = samples_weight.double()
sampler = torch.utils.data.WeightedRandomSampler(weights=samples_weight,
num_samples=len(samples_weight),
replacement=True) # 有放回采样
train_loader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, sampler=sampler)
2. 重加权 Re-weighting
重加权(re-weighting)的思想是在损失函数中对不同类别样本的损失设置不同的权重,通常是对tail class对应的损失设置更大的权重。但是这类方法需要针对不同的数据集和模型等条件设置不同的超参数,泛化性较差。
假设共有$C$个类别,类别$c$共有$n_c$个样本,总样本数为$n$;模型的输出logits(softmax前的输出)为$z=[z_1,z_2,…,z_C]^T$,则属于类别$c$的样本$x$的交叉熵损失函数计算为:
\[\mathcal{L}(x,c) = -\log(\frac{\exp(z_c)}{\sum_{i=1}^{C} \exp(z_i)})\]根据对损失函数进行调整的位置是在$\log$运算之外还是在$\log$运算之内,重加权方法又可以粗略地分为两种情况。
(1) log外调整:class-level re-weighting
在$\log$运算之外调整损失函数的本质是在调节样本权重或者类别权重。
- Inverse Class Frequency Weighting:根据类别出现频率的倒数进行加权:
- Cost-Sensitive Cross-Entropy Loss:根据类别出现(与最少类别的)倍数的倒数进行加权:
- Focal Loss:根据类别预测概率的指数进行加权,为容易预测的类别分配更低的权重:
- Class-Balanced Loss:使用不同类别的有效样本数量$E_{n_c}$进行加权:
(2) log内调整:class-level re-margining
注意到交叉熵损失也可以表示为:
\[-\log(\frac{\exp(z_c)}{\sum_{i=1}^{C} \exp(z_i)}) = -\log(\frac{1}{\sum_{i=1}^{C} \exp(z_i-z_c)}) = \log(\sum_{i=1}^{C} \exp(z_i-z_c))\]注意到logsumexp函数是最大值函数的光滑近似,则交叉熵损失实际上相当于:
\[\mathcal{L}(x,c) = \max(z_1-z_c,z_2-z_c,...,z_c-z_c,...,z_C-z_c)\]最小化上述损失函数,即使得所有非目标类的logits得分$z_{i\ne c}$均小于目标类的logits得分$z_c$。上述优化过程会对所有非目标类产生负样本梯度,抑制这些类别的预测过程,这个现象称为负梯度过抑制(negative gradient over-suppression)。tail类样本作为非目标类样本的频率更高,因此抑制程度更强。
在$\log$运算之内调整损失函数的本质是调整logits得分$z$,从而缓解对tail类别的负梯度。一种可行的方法是为每个类别引入margin $m_c>0$,则logits得分调整为$z_c-m_c$,样本数量越少的类别具有越大的margin。此时损失函数的形式为:
\[-\log(\frac{\exp(z_c-m_c)}{\sum_{i=1}^{C} \exp(z_i-m_i)}) = -\log(\frac{\exp(-m_c)\exp(z_c)}{\sum_{i=1}^{C} \exp(-m_i)\exp(z_i)})\]- Equalization Loss:减轻对其余属于tail类别的梯度抑制:
- Equalization Loss v2:根据梯度引导重加权机制动态调整每轮训练中正梯度和负梯度的权重:
- Logit Adjustment Loss:将类别出现频率$p_c=\frac{n_c}{n}$引入logits:
- Balanced Softmax Loss:消除不平衡训练集与平衡测试集之间的标签分布偏移:
- Seesaw Loss:通过平衡系数\(\mathcal{S}_{ij}\)(由缓解因子\(\mathcal{M}_{ij}\)和补偿因子\(\mathcal{C}_{ij}\)控制)控制施加在其余类别上的负样本梯度:
3. 其他方法 Others
(1) 解耦特征表示与分类
-
Decoupling Representation and Classifier for Long-Tailed Recognition:将长尾分布的图像分类问题解耦为特征的表示学习和特征的分类。采用两阶段的训练方法,首先在原始数据集上进行特征学习,然后在构造的类别平衡数据集上进行微调。
-
BBN: Bilateral-Branch Network with Cumulative Learning for Long-Tailed Visual Recognition:采用双分支的网络结构同时进行特征学习和分类器学习,通过累积学习在训练过程中调整两个分支的权重。
(2) 类别分组分类
- Overcoming Classifier Imbalance for Long-tail Object Detection with Balanced Group Softmax:提出了BAGS方法,即按照不同类别的样本数量级对类别进行分组,每一组额外增加others类别,训练时分组分类训练,测试时分组测试并合并结果。
⚪ 参考文献
- Bag of Tricks for Long-Tailed Visual Recognition with Deep Convolutional Neural Networks:(AAAI2021)一篇长尾分布的综述。
- Deep Long-Tailed Learning: A Survey:(arXiv2110)一篇长尾分布的综述。
- Class-Balanced Loss Based on Effective Number of Samples:(arXiv1901)Class-balanced Loss:基于有效样本数的类别平衡损失。
- Decoupling Representation and Classifier for Long-Tailed Recognition:(arXiv1910)将长尾分布的图像分类问题解耦为表示学习和分类。
- BBN: Bilateral-Branch Network with Cumulative Learning for Long-Tailed Visual Recognition:(arXiv1912)BBN:通过累积学习进行长尾分类的双分支网络。
- Equalization Loss for Long-Tailed Object Recognition:(arXiv2003)Equalization Loss:长尾目标检测中的均衡损失。
- Overcoming Classifier Imbalance for Long-tail Object Detection with Balanced Group Softmax:(arXiv2006)BAGS:按照类别样本的量级对长尾数据集进行分组分类。
- Long-tail learning via logit adjustment:(arXiv2007)Logit Adjustment Loss: 将类别出现频率引入logits。
- Balanced Meta-Softmax for Long-Tailed Visual Recognition:(arXiv2007)BALMS: 长尾图像分类中的平衡元Softmax函数。
- Seesaw Loss for Long-Tailed Instance Segmentation:(arXiv2008)Seesaw Loss:长尾实例分割中的平衡损失。
- Equalization Loss v2: A New Gradient Balance Approach for Long-tailed Object Detection:(arXiv2012)Equalization Loss v2:通过梯度引导重加权机制解决目标检测的正负梯度不平衡问题。