0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

图像分类任务的各种tricks

新机器视觉 来源:新机器视觉 作者:新机器视觉 2022-09-14 16:42 次阅读

导读

计算机视觉主要问题有图像分类、目标检测和图像分割等。针对图像分类任务,提升准确率的方法路线有两条,一个是模型的修改,另一个是各种数据处理和训练的tricks。图像分类中的各种技巧对于目标检测、图像分割等任务也有很好的作用。本文在精读论文的基础上,总结了图像分类任务的各种tricks。

目录:

Warmup

Linear scaling learning rate

Label-smoothing

Random image cropping and patching

Knowledge Distillation

Cutout

Random erasing

Cosine learning rate decay

Mixup training

AdaBoud

AutoAugment

其他经典的tricks

Warmup

学习率是神经网络训练中最重要的超参数之一,针对学习率的技巧有很多。Warm up是在ResNet论文[1]中提到的一种学习率预热的方法。由于刚开始训练时模型的权重(weights)是随机初始化的(全部置为0是一个坑,原因见[2]),此时选择一个较大的学习率,可能会带来模型的不稳定。学习率预热就是在刚开始训练的时候先使用一个较小的学习率,训练一些epoches或iterations,等模型稳定时再修改为预先设置的学习率进行训练。论文[1]中使用一个110层的ResNet在cifar10上训练时,先用0.01的学习率训练直到训练误差低于80%(大概训练了400个iterations),然后使用0.1的学习率进行训练。

上述的方法是constant warmup,18年Facebook又针对上面的warmup进行了改进[3],因为从一个很小的学习率一下变为比较大的学习率可能会导致训练误差突然增大。论文[3]提出了gradual warmup来解决这个问题,即从最开始的小学习率开始,每个iteration增大一点,直到最初设置的比较大的学习率。

Gradual warmup代码如下:

fromtorch.optim.lr_schedulerimport_LRScheduler

classGradualWarmupScheduler(_LRScheduler):
"""
Args:
optimizer(Optimizer):Wrappedoptimizer.
multiplier:targetlearningrate=baselr*multiplier
total_epoch:targetlearningrateisreachedattotal_epoch,gradually
after_scheduler:aftertarget_epoch,usethisscheduler(eg.ReduceLROnPlateau)
"""

def__init__(self,optimizer,multiplier,total_epoch,after_scheduler=None):
self.multiplier=multiplier
ifself.multiplier<=  1.:
             raise  ValueError('multiplier should be greater than 1.')
         self.total_epoch = total_epoch
         self.after_scheduler = after_scheduler
         self.finished =  False
         super().__init__(optimizer)

    def get_lr(self):
        if self.last_epoch >self.total_epoch:
ifself.after_scheduler:
ifnotself.finished:
self.after_scheduler.base_lrs=[base_lr*self.multiplierforbase_lrinself.base_lrs]
self.finished=True
returnself.after_scheduler.get_lr()
return[base_lr*self.multiplierforbase_lrinself.base_lrs]

return[base_lr*((self.multiplier-1.)*self.last_epoch/self.total_epoch+1.)forbase_lrinself.base_lrs]

defstep(self,epoch=None):
ifself.finishedandself.after_scheduler:
returnself.after_scheduler.step(epoch)
else:
returnsuper(GradualWarmupScheduler,self).step(epoch)

Linear scaling learning rate

Linear scaling learning rate是在论文[3]中针对比较大的batch size而提出的一种方法。

在凸优化问题中,随着批量的增加,收敛速度会降低,神经网络也有类似的实证结果。随着batch size的增大,处理相同数据量的速度会越来越快,但是达到相同精度所需要的epoch数量越来越多。也就是说,使用相同的epoch时,大batch size训练的模型与小batch size训练的模型相比,验证准确率会减小。

上面提到的gradual warmup是解决此问题的方法之一。另外,linear scaling learning rate也是一种有效的方法。在mini-batch SGD训练时,梯度下降的值是随机的,因为每一个batch的数据是随机选择的。增大batch size不会改变梯度的期望,但是会降低它的方差。也就是说,大batch size会降低梯度中的噪声,所以我们可以增大学习率来加快收敛。

具体做法很简单,比如ResNet原论文[1]中,batch size为256时选择的学习率是0.1,当我们把batch size变为一个较大的数b时,学习率应该变为 0.1 × b/256。

Label-smoothing

在分类问题中,我们的最后一层一般是全连接层,然后对应标签的one-hot编码,即把对应类别的值编码为1,其他为0。这种编码方式和通过降低交叉熵损失来调整参数的方式结合起来,会有一些问题。这种方式会鼓励模型对不同类别的输出分数差异非常大,或者说,模型过分相信它的判断。但是,对于一个由多人标注的数据集,不同人标注的准则可能不同,每个人的标注也可能会有一些错误。模型对标签的过分相信会导致过拟合。

标签平滑(Label-smoothing regularization,LSR)是应对该问题的有效方法之一,它的具体思想是降低我们对于标签的信任,例如我们可以将损失的目标值从1稍微降到0.9,或者将从0稍微升到0.1。标签平滑最早在inception-v2[4]中被提出,它将真实的概率改造为:

886b7422-33e4-11ed-ba43-dac502259ad0.jpg

其中,ε是一个小的常数,K是类别的数目,y是图片的真正的标签,i代表第i个类别,是图片为第i类的概率。

总的来说,LSR是一种通过在标签y中加入噪声,实现对模型约束,降低模型过拟合程度的一种正则化方法。LSR代码如下:

importtorch
importtorch.nnasnn

classLSR(nn.Module):

def__init__(self,e=0.1,reduction='mean'):
super().__init__()

self.log_softmax=nn.LogSoftmax(dim=1)
self.e=e
self.reduction=reduction

def_one_hot(self,labels,classes,value=1):
"""

Convertlabelstoonehotvectors

Args:
labels:torchtensorinformat[label1,label2,label3,...]
classes:int,numberofclasses
value:labelvalueinonehotvector,defaultto1

Returns:
returnonehotformatlabelsinshape[batchsize,classes]
"""

one_hot=torch.zeros(labels.size(0),classes)

#labelsandvalue_addedsizemustmatch
labels=labels.view(labels.size(0),-1)
value_added=torch.Tensor(labels.size(0),1).fill_(value)

value_added=value_added.to(labels.device)
one_hot=one_hot.to(labels.device)

one_hot.scatter_add_(1,labels,value_added)

returnone_hot

def_smooth_label(self,target,length,smooth_factor):
"""converttargetstoone-hotformat,andsmooththem.
Args:
target:targetinformwith[label1,label2,label_batchsize]
length:lengthofone-hotformat(numberofclasses)
smooth_factor:smoothfactorforlabelsmooth

Returns:
smoothedlabelsinonehotformat
"""
one_hot=self._one_hot(target,length,value=1-smooth_factor)
one_hot+=smooth_factor/length

returnone_hot.to(target.device)

Random image cropping and patching

Random image cropping and patching (RICAP)[7]方法随机裁剪四个图片的中部分,然后把它们拼接为一个图片,同时混合这四个图片的标签。

RICAP在caifar10上达到了2.19%的错误率。

如下图所示,Ix, Iy是原始图片的宽和高。w和h称为boundary position,它决定了四个裁剪得到的小图片的尺寸。w和h从beta分布Beta(β, β)中随机生成,β也是RICAP的超参数。最终拼接的图片尺寸和原图片尺寸保持一致。

88aa8aae-33e4-11ed-ba43-dac502259ad0.jpg

RICAP的代码如下:

beta=0.3#hyperparameter
for(images,targets)intrain_loader:

#gettheimagesize
I_x,I_y=images.size()[2:]

#drawaboundryposition(w,h)
w=int(np.round(I_x*np.random.beta(beta,beta)))
h=int(np.round(I_y*np.random.beta(beta,beta)))
w_=[w,I_x-w,w,I_x-w]
h_=[h,h,I_y-h,I_y-h]

#selectandcropfourimages
cropped_images={}
c_={}
W_={}
forkinrange(4):
index=torch.randperm(images.size(0))
x_k=np.random.randint(0,I_x-w_[k]+1)
y_k=np.random.randint(0,I_y-h_[k]+1)
cropped_images[k]=images[index][:,:,x_k:x_k+w_[k],y_k:y_k+h_[k]]
c_[k]=target[index].cuda()
W_[k]=w_[k]*h_[k]/(I_x*I_y)

#patchcroppedimages
patched_images=torch.cat(
(torch.cat((cropped_images[0],cropped_images[1]),2),
torch.cat((cropped_images[2],cropped_images[3]),2)),
3)
#patched_images=patched_images.cuda()

#getoutput
output=model(patched_images)

#calculatelossandaccuracy
loss=sum([W_[k]*criterion(output,c_[k])forkinrange(4)])
acc=sum([W_[k]*accuracy(output,c_[k])[0]forkinrange(4)])

Knowledge Distillation

提高几乎所有机器学习算法性能的一种非常简单的方法是在相同的数据上训练许多不同的模型,然后对它们的预测进行平均。但是使用所有的模型集成进行预测是比较麻烦的,并且可能计算量太大而无法部署到大量用户。Knowledge Distillation(知识蒸馏)[8]方法就是应对这种问题的有效方法之一。

在知识蒸馏方法中,我们使用一个教师模型来帮助当前的模型(学生模型)训练。教师模型是一个较高准确率的预训练模型,因此学生模型可以在保持模型复杂度不变的情况下提升准确率。比如,可以使用ResNet-152作为教师模型来帮助学生模型ResNet-50训练。在训练过程中,我们会加一个蒸馏损失来惩罚学生模型和教师模型的输出之间的差异。

给定输入,假定p是真正的概率分布,z和r分别是学生模型和教师模型最后一个全连接层的输出。之前我们会用交叉熵损失l(p,softmax(z))来度量p和z之间的差异,这里的蒸馏损失同样用交叉熵。所以,使用知识蒸馏方法总的损失函数是

88bf3a4e-33e4-11ed-ba43-dac502259ad0.jpg

上式中,第一项还是原来的损失函数,第二项是添加的用来惩罚学生模型和教师模型输出差异的蒸馏损失。其中,T是一个温度超参数,用来使softmax的输出更加平滑的。实验证明,用ResNet-152作为教师模型来训练ResNet-50,可以提高后者的准确率。

Cutout

Cutout[9]是一种新的正则化方法。原理是在训练时随机把图片的一部分减掉,这样能提高模型的鲁棒性。它的来源是计算机视觉任务中经常遇到的物体遮挡问题。通过cutout生成一些类似被遮挡的物体,不仅可以让模型在遇到遮挡问题时表现更好,还能让模型在做决定时更多地考虑环境(context)。

代码如下:

importtorch
importnumpyasnp

classCutout(object):
"""Randomlymaskoutoneormorepatchesfromanimage.
Args:
n_holes(int):Numberofpatchestocutoutofeachimage.
length(int):Thelength(inpixels)ofeachsquarepatch.
"""
def__init__(self,n_holes,length):
self.n_holes=n_holes
self.length=length

def__call__(self,img):
"""
Args:
img(Tensor):Tensorimageofsize(C,H,W).
Returns:
Tensor:Imagewithn_holesofdimensionlengthxlengthcutoutofit.
"""
h=img.size(1)
w=img.size(2)

mask=np.ones((h,w),np.float32)

forninrange(self.n_holes):
y=np.random.randint(h)
x=np.random.randint(w)

