pytorch——冻结某层参数

参考链接:

https://blog.csdn.net/qq_41368074/article/details/107860126

https://blog.csdn.net/Code_Mart/article/details/88254444

首先,我们知道,深度学习网络中的参数是通过计算梯度,在反向传播进行更新的,从而能得到一个优秀的参数,但是有的时候,我们想固定其中的某些层的参数不参与反向传播。比如说,进行微调时,我们想固定已经加载预训练模型的参数部分,指向更新最后一层的分类器,这时应该怎么做呢。

方法一

首先我们的模型定义为:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d()
        self.conv2 = nn.Conv2d()
        self.fc1 = nn.Squential(
                                 nn.Linear(),
                                 nn.Linear(),
                                 ReLU(inplace=True),
                                )
        self.classifier = nn.Linear()

我们通过设置参数param的requires_grad属性为False,来冻结该层参数。我们可以定义如下函数:

def freeze(layer):
    for child in layer.children():
        for param in child.parameters():
            param.requires_grad = False

这里的layer,即为我们需要冻结的某层。如果我们要冻结fc1层,则: 

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d()
        self.conv2 = nn.Conv2d()
        self.fc1 = nn.Squential(
                                 nn.Linear(),
                                 nn.Linear(),
                                 ReLU(inplace=True),
                                )
        freeze(self.fc1)#########
        self.classifier = nn.Linear()

 

当然这样还不够,我们要在定义优化器的时候,告诉优化器,哪些需要更新,那些不需要,这一步至关重要,即:

optimizer.SGD(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-5)

感兴趣的同学可以查看filter函数的作用:https://www.runoob.com/python/python-func-filter.html

有的同学表示,我大部分层需要冻结,只有少部分层要训练,那这样一层一层的稍显麻烦,我们应该怎么做呢,还拿上面的模型举例,假设我的模型是按序定义的,则我只想训练classifier层,其余的统统冻结那么:

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d()
        self.conv2 = nn.Conv2d()
        self.fc1 = nn.Squential(
                                 nn.Linear(),
                                 nn.Linear(),
                                 ReLU(inplace=True),
                                )
 
        for param in self.parameters():
            param.requires_grad = False
        #这样for循环之前的参数都被冻结,其后的正常更新。
        self.classifier = nn.Linear()

 方法二

加载完 Pre-Trained model后,我们需要对其进行 Finetune。但是在此之前,我们往往需要冻结一部分的模型参数:

# 第一种方式
for p in freeze.parameters(): # 将需要冻结的参数的 requires_grad 设置为 False
	p.requires_grad = False
for p in no_freeze.parameters(): # 将fine-tuning 的参数的 requires_grad 设置为 True
	p.requires_grad = True
optimizer.SGD(filter(lambda p: p.requires_grad, model.parameters()), lr=1e-3) # 将需要 fine-tuning 的参数放入optimizer 中

# 第二种方式
optim_param = []
for p in freeze.parameters(): # 将需要冻结的参数的 requires_grad 设置为 False
	p.requires_grad = False
for p in no_freeze.parameters(): # 将fine-tuning 的参数的 requires_grad 设置为 True
	p.requires_grad = True
	optim_param.append(p)
optimizer.SGD(optim_param, lr=1e-3) # 将需要 fine-tuning 的参数放入optimizer 中

 

你可能感兴趣的:(Pytorch)