pytorch中的正则化,自定义优化器设置等操作

本文详细介绍了PyTorch中优化器的使用,包括SGD、Adam等,以及如何通过weight_decay实现L2正则化。特别讲解了如何针对不同层设置不同的学习率和正则化强度,提供代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1) pytorch中的L2和L1正则化,自定义优化器设置等操作

https://ptorch.com/docs/1/optim

在pytorch中进行L2正则化,最直接的方式可以直接用优化器自带的weight_decay选项指定权值衰减率,相当于L2正则化中的λ \lambdaλ,也就是:

中的λ \lambdaλ。但是有一个问题就是,这个指定的权值衰减是会对网络中的所有参数,包括权值w ww和偏置b bb同时进行的,很多时候如果对b bb进行L2正则化将会导致严重的欠拟合1,因此这个时候一般只需要对权值进行正则即可,当然,你可以获取模型中的所有权值,然后按照定义的方法显式地进行处理,得到一个正则损失之后在交给优化器优化,这是一个通用的方法。但是其实还有更为简单的方法,同样在优化器中提供了。

torch.optim中包含了很多现成的优化器,包括SGD,Adadelta,Adam,Adagrad,RMSprop等,使用它很简单,你需要传入一个可迭代的参数列表(里面必须都是Variable类型的)进行优化,然后你可以指定一些优化器的参数,如学习率,动量,权值衰减等。例子如:

optimizer = optim.SGD(model.parameters(), lr = 0.01, momentum=0.9,weight_decay=1e-5)
optimizer = optim.Adam([var1, var2], lr = 0.0001)

此外,优化器还支持一种称之为Per-parameter options的操作,就是对每一个参数进行特定的指定,以满足更为细致的要求。做法也很简单,与上面不同的,我们传入的待优化变量不是一个Variable而是一个可迭代的字典,字典中必须有params的key,用于指定待优化变量,而其他的key需要匹配优化器本身的参数设置。我们看一下例子:

optim.SGD([
                {'params': model.base.parameters()},
                {'params': model.classifier.parameters(), 'lr': 1e-3}
            ], lr=1e-2, momentum=0.9)

其中,我们可以看到,传入的list中有两个字典,每一个都是一个独立的参数组,其中每一组中都有一个paramskey,用于指定需要训练的参数,如model.base.parameters()就是base网络中的所有参数,尔后,也可以在每一组内单独设置学习率,权值衰减等。如果不显式地在组内设定,那么就会继承优化器的全局参数,如lr=1e-2,momentum=0.9等,如果组内指定了,那么全局的将不会覆盖掉组内的参数设置。
这样我们就可以灵活的给每一个子网络设定不同的学习率,权值衰减,momentum了,我们也可以给权值设定权值衰减,而不作用与偏置,如:

weight_p, bias_p = [],[]
for name, p in model.named_parameters():
  if 'bias' in name:
     bias_p += [p]
   else:
     weight_p += [p]
# 这里的model中每个参数的名字都是系统自动命名的,只要是权值都是带有weight,偏置都带有bias,
# 因此可以通过名字判断属性,这个和tensorflow不同,tensorflow是可以用户自己定义名字的,当然也会系统自己定义。
optim.SGD([
          {'params': weight_p, 'weight_decay':1e-5},
          {'params': bias_p, 'weight_decay':0}
          ], lr=1e-2, momentum=0.9)

Update 2018-12-12:
有朋友说博文的方法好像报错,我这里又试了下,并没有问题。环境是pytorch 1.0.0,jupyter notebook,ubuntu 16.04。完整测试代码如下:

import torch
import torch.nn as nn
import numpy as np

## build model
class net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(100,50)
        self.fc2 = nn.Linear(50,1)
        self.relu = nn.ReLU(inplace=True)
    def forward(self, inputs):
        layer = self.fc1(inputs)
        layer = self.relu(layer)
        layer = self.fc2(layer)
        return layer
## analoy inputs and labels
inputs = np.random.normal(size=(8,100))
inputs = torch.tensor(inputs).float()
labels = np.ones((8,1))
labels = torch.tensor(labels).float()

## update the weights and bias with L2 weight decay 
n = net()
weight_p, bias_p = [],[]
for name, p in n.named_parameters():
    if 'bias' in name:
        bias_p += [p]
    else:
        weight_p += [p]
        
criterion = nn.MSELoss()
logit = n(inputs)
loss = criterion(input=logit, target=labels)
opt = torch.optim.SGD([{'params': weight_p, 'weight_decay':1e-5},
                      {'params': bias_p, 'weight_decay':0}], 
                      lr=1e-2, 
                      momentum=0.9)

## update
opt.zero_grad()
loss.backward()
opt.step()        

请各位试试,谢谢。

Reference
[1]. PyTorch Documentation -> torch.optim
--------------------- 
作者:FesianXu 
来源:CSDN 
原文:https://blog.csdn.net/LoseInVain/article/details/81708474 
版权声明:本文为博主原创文章,转载请附上博文链接!

(2) Adding L1/L2 regularization in PyTorch?

Following should help for L2 regularization:

optimizer = torch.optim.Adam(model.parameters(), lr=1e-4, weight_decay=1e-5)

https://discuss.pytorch.org/t/how-does-one-implement-weight-regularization-l1-or-l2-manually-without-optimum/7951/19

(3) pytorch在不同的层使用不同的学习率
有时候我们希望某些层的学习率与整个网络有些差别,这里我简单介绍一下在pytorch里如何设置,方法略麻烦,如果有更好的方法,请务必教我:

首先我们定义一个网络:

class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, 1)
        self.conv2 = nn.Conv2d(64, 64, 1)
        self.conv3 = nn.Conv2d(64, 64, 1)
        self.conv4 = nn.Conv2d(64, 64, 1)
        self.conv5 = nn.Conv2d(64, 64, 1)
    def forward(self, x):
        out = conv5(conv4(conv3(conv2(conv1(x)))))
        return out

我们希望conv5学习率是其他层的100倍,我们可以:

net = net()
lr = 0.001

conv5_params = list(map(id, net.conv5.parameters()))
base_params = filter(lambda p: id(p) not in conv5_params,
                     net.parameters())
optimizer = torch.optim.SGD([
            {'params': base_params},
            {'params': net.conv5.parameters(), 'lr': lr * 100},
, lr=lr, momentum=0.9)

如果多层,则:

conv5_params = list(map(id, net.conv5.parameters()))
conv4_params = list(map(id, net.conv4.parameters()))
base_params = filter(lambda p: id(p) not in conv5_params + conv4_params,
                     net.parameters())
optimizer = torch.optim.SGD([
            {'params': base_params},
            {'params': net.conv5.parameters(), 'lr': lr * 100},
            {'params': net.conv4.parameters(), 'lr': lr * 100},
            , lr=lr, momentum=0.9)
 

--------------------- 
作者:BinWang-cvlab 
来源:CSDN 
原文:https://blog.csdn.net/wangbin12122224/article/details/79949824 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值