迁移学习我们经常会用到,无论是CV还是NLP任务。
在pytorch中主要通过如下方式进行:
方式一:
1)首先冻结不需要进行梯度更新曾的参数(减少计算):
class Net(nn.Module):
def __init__(self, model, pretrained):
super(self, Net).__init__()
self.resnet = model(pretrained)
for p in self.parameters():
p.requires_grad = False # 冻结不需要训练的参数
self.liner = nn.Linear(...) # optimizer中需要训练的层
...
2) 定义优化器传入需要训练的参数,同时过滤到第一步中requires_grad = false的参数:filter(lambda p: p.requires_grad, model.parameters())
optimizer = optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), lr=0.001, ...)
方式二:
直接传入需要训练层的参数
optimizer = optim.Adam(param, lr=0.01,...)
这种方式没有冻结不参与训练的参数,尽管这部分参数没有传入优化器,理论上虽然会计算梯度,但是不会进行更新。相比于requires_grad=False 会增加计算量。
方式三:
以VGG为例:
1)冻结不训练的参数
for param in vgg.features.parameters():
param.requeires_grad=False
2)只传入训练层的参数:
optimizer=optim.SGD(vgg.classifier.paramters(),lr=0.001)
这种方式,不仅减少了计算量,也同样可以进行正确的迁移学习。