本文最后更新于:2022年7月21日 下午
深度学习调参笔记#1-正则化(weight decay)
在模型过拟合的时候,总是会想着添加正则化,在PyTorch中常用的添加正则化的方法,就是在优化器中添加weight_decay
参数,然而,调参过程中也有一些细节需要注意。
首先要弄明白正则化的目的,《深度学习》书的第七章中提到,正则化旨在减少泛化误差而不是训练误差 ,其中最常用的一个方式就是参数范数惩罚 。这个方法简单来说就是在损失函数中添加一项α Ω ( θ ) \alpha\Omega(\theta) α Ω ( θ ) ,α \alpha α 表示惩罚强度、Ω ( θ ) \Omega(\theta) Ω ( θ ) 表示模型的复杂度。添加这个之后,就会倾向于学习更简单的网络。
要注意的点就是,通常只对权重(weight)做惩罚而 不对偏置(bias)做正则惩罚。过拟合实际上是模型对于轻微的输入改变,产生剧烈的输出改变,而输出结果 主要 取决于权重而不是偏置,所以权重的L2更能起到表示模型复杂度的作用。偏置对模型复杂度贡献较低,但是对最终结果有一定影响,假如惩罚了偏置,可能会导致欠拟合。
那么在PyTorch中如何只对权重做惩罚呢?
参考yolov5代码 ,下面为了排版有部分删减:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 g = [], [], [] bn = tuple (v for k, v in nn.__dict__.items() if 'Norm' in k) for v in model.modules(): if hasattr (v, 'bias' ) and isinstance (v.bias, nn.Parameter): g[2 ].append(v.bias) if isinstance (v, bn): g[1 ].append(v.weight) elif hasattr (v, 'weight' ) and isinstance (v.weight, nn.Parameter): g[0 ].append(v.weight) if opt.optimizer == 'Adam' : optimizer = Adam(g[2 ], lr=hyp['lr0' ], betas=(hyp['momentum' ], 0.999 )) elif opt.optimizer == 'AdamW' : optimizer = AdamW(g[2 ], lr=hyp['lr0' ], betas=(hyp['momentum' ], 0.999 )) optimizer.add_param_group({'params' : g[0 ], 'weight_decay' :hyp['weight_decay' ]}) optimizer.add_param_group({'params' : g[1 ]})
也可以参考MAE代码 ,使用timm库的一个函数来设置(新版本有改动,没对应函数了)
1 2 3 4 5 6 import timmassert timm.__version__ == "0.3.2" import timm.optim.optim_factory as optim_factory param_groups = optim_factory.add_weight_decay(model_without_ddp, args.weight_decay) optimizer = torch.optim.AdamW(param_groups, lr=args.lr, betas=(0.9 , 0.95 ))
timm中每一层的weight_decay
还不一样:pytorch-image-models/optim_factory.py at master · rwightman/pytorch-image-models (github.com)
参考资料:
《深度学习》
深度学习里面的偏置为什么不加正则? - 知乎 (zhihu.com)