Pytorch 模型fusion

模型A和模型B,两个模型共享backbone,现需要将两模型共享backbone参数

backbone为resnet18

 

步骤:

1.训练单独的A模型

2.load第一步的模型,将backbone中的某些层之前lr调小,之后的lr不变,训练B模型

3.load第二步的模型,训练A模型,同时需要固定第二步中某些层的参数

 

trick:

1.第2、3步load模型的时候,会有一些参数不需要,需要把这些参数保存下来,再后面finetune的时候会用到。本次使用的方法是在load_state的时候,用一个OrderedDict存下来没有用的参数,save_checkpoint的时候保存

2.需要在config的时候设置一个flag,用于区别是第一次训练,还是用别的模型finetune

3.第二步训练的时候,是选取节点,将节点前的lr调小,后面的lr正常,去训练;而第三步需要选取节点,将节点前的层fix住,后面的层训练,根据结果是,第三步训练时候,lr越大越好;另外根据resnet18,从layer3开始finetune效果比较好

4.在第二步,fix的层比未fix的层,lr为1/5的关系时效果最好

 

bn层的坑:

在model中,用:

    for p in self.parameters():

            p.requires_grad = False

然后在main函数里,optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, model.parameters), momentum=args.momentum, weight_decay=args.weight_decay)

如果是想微调一些层,而后面层lr不变,可以写为:

conv_params = list(map(id, model.layer1.parameters()))

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

params = [{“params”: model.layer1.parameters(), “lr”: 0.01},

                 {“params”: base_params, “lr”: args.lr},]

optimizer = torch.optim.Adam(params, weight_decay=args.weight_decay)

 

但是fix的时候,bn里面的参数running_var和running_mean是变的,这两个参数不是学习出来的,而是在train的时候计算出来的,用于inference。而这两个参数是不经过optimizer的,并且不需要梯度回传,于是一开始没有发现这个问题,后来发现就算是梯度固定住,这两个参数还是会更新,只需要将model设置为eval()

这个时候需要将需要fix的bn层,设置为m.eval()

 

你可能感兴趣的:(深度学习,pytorch)