您的位置:首页 > 理论基础 > 计算机网络

PyTorch中使用预训练的模型初始化网络的一部分参数

2018-01-15 20:50 1491 查看
在预训练网络的基础上,修改部分层得到自己的网络,通常我们需要解决的问题包括:

1. 从预训练的模型加载参数

2. 对新网络两部分设置不同的学习率,主要训练自己添加的层

一. 加载参数的方法:

加载参数可以参考apaszke推荐的做法,即删除与当前model不匹配的key。代码片段为:

model = ...
model_dict = model.state_dict()

# 1. filter out unnecessary keys
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}
# 2. overwrite entries in the existing state dict
model_dict.update(pretrained_dict)
# 3. load the new state dict
model.load_state_dict(model_dict)


二. 不同层设置不同学习率的方法

此部分主要参考PyTorch教程的Autograd machnics部分

2.1 在PyTorch中,每个Variable数据含有两个flag(requires_grad和volatile)用于指示是否计算此Variable的梯度。设置requires_grad = False,或者设置volatile=True,即可指示不计算此Variable的梯度:

for param in model.parameters():
param.requires_grad = False


注意,在模型测试时,对input_data设置volatile=True,可以节省测试时的显存

2.2 PyTorch的Module.modules()和Module.children()

参考PyTorch document和discuss

在PyTorch中,所有的neural network module都是class torch.nn.Module的子类,在Modules中可以包含其它的Modules,以一种树状结构进行嵌套。当需要返回神经网络中的各个模块时,Module.modules()方法返回网络中所有模块的一个iterator,而Module.children()方法返回所有直接子模块的一个iterator。具体而言:

list(nn.Sequential(nn.Linear(10, 20), nn.ReLU()).modules())
Out[9]:
[Sequential (
(0): Linear (10 -> 20)
(1): ReLU ()
), Linear (10 -> 20), ReLU ()]

In [10]: list(nn.Sequential(nn.Linear(10, 20), nn.ReLU()).children())
Out[10]: [Linear (10 -> 20), ReLU ()]


2.3 选择特定的层进行finetune

先使用Module.children()方法查看网络的直接子模块,将不需要调整的模块中的参数设置为param.requires_grad = False,同时用一个list收集需要调整的模块中的参数。具体代码为:

count = 0
para_optim = []
for k in model.children():
count += 1
# 6 should be changed properly
if count > 6:
for param in k.parameters():
para_optim.append(param)
else:
for param in k.parameters():
param.requires_grad = False
optimizer = optim.RMSprop(para_optim, lr)


到此我们实现了PyTorch中使用预训练的模型初始化网络的一部分参数,参考代码见我的GitHub
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: