100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 再也不用担心过拟合的问题了

再也不用担心过拟合的问题了

时间:2019-03-06 04:54:48

相关推荐

再也不用担心过拟合的问题了

点击上方“视学算法”,选择加"星标"或“置顶

重磅干货,第一时间送达

作者 | Sean Benhur J

编译 | ronghuaiyang

转自 | AI公园

使用SAM(锐度感知最小化),优化到损失的最平坦的最小值的地方,增强泛化能力。

论文:/pdf/.01412.pdf

代码:/moskomule/sam.pytorch

动机来自先前的工作,在此基础上,我们提出了一种新的、有效的方法来同时减小损失值和损失的锐度。具体来说,在我们的处理过程中,进行锐度感知最小化(SAM),在领域内寻找具有均匀的低损失值的参数。这个公式产生了一个最小-最大优化问题,在这个问题上梯度下降可以有效地执行。我们提出的实证结果表明,SAM在各种基准数据集上都改善了的模型泛化。

在深度学习中,我们使用SGD/Adam等优化算法在我们的模型中实现收敛,从而找到全局最小值,即训练数据集中损失较低的点。但等几种研究表明,许多网络可以很容易地记住训练数据并有能力随时overfit,为了防止这个问题,增强泛化能力,谷歌研究人员发表了一篇新论文叫做Sharpness Awareness Minimization,在CIFAR10上以及其他的数据集上达到了最先进的结果。

在本文中,我们将看看为什么SAM可以实现更好的泛化,以及我们如何在Pytorch中实现SAM。

SAM的原理是什么?

在梯度下降或任何其他优化算法中,我们的目标是找到一个具有低损失值的参数。但是,与其他常规的优化方法相比,SAM实现了更好的泛化,它将重点放在领域内寻找具有均匀的低损失值的参数(而不是只有参数本身具有低损失值)上。

由于计算邻域参数而不是计算单个参数,损失超平面比其他优化方法更平坦,这反过来增强了模型的泛化。

(左))用SGD训练的ResNet收敛到的一个尖锐的最小值。(右)用SAM训练的相同的ResNet收敛到的一个平坦的最小值。

注意:SAM不是一个新的优化器,它与其他常见的优化器一起使用,比如SGD/Adam。

在Pytorch中实现SAM

在Pytorch中实现SAM非常简单和直接

importtorchclassSAM(torch.optim.Optimizer):def__init__(self,params,base_optimizer,rho=0.05,**kwargs):assertrho>=0.0,f"Invalidrho,shouldbenon-negative:{rho}"defaults=dict(rho=rho,**kwargs)super(SAM,self).__init__(params,defaults)self.base_optimizer=base_optimizer(self.param_groups,**kwargs)self.param_groups=self.base_optimizer.param_groups@torch.no_grad()deffirst_step(self,zero_grad=False):grad_norm=self._grad_norm()forgroupinself.param_groups:scale=group["rho"]/(grad_norm+1e-12)forpingroup["params"]:ifp.gradisNone:continuee_w=p.grad*scale.to(p)p.add_(e_w)#climbtothelocalmaximum"w+e(w)"self.state[p]["e_w"]=e_wifzero_grad:self.zero_grad()@torch.no_grad()defsecond_step(self,zero_grad=False):forgroupinself.param_groups:forpingroup["params"]:ifp.gradisNone:continuep.sub_(self.state[p]["e_w"])#getbackto"w"from"w+e(w)"self.base_optimizer.step()#dotheactual"sharpness-aware"updateifzero_grad:self.zero_grad()def_grad_norm(self):shared_device=self.param_groups[0]["params"][0].device#puteverythingonthesamedevice,incaseofmodelparallelismnorm=torch.norm(torch.stack([p.grad.norm(p=2).to(shared_device)forgroupinself.param_groupsforpingroup["params"]ifp.gradisnotNone]),p=2)returnnorm

代码取自非官方的Pytorch实现。

代码解释:

首先,我们从Pytorch继承优化器类来创建一个优化器,尽管SAM不是一个新的优化器,而是在需要继承该类的每一步更新梯度(在基础优化器的帮助下)。

该类接受模型参数、基本优化器和rho, rho是计算最大损失的邻域大小。

在进行下一步之前,让我们先看看文中提到的伪代码,它将帮助我们在没有数学的情况下理解上述代码。

正如我们在计算第一次反向传递后的伪代码中看到的,我们计算epsilon并将其添加到参数中,这些步骤是在上述python代码的方法first_step中实现的。

现在在计算了第一步之后,我们必须回到之前的权重来计算基础优化器的实际步骤,这些步骤在函数second_step中实现。

函数_grad_norm用于返回矩阵向量的norm,即伪代码的第10行

在构建这个类后,你可以简单地使用它为你的深度学习项目通过以下的训练函数片段。

fromsamimportSAM...model=YourModel()base_optimizer=torch.optim.SGD#defineanoptimizerforthe"sharpness-aware"updateoptimizer=SAM(model.parameters(),base_optimizer,lr=0.1,momentum=0.9)...forinput,outputindata:#firstforward-backwardpassloss=loss_function(output,model(input))#usethislossforanytrainingstatisticsloss.backward()optimizer.first_step(zero_grad=True)#secondforward-backwardpassloss_function(output,model(input)).backward()#makesuretodoafullforwardpassoptimizer.second_step(zero_grad=True)...

总结

虽然SAM的泛化效果较好,但是这种方法的主要缺点是,由于前后两次计算锐度感知梯度,需要花费两倍的训练时间。除此之外,SAM还在最近发布的NFNETS上证明了它的效果,这是ImageNet目前的最高水平,在未来,我们可以期待越来越多的论文利用这一技术来实现更好的泛化。

英文原文:/we-dont-need-to-worry-about-overfitting-anymore-9fb31a154c81

点个在看 paper不断!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。