图片分类算法调优技巧

2020-05-15  本文已影响0人  残剑天下论

说到图片分类算法的调优技巧,不得不提亚马逊团队的一篇文章Bag of Tricks for Image Classification with Convolutional Neural Networks

下面的Table1展示了一系列Tricks被用在ResNet50网络做分类任务获得的结果。


可以看到使用本文的技巧,Top1准确率从75.3%提升到了79.29%。所以这一系列技巧还是非常给力的,接下来我们就一起来探索探索。

一、Baseline

既然涉及到调参,那么第一步就得有一个BaseLine的结果作为参考,这一BaseLine并非直接截取之前对应的论文的结果,而是作者基于GluonCV复现的。关于复现的细节作者在论文2.1节中说的很清楚,包括数据预处理的方式和顺序,网络层的初始化方法,迭代次数,学习率变化策略等等。

下面的Table2展示了作者复现的ResNet-50,Inception-V3,MobileNet三个BaseLine。


二、训练调参经验

介绍完BaseLine,接下来就来看看作者的优化方法。论文从加快模型训练,网络结构优化以及训练参数调优三个部分分别介绍如何提升模型的效果。

1、模型训练加速

关于模型训练加速,论文提到了2点,

关于使用更大的Batch Size进行训练加速,作者指出一般只增加Batch Size的话,效果不会太理想,例如FaceBook这篇大名鼎鼎的论文有证明:Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour

然后本文总结了几个重要要的调参方案,如下:

接下来作者提到了使用低精度(16-Bit浮点型)来做训练加速,也即是我们常说的混合精度训练。但不是所有的NVIDIA GPU都支持FP16,我大概只知道V100和2080 Ti是支持混合精度训练的。

作者将上面的Tricks结合在一起进行训练,下面的Table3展示了使用更大的Batch Size和16位浮点型进行训练的结果,可以看到这俩Tricks相比于BaseLine训练速度提升了许多,并且精度也更好了。

而下面的Table4则进一步展示了这些Tricks的消融实验,证明确实是有效的。

2、网络结构调优

这一小节以ResNet-50为例子展开,下面的Figure1表示ResNet网络的原始结构图,简单来说就是一个输入流加4个stage和一个输出流。其中输入流和每个stage的详细结构在Figure1中间那一列显示,而残差结构则在Figure1中最右边进行显示。

论文在网络结构部分进行改进获得的3种结构如Figure2(a),(b),(c)所示:


最终关于这些改进的网络结构的效果如Table5所示,可以看到效果提升还是有的。


3、模型训练调优

代码实现可以简单表示为:

new_labels = (1.0 - label_smoothing) * one_hot_labels + label_smoothing / num_classes

完整的Pytorch代码如下:

import torch
import torch.nn as nn

class LabelSmoothing(nn.Module):
    """
    NLL loss with label smoothing.
    """
    def __init__(self, smoothing=0.0):
        """
        Constructor for the LabelSmoothing module.
        :param smoothing: label smoothing factor
        """
        super(LabelSmoothing, self).__init__()
        self.confidence = 1.0 - smoothing
        self.smoothing = smoothing

    def forward(self, x, target):
        logprobs = torch.nn.functional.log_softmax(x, dim=-1)

        nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
        nll_loss = nll_loss.squeeze(1)
        smooth_loss = -logprobs.mean(dim=-1)
        loss = self.confidence * nll_loss + self.smoothing * smooth_loss
        return loss.mean()

具体细节和公式可以再阅读原文,这里展示一下Lable Smooth的效果,下图展示了真实类别概率和其他类别的概率均值之间的gap的理想情况以及使用了Label Smooth后的情况。

总结就一句话,one-hot编码会自驱的向正类和负类的差值扩大的方向学习(过度的信任标签为1的为正类),在训练数据不足的情况容易过拟合,所以使用Label Smooth来软化一下,使得没那么容易过拟合。

其中p表示真实标签,z表示student model的全连接层输出,r表示teacher model的全连接层输出,T是超参数,用来平滑softmax函数的输出。

最终,在使用了这4个Tricks后的消融实验结果如Table6所示。

三、检测、分割任务上的作用

当把上面的Tricks迁移到目标检测和语义分割任务同样是有效的,实验结果如Table8和Table9所示。


上一篇 下一篇

猜你喜欢

热点阅读