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 中