y1=np.clip(y-self.length//2,0,h)
y2=np.clip(y+self.length//2,0,h)
x1=np.clip(x-self.length//2,0,w)
x2=np.clip(x+self.length//2,0,w)

mask[y1:y2,x1:x2]=0.

mask=torch.from_numpy(mask)
mask=mask.expand_as(img)
img=img*mask

returnimg

效果如下图,每个图片的一小部分被cutout了。

Random erasing

Random erasing[6]其实和cutout非常类似,也是一种模拟物体遮挡情况的数据增强方法。区别在于,cutout是把图片中随机抽中的矩形区域的像素值置为0,相当于裁剪掉,random erasing是用随机数或者数据集中像素的平均值替换原来的像素值。而且,cutout每次裁剪掉的区域大小是固定的,Random erasing替换掉的区域大小是随机的。

Random erasing代码如下:

from__future__importabsolute_import
fromtorchvision.transformsimport*
fromPILimportImage
importrandom
importmath
importnumpyasnp
importtorch

classRandomErasing(object):
'''
probability:Theprobabilitythattheoperationwillbeperformed.
sh:maxerasingarea
r1:minaspectratio
mean:erasingvalue
'''
def__init__(self,probability=0.5,sl=0.02,sh=0.4,r1=0.3,mean=[0.4914,0.4822,0.4465]):
self.probability=probability
self.mean=mean
self.sl=sl
self.sh=sh
self.r1=r1
def__call__(self,img):
ifrandom.uniform(0,1)>self.probability:
returnimg

forattemptinrange(100):
area=img.size()[1]*img.size()[2]

target_area=random.uniform(self.sl,self.sh)*area
aspect_ratio=random.uniform(self.r1,1/self.r1)

h=int(round(math.sqrt(target_area*aspect_ratio)))
w=int(round(math.sqrt(target_area/aspect_ratio)))

ifw< img.size()[2]  and h < img.size()[1]:
                x1 = random.randint(0, img.size()[1]  - h)
                y1 = random.randint(0, img.size()[2]  - w)
                if img.size()[0]  ==  3:
                    img[0, x1:x1+h, y1:y1+w]  = self.mean[0]
                    img[1, x1:x1+h, y1:y1+w]  = self.mean[1]
                    img[2, x1:x1+h, y1:y1+w]  = self.mean[2]
                else:
                    img[0, x1:x1+h, y1:y1+w]  = self.mean[0]
                return img
    return img

Cosine learning rate decay

在warmup之后的训练过程中,学习率不断衰减是一个提高精度的好方法。其中有step decay和cosine decay等,前者是随着epoch增大学习率不断减去一个小的数,后者是让学习率随着训练过程曲线下降。

对于cosine decay,假设总共有T个batch(不考虑warmup阶段),在第t个batch时,学习率η_t为:

88eff800-33e4-11ed-ba43-dac502259ad0.jpg

这里,η代表初始设置的学习率。这种学习率递减的方式称之为cosine decay。

下面是带有warmup的学习率衰减的可视化图[4]。其中,图(a)是学习率随epoch增大而下降的图,可以看出cosine decay比step decay更加平滑一点。图(b)是准确率随epoch的变化图,两者最终的准确率没有太大差别,不过cosine decay的学习过程更加平滑。

88fad680-33e4-11ed-ba43-dac502259ad0.jpg

在pytorch的torch.optim.lr_scheduler中有更多的学习率衰减的方法,至于哪个效果好,可能对于不同问题答案是不一样的。对于step decay,使用方法如下:

#Assumingoptimizeruseslr=0.05forallgroups
#lr=0.05ifepoch< 30
# lr = 0.005    if 30 <= epoch < 60
# lr = 0.0005   if 60 <= epoch < 90

from torch.optim.lr_scheduler import  StepLR
scheduler =  StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(100):
    scheduler.step()
    train(...)
    validate(...)

Mixup training

Mixup[10]是一种新的数据增强的方法。Mixup training,就是每次取出2张图片,然后将它们线性组合,得到新的图片,以此来作为新的训练样本,进行网络的训练,如下公式,其中x代表图像数据,y代表标签,则得到的新的xhat, yhat。

89080256-33e4-11ed-ba43-dac502259ad0.jpg

其中,λ是从Beta(α, α)随机采样的数,在[0,1]之间。在训练过程中,仅使用(xhat, yhat)。Mixup方法主要增强了训练样本之间的线性表达,增强网络的泛化能力,不过mixup方法需要较长的时间才能收敛得比较好。

Mixup代码如下:

for(images,labels)intrain_loader:

l=np.random.beta(mixup_alpha,mixup_alpha)

index=torch.randperm(images.size(0))
images_a,images_b=images,images[index]
labels_a,labels_b=labels,labels[index]

mixed_images=l*images_a+(1-l)*images_b

outputs=model(mixed_images)
loss=l*criterion(outputs,labels_a)+(1-l)*criterion(outputs,labels_b)
acc=l*accuracy(outputs,labels_a)[0]+(1-l)*accuracy(outputs,labels_b)[0]

AdaBound

AdaBound是最近一篇论文[5]中提到的,按照作者的说法,AdaBound会让你的训练过程像adam一样快,并且像SGD一样好。如下图所示,使用AdaBound会收敛速度更快,过程更平滑,结果更好。

8916318c-33e4-11ed-ba43-dac502259ad0.jpg

另外,这种方法相对于SGD对超参数的变化不是那么敏感,也就是说鲁棒性更好。但是,针对不同的问题还是需要调节超参数的,只是所用的时间可能变少了。

8924b75c-33e4-11ed-ba43-dac502259ad0.jpg

当然,AdaBound还没有经过普遍的检验,也有可能只是对于某些问题效果好。

使用方法如下:安装AdaBound

pipinstalladabound

使用AdaBound(和其他PyTorch optimizers用法一致)

optimizer=adabound.AdaBound(model.parameters(),lr=1e-3,final_lr=0.1)

AutoAugment

数据增强在图像分类问题上有很重要的作用,但是增强的方法有很多,并非一股脑地用上所有的方法就是最好的。那么,如何选择最佳的数据增强方法呢?AutoAugment[11]就是一种搜索适合当前问题的数据增强方法的方法。该方法创建一个数据增强策略的搜索空间,利用搜索算法选取适合特定数据集的数据增强策略。此外,从一个数据集中学到的策略能够很好地迁移到其它相似的数据集上。

AutoAugment在cifar10上的表现如下表,达到了98.52%的准确率。

8934adce-33e4-11ed-ba43-dac502259ad0.jpg

其他经典的tricks

常用的正则化方法为

Dropout

L1/L2正则

Batch Normalization

Early stopping

Random cropping

Mirroring

Rotation

Color shifting

PCA color augmentation

...

其他

Xavier init[12]

...

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 图像分割
    +关注

    关注

    4

    文章

    182

    浏览量

    17998
  • 模型
    +关注

    关注

    1

    文章

    3237

    浏览量

    48824
  • 计算机视觉
    +关注

    关注

    8

    文章

    1698

    浏览量

    45986

原文标题:其他经典的tricks

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于多通道分类合成的SAR图像分类研究

    【作者】:李长春;冒亚明;孙灏;慎利;【来源】:《计算机与现代化》2010年03期【摘要】:SAR具有全天时、全天候工作能力,且能够提供高分辨率图像数据。SAR图像分类是SAR图像处理
    发表于 04-23 11:52

    区分图像分类方法是什么

    区分图像分类方法
    发表于 05-07 09:37

    基于Brushlet和RBF网络的SAR图像分类

    针对SAR图像纹理特征丰富的特点,本文提出一种新的SAR图像分类方法:通过提取Brushlet变换的能量及相位信息作为SAR图像的纹理特征,然后输入径向基函数RBF网络对
    发表于 12-18 16:20 20次下载

    Programming Tricks for Higher Conversion Speeds Utilizing De

    PROGRAMMING TRICKS FOR HIGHER CONVERSION SPEEDS UTILIZING DELTA SIGMA CONVERTERS:编程更高的转换利用Δ-Σ转换速度把戏
    发表于 06-01 18:05 28次下载

    图像分类的方法之深度学习与传统机器学习

    图像分类,顾名思义,是一个输入图像,输出对该图像内容分类的描述的问题。它是计算机视觉的核心,实际应用广泛。
    发表于 09-28 19:43 0次下载

    基于显著性检测的图像分类算法

    针对传统的图像分类方法对整个图像不分等级处理以及缺乏高层认知的问题,提出了一种基于显著性检测的图像分类方法。首先,利用视觉注意模型进行显著性
    发表于 01-04 13:47 0次下载

    简单好上手的图像分类教程!

    简单好上手的图像分类教程!构建图像分类模型的一个突破是发现卷积神经网络(CNN)可以用来逐步地提取图像内容的更高层的表示。CNN不是预先处理
    的头像 发表于 05-31 16:36 8239次阅读
    简单好上手的<b class='flag-5'>图像</b><b class='flag-5'>分类</b>教程!

    如何利用机器学习思想,更好地去解决NLP分类任务

    NLP分类任务我们每个NLPer都异常熟悉了,其在整个NLP业务中占据着举足轻重的地位,更多领域的子任务也常常转化为一个分类任务,例如新闻
    的头像 发表于 08-28 10:02 2267次阅读
    如何利用机器学习思想,更好地去解决NLP<b class='flag-5'>分类</b><b class='flag-5'>任务</b>

    针对遥感图像场景分类的多粒度特征蒸馏方法

    深度神经网络广泛应用于遥感图像场景分类任务中并能大幅提高分类精度,但隐藏层数较少的神经网络在标记数据不足的遥感场景分类中泛化能力较低,而隐层
    发表于 03-11 17:18 20次下载
    针对遥感<b class='flag-5'>图像</b>场景<b class='flag-5'>分类</b>的多粒度特征蒸馏方法

    关于深度学习图像分类不得不说的技巧详解

    计算机视觉主要问题有图像分类、目标检测和图像分割等。针对图像分类任务,提升准确率的方法路线有两条
    的头像 发表于 04-01 14:29 2958次阅读
    关于深度学习<b class='flag-5'>图像</b><b class='flag-5'>分类</b>不得不说的技巧详解

    文本分类任务的Bert微调trick大全

    1 前言 大家现在打比赛对预训练模型非常喜爱,基本上作为NLP比赛基线首选(图像分类也有预训练模型)。预训练模型虽然很强,可能通过简单的微调就能给我们带来很大提升,但是大家会发现比赛做到后期
    的头像 发表于 07-18 09:49 2484次阅读

    图像关系型KD方法语义分割任务-CIRKD

    语义分割任务作为计算机视觉中的基础任务之一,其目的是对图像中的每一个像素进行分类。该任务也被广泛应用于实践,例如自动驾驶和医学
    的头像 发表于 05-10 11:30 2444次阅读
    跨<b class='flag-5'>图像</b>关系型KD方法语义分割<b class='flag-5'>任务</b>-CIRKD

    一种对红细胞和白细胞图像分类任务的主动学习端到端工作流程

    细胞成像的分割和分类等技术是一个快速发展的领域研究。就像在其他机器学习领域一样,数据的标注是非常昂贵的,并且对于数据标注的质量要求也非常的高。针对这一问题,本篇文章介绍一种对红细胞和白细胞图像分类
    的头像 发表于 08-13 10:27 1266次阅读

    计算机视觉的5大核心任务是什么?

    图像分类是将图像分配到某个特定类别的任务,而图像识别则进一步将类别关联到具体的实体或对象。例如,分类
    发表于 08-28 11:45 886次阅读
    计算机视觉的5大核心<b class='flag-5'>任务</b>是什么?

    计算机视觉怎么给图像分类

    图像分类是计算机视觉领域中的一项核心任务,其目标是将输入的图像自动分配到预定义的类别集合中。这一过程涉及图像的特征提取、特征表示以及
    的头像 发表于 07-08 17:06 675次阅读