0
点赞
收藏
分享

微信扫一扫

PyTorch优化器正则化问题:偏置(bias)不需要正则化(weight decay) / 如何分离网络参数中的偏置(bias)?



文章目录

  • 问题描述
  • 解决方案


问题描述

截至目前,PyTorch中有一个潜在的不合理之处,即pytorch优化器中的正则化会将所有可训练参数都进行正则化,而理论上,偏置(bias)是没有必要进行正则化的(反而会限制模型的能力)。以Adam优化器为例,我们在模型的训练开始之前,一般会这样定义优化器:

optimizer = torch.optim.Adam(net.parameters(), lr=0.01, weight_decay=0.0001)

其中weight_decay为正则化项的系数。如上定义,模型在训练时,模型的所有参数(即net.parameters())都将被正则化,而我们希望其中的偏置(bias)不要被正则化。怎么办?

解决方案

pytorch的torch.optim.Adam的第一个参数接受一个可学习参数的迭代器(或列表),同时还可以是字典。如下

optimizer = torch.optim.Adam([
    {'params': net.layer.weight, 'weight_decay': 0.0001},
    {'params': net.layer.bias}
], lr=0.01)

如上指定了可学习参数net.layer.bias(这是网络中的一个偏置参数)的学习率lr0.01weight_decay0(也就是没有正则化项)。

对于非常简单的模型,我们可以手动把可学习参数写成如上代码中的字典形式,但对于比较复杂的模型很难手动一个一个的分离出来。通过分析发现,对于比较复杂的模型,其中所有的偏置参数的名字中都含有子串"bias",如下测试:

PyTorch优化器正则化问题:偏置(bias)不需要正则化(weight decay) / 如何分离网络参数中的偏置(bias)?_pytorch


其中named_parameters()函数可以获取当前模型中所有的参数(含不可训练的参数)。于是,我们可以这样分离出偏置参数:

bias_list = (p for name, p in net.named_parameters() if 'bias' in name)

注意细节,这里用的是圆括号()而不是[],因为[]默认是列表,会主动进行一次遍历并返回这个列表,而()返回值为迭代器,只有当被动的迭代它时它才会去计算。话句话说就是[]复杂度高一倍。

最终,我们的优化器如下定义即可实现仅weight正则化而bias取消正则化

optimizer = torch.optim.Adam([
    {'params': (p for name, p in net.named_parameters() if 'bias' not in name), 'weight_decay': 0.0001},
    {'params': (p for name, p in net.named_parameters() if 'bias' in name)}
], lr=0.01)


举报

相关推荐

0 条评论