pytorch 指定网络不同部分使用不同学习率

文章介绍了在PyTorch中如何针对模型的不同层设置不同的学习率,以适应如微调预训练模型等场景。通过优化器参数设置,可以将模型的参数分为不同的组,并为每组指定独立的学习率。示例代码展示了如何为网络的不同部分如卷积层、线性层设置不同的学习率。
摘要由CSDN通过智能技术生成

参考:Pytorch不同层设置不同学习率_呆呆象呆呆的博客-CSDN博客_pytorch 不同层不同学习率

        自己做记录使用,大家可以去看原作者哦! 他写的更清晰!

        有时做优化时不同的层需要设置不同的学习率,例如: 在对预训练语言模型进行调参时,只希望拿自己的数据对模型进行微调,不过多改变模型本身的参数,这时要设置较小的学习率;但是其他网络部分,需要设置相对较大些的学习率加速模型收敛

        这样就需要对模型的部分设置不同的学习率,设置方法如下。

全局设置学习率

优化器参数展示:

params (iterable): iterable of parameters to optimize or dicts defining
            parameter groups,该参数为迭代器形式,或者字典形式

lr (float, optional): learning rate (default: 1e-3)

betas (Tuple[float, float], optional): coefficients used for computing
            running averages of gradient and its square (default: (0.9, 0.999))

eps (float, optional): term added to the denominator to improve
            numerical stability (default: 1e-8)

weight_decay (float, optional): weight decay (L2 penalty) (default: 0)

amsgrad (boolean, optional): whether to use the AMSGrad variant of this
            algorithm from the paper `On the Convergence of Adam and Beyond`_
            (default: False)

foreach (bool, optional): whether foreach implementation of optimizer
            is used (default: None)

maximize (bool, optional): maximize the params based on the objective, instead of
            minimizing (default: False)

capturable (bool, optional): whether this instance is safe to capture in a CUDA graph.

Passing True can impair ungraphed performance, so if you don't intend to graph capture this instance, leave it False (default: False)

针对模型全局参数统一设置学习率:

optimizer = optim.SGD(net.parameters(), lr=0.001 )

优化器的第一个参数要设置为迭代器形式。

针对网络不同部分设置学习率

主要做的改变是针对第一个参数

        将集合迭代器(net.parameters())分为不同的部分 -- 列表形式,列表内各个元素为字典形式,字典内部设置不同的迭代器和参数;

代码举例:

        (1) 不同层的网络结构使用类内函数.parameters()得到不同层的迭代器;

     或者,   (2)以字典的形式进行对不同参数组的所需要的优化参数定义;

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.net1 = nn.Linear(2,10)
        self.net2 = nn.Linear(10,1)
    def forward(self, x):
        x = self.net1(x)
        x = self.net2(x)
        return x
net = Net()
#不同层的网络结构使用类内函数.parameters()得到不同层的迭代器
optimizer = optim.SGD([
                    {'params': net.net1.parameters(),'lr': 1e-2},
                    {'params': net.net1.parameters(), 'lr': 1e-1}])

# 或者以字典的形式进行对不同参数组的所需要的优化参数定义
optimizer = optim.SGD([
                    {'params': [net.net1.weight,net.net2.weight],'lr': 1e-2},
                    {'params': [net.net1.bias,net.net2.bias], 'lr': 1e-1}])
for epoch in range(100):
        print("Epoch:{}  Lr:{:.2E}".format(epoch,optimizer.state_dict()['param_groups'][0]['lr']))
        print("Epoch:{}  Lr:{:.2E}".format(epoch,optimizer.state_dict()['param_groups'][1]['lr']))
        optimizer.step()

或者(3)通过一些常用的函数获得参数迭代器lambda, map,filterid

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.conv1 = nn.Conv2d(3,32,3)
        self.conv2 = nn.Conv2d(32,24,3)
        self.prelu = nn.PReLU()
        for m in self.modules():
            if isinstance(m,nn.Conv2d):
                nn.init.xavier_normal_(m.weight.data)
                nn.init.constant_(m.bias.data,0)
            if isinstance(m,nn.Linear):
                m.weight.data.normal_(0.01,0,1)
                m.bias.data.zero_()
 
    def forward(self, input):
        out = self.conv1(input)
        out = self.conv2(out)
        out = self.prelu(out)
        return out

model = Net()
conv_params = list(map(id,model.conv1.parameters()))   #提出前两个卷积层存放参数的地址
conv_params += list(map(id,model.conv2.parameters()))
prelu_params = []
for m in model.modules():    #找到Prelu的参数
    if isinstance(m, nn.PReLU):
        prelu_params += m.parameters()
 
#假象网络很大,还有一部分参数,这部分参数使用另一个学习率
rest_params = filter(lambda x:id(x) not in conv_params+list(map(id,prelu_params)),model.parameters())  #提取出剩下的参数
print(list(rest_params))
'''
>> []   #是空的,因为我举的例子没其他参数了
'''
import torch.optim as optim

# 不同部分设置不同的学习率
 
optimizer = optim.Adam([{'params':model.conv1.parameters(),'lr':0.2},
                        {'params':model.conv2.parameters(),'lr':0.2},
                        {'params':prelu_params,'lr':0.02},
                        {'params':rest_params,'lr':0.3}
])

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值