详解pytorch冻结模型部分层的参数

问题一:固定模型参数的方法

for para in model.parameters():
    para.requires_grad = Flase
optimizer = optim.Adam(filter(lambda p: p.requires_grad, net.parameters()), lr=0.1)

问题二:requires_grad==False的参数是否要加入optimizer

结论:加不加output的结果都一样。使用filter过滤一下的好处是防止后面犯一些意想不到的错误。后面要是想重新加上,可以使optimizer.add_param_group() 把需要加的参数加到param_groups里面(见下例),这个时候,optimizerparam_groups的长度就增加了1,param_groups是一个列表,里面的每个元素都是字典,每个字典有关键字'params''lr'等等。

问题三:开始固定,后来又解冻的那些参数,他们的学习率如何变化

结论:这个要分情况讨论

情况一:requires_grad==False的参数是也加入optimizer,这种情况下,这些参数一直都在optimizer中,他的学习率随着他所在的那个para_group变化而变化。这个可以用optimizer.para_groups[索引(比如0)]['lr']查看,

情况二:requires_grad==Falseoptimizer创建中被过滤掉,后面需要使用的时候,再使用optimizer.add_param_group()加上去,从这个add就可以看出来,他是在原来的optimizer.para_groups的后面append上去的,因此,这个是新加进optimizer上的,使用scheduler.step的时候,新加进去的这些参数的是从optimizer创建时候的初始学习率开始的。

举个例子:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()

        self.fc1 = nn.Linear(5, 3)
        self.fc2 = nn.Linear(3, 1)
    def forward(self, x):
        x = self.fc1(x)
        x = self.fc2(x)
        return x

net = Net()
random_input = Variable(torch.randn(5, ))
random_target = Variable(torch.randn(1, ))

net.fc2.weight.requires_grad = False
net.fc2.bias.requires_grad = False
optimizer = optim.Adam(filter(lambda p: p.requires_grad, net.parameters()), lr=0.1)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=2, gamma=0.1,last_epoch=-1)

for i in range(4):
    optimizer.zero_grad()
    output = net(random_input)
    loss = criterion(output, random_target)
    loss.backward()
    optimizer.step()
    scheduler.step()

net.fc2.weight.requires_grad = True
net.fc2.bias.requires_grad = True
optimizer.add_param_group({'params': net.fc2.parameters()})

for i in range(4):
    optimizer.zero_grad()
    output = net(random_input)
    loss = criterion(output, random_target)
    loss.backward()
    optimizer.step()
    scheduler.step()
  1. 创建好后:optimizerparam_groups的长度为1,只有索引0,里面的param对应的参数并没有fc2.
  2. 第一次的四个epoch:此时optimizer的参数的学习率每隔2个epoch变成原来的0.1,所以依次为0.1 -> 0.1 -> 0.01 -> 0.01
  3. fc2的requires_grad设置为True,并add进optimizer:optimizer的param_groups的长度为2,索引1对应的字典,里面的param对应的参数是fc2,此时查看optimizer.param_groups,发现,param_groups[0]里面新增了一个键值对'initial_lr': 0.1,并且'lr':0.001,param_groups[1]是对应的是刚才新增的fc2,里面的'lr':0.1,没有键'initial_lr'
  4. 第二次的四个epoch:此时optimizer的参数的学习率每隔2个epoch变成原来的0.1(注意此时param_groups两组的学习率是不相等的)。所以param_groups[0]的就是0.001 -> 0.001 -> 0.0001 -> 0.0001param_groups[1]的是0.1 -> 0.1 -> 0.01 -> 0.01
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一米七八_FZH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值