pytorch 冻结层操作 + 学习率超参数设置

torch finetune冻结层操作

这个做了简单的实验:

神经网络冻结层,固定参数_AI视觉网奇的博客-CSDN博客

知乎文章:pytorch 两种冻结层的方式 - 知乎

文章说了两种冻结层的方法:

一、设置requires_grad为False

第一步:

for param in model.named_parameters():
    if param[0] in need_frozen_list:
        param[1].requires_grad = False

这种方法需要注意的是层名一定要和model中一致,model经过.cuda后往往所用层会添加module.的前缀,会导致后面的冻结无效。

第二步,还需要注意的是加上filter:

optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, model.parameters()), lr=args.lr,momentum=args.momentum, weight_decay=args.weight_decay)

第三步,模型需要设置eval(),train(False)。

二、使用 torch.no_grad()

这种方式只需要在网络定义中的forward方法中,将需要冻结的层放在 torch.no_grad()下,强力推这种方式

class xxnet(nn.Module):
    def __init__():
        ....
        self.layer1 = xx
        self.layer2 = xx
        self.fc = xx

    def forward(self.x):
        with torch.no_grad():
            x = self.layer1(x)
            x = self.layer2(x)
        x = self.fc(x)
        return x

模型也需要设置eval(),train(False)。

这种方式则是将layer1和layer2定义的层冻结,只训练fc层的参数。

我看了一下,层的参数确实冻结了,但是训练过程中,网络预测的结果一直是变的。

经过反复测试,发现是model.train()的原因:

model.train()是保证BN层能够用到每一批数据的均值和方差。对于Dropout,model.train()是随机取一部分网络连接来训练更新参数。

3、调整学习率衰减

方法一:使用torch.optim.lr_scheduler()函数:

model = Mymodel()

if use_gpu:

model = model.cuda()

# loss

criterion = nn.CrossEntropyLoss()

# optimizer

ignored_params = list(map(id, model.ViewModel.viewclassifier.parameters())) + list(map(id, model.Block.parameters()))

base_params = filter(lambda p: id(p) not in ignored_params, model.parameters())

optimizer_ft = optim.SGD([

{'params': base_params, 'lr': 0.01},

{'params': model.ViewModel.viewclassifier.parameters(), 'lr': 0.001},

{'params': model.Block.parameters(), 'lr': 0.01}

], weight_decay=1e-3, momentum=0.9, nesterov=True)



exp_lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=60, gamma=0.1)


scheduler.step() # put it before model.train(True)

model.train(True) # Set model to training mode


....

方法二:使用optimizer.param_groups方法。(好处:能分别设定不同层的衰减率!)


model = Mymodel()

if use_gpu:

model = model.cuda()

criterion = nn.CrossEntropyLoss()


ignored_params = list(map(id, model.ViewModel.viewclassifier.parameters())) + list(map(id, model.Block.parameters()))

base_params = filter(lambda p: id(p) not in ignored_params, model.parameters())

optimizer_ft = optim.SGD([

{'params': base_params, 'lr': 0.01},

{'params': model.ViewModel.viewclassifier.parameters(), 'lr': 0.001},

{'params': model.Block.parameters(), 'lr': 0.03}],

weight_decay=1e-3, momentum=0.9, nesterov=True)


def adjust_lr(epoch):

    step_size = 60

    lr = args.lr * (0.1 ** (epoch // 30))

    for g in optimizer.param_groups:

        g['lr'] = lr * g.get('lr')


### optimizer.param_groups 类型与内容

[

{ 'params': base_params, 'lr': 0.01, 'momentum': 0.9, 'dampening': 0,

'weight_decay': 0.001, 'nesterov': True, 'initial_lr': 0.01 },

{ 'params': model.ViewModel.viewclassifier.parameters(), 'lr': 0.001,

'momentum': 0.9, 'dampening': 0, 'weight_decay': 0.001, 'nesterov': True,

'initial_lr': 0.001 },

{ 'params': model.Block.parameters(), 'lr': 0.03, 'momentum': 0.9,

'dampening': 0, 'weight_decay': 0.001, 'nesterov': True, 'initial_lr':

0.03 }

]

### optimizer.param_groups 类型与内容


for epoch in range(start_epoch, args.epochs):

adjust_lr(epoch) # 每epoch更新一次。

model.train(True) # Set model to training mode

....

补充知识:python中的字典方法.get()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AI算法网奇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值