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

冻结训练的作用:当我们已有部分预训练权重,这部分预训练权重所应用的那部分网络是通用的,如骨干网络,那么我们可以先冻结这部分权重的训练,将更多的资源放在训练后面部分的网络参数,这样使得时间和资源利用都能得到很大改善。然后后面的网络参数训练一段时间之后再解冻这些被冻结的部分,这时再全部一起训练。
1、冻结层不参与训练方法:

######### 模型定义 #########
class MyModel(nn.Module):
    def __init__(self, feat_dim):   # input the dim of output fea-map of Resnet:
        super(MyModel, self).__init__()
        
        BackBone = models.resnet50(pretrained=True)
        
        add_block = []
        add_block += [nn.Linear(2048, 512)]
        add_block += [nn.LeakyReLU(inplace=True)]
        add_block = nn.Sequential(*add_block)
        add_block.apply(weights_init_xavier)
 
        self.BackBone = BackBone
        self.add_block = add_block
 
 
    def forward(self, input):   # input is 2048!
 
        x = self.BackBone(input)
        x = self.add_block(x)
 
        return x
##############################
# 模型准备
model = MyModel()
 
# 优化、正则项、权重设置与冻结层
 
for param in model.parameters():
    param.requires_grad = False
for param in model.add_block.parameters():
    param.requires_grad = True
 
optimizer = optim.SGD(
            filter(lambda p: p.requires_grad, model.parameters()),  # 记住一定要加上filter(),不然会报错。 filter用法:https://www.runoob.com/python/python-func-filter.html
            lr=0.01,
            weight_decay=1e-5, momentum=0.9, nesterov=True)


2、各层采用不同学习率方法

######### 模型定义 #########
class MyModel(nn.Module):
    def __init__(self, feat_dim):   # input the dim of output fea-map of Resnet:
        super(MyModel, self).__init__()
        
        BackBone = models.resnet50(pretrained=True)
        
        add_block = []
        add_block += [nn.Linear(2048, 512)]
        add_block += [nn.LeakyReLU(inplace=True)]
        add_block = nn.Sequential(*add_block)
        add_block.apply(weights_init_xavier)
 
        self.BackBone = BackBone
        self.add_block = add_block
 
 
    def forward(self, input):   # input is 2048!
 
        x = self.BackBone(input)
        x = self.add_block(x)
 
        return x
##############################
 
# 模型准备
model = MyModel()
 
# 不同层学习率设置
 
ignored_params = list(map(id, model.add_block.parameters()))
base_params = filter(lambda p: id(p) not in ignored_params, model.parameters())
 
optimizer = optim.SGD(
             [
                {'params': base_params, 'lr': 0.01},
                {'params': model.add_block.parameters(), 'lr': 0.1},
                ]
            weight_decay=1e-5, momentum=0.9, nesterov=True)


3、调整学习率衰减。

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

####################
#  model structure
#-------------------
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)
 
 
####################
#**  Set lr_decay  **
#-------------------
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 structure
#-------------------
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.03}],  
    weight_decay=1e-3, momentum=0.9, nesterov=True)
 
 
####################
#**  Set lr_decay  **
#-------------------
 
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
    ....

4..lambda表达式,又称匿名函数

作用:函数速写

语法:lambda arg : expression,解释:冒号前是参数,冒号后是返回值。

例子:

>>x=range(10)
>>lambda x:x%2==1

5.filter函数

参数:一个函数func和一个列表list

func的作用:对list的每个元素进行判断,符合条件返回true,否则返回false

filter根据判断结果自动过滤掉不符合条件的元素,并返回有符合元素组成的新列表

举例:

>>x=range(10)
>>filter(lambda x:x%2==1,x)

[1, 3, 5, 7, 9]

6.例如,0-49 Epoch:冻结 backbone进行训练;50-99:不冻结训练。

Init_Epoch = 0
Freeze_Epoch = 50
Unfreeze_Epoch =100
#------------------------------------#
#   冻结一定部分训练
#------------------------------------#  
for param in model.backbone.parameters():
    param.requires_grad = False
for epoch in range(Init_Epoch,Freeze_Epoch):    
    # I`m Freeze-training !!
    pass

#------------------------------------#
#   解冻后训练
#------------------------------------#
for param in model.backbone.parameters():
    param.requires_grad = True
for epoch in range(Freeze_Epoch,Unfreeze_Epoch):
    # I`m unfreeze-training !!
    pass 


参考:

https://blog.csdn.net/qq_36758461/article/details/112852050

[ pytorch ] 基本使用丨3. finetune冻结层操作 + 学习率超参数设置丨_它的专栏-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值