第一步:保存模型参数
若拥有模型参数,可跳过这一步。
假设创建了一个net = Net(),并且经过训练,通过以下方式保存:
torch.save(net.state_dict(), 'net_params.pkl')
第二步:加载模型
进行三步曲中的第二步,加载模型,这里只是加载模型的参数:
pretrained_dict = torch.load('net_params.pkl')
第三步: 初始化
进行三步曲中的第三步,将取到的权值,对应的放到新模型中:
首先我们创建新模型,并且获取新模型的参数字典net_state_dict:
net = Net() # 创建net
net_state_dict = net.state_dict() # 获取已创建net的state_dict
接着将pretrained_dict里不属于net_state_dict的键剔除掉:
pretrained_dict_1 = {k: v for k, v in pretrained_dict.items() if k in net_state_dict}
然后,用预训练模型的参数字典 对 新模型的参数字典net_state_dict 进行更新:
net_state_dict.update(pretrained_dict_1)
最后,将更新了参数的字典 “放”回到网络中:
net.load_state_dict(net_state_dict)
Code:
ignored_params = list(map(id, net.fc3.parameters())) # 返回的是parameters的 内存地址
base_params = filter(lambda p: id(p) not in ignored_params, net.parameters())
optimizer = optim.SGD([
{'params': base_params},
{'params': net.fc3.parameters(), 'lr': 0.001*10}], 0.001, momentum=0.9, weight_decay=1e-4)
第一行+ 第二行的意思就是,将fc3层的参数net.fc3.parameters()从原始参数net.parameters()中剥离出来
base_params就是剥离了fc3层的参数的其余参数,然后在优化器中为fc3层的参数单独设定学习率。
optimizer = optim.SGD(…)这里的意思就是 base_params中的层,用 0.001, momentum=0.9, weight_decay=1e-4
fc3层设定学习率为: 0.001*10
完整代码位于
PyTorch_Tutorial/2_finetune.py at master · TingsongYu/PyTorch_Tutorial · GitHub
补充:
挑选出特定的层的机制是利用内存地址作为过滤条件,将需要单独设定的那部分参数,从总的参数中剔除。
base_params 是一个list,每个元素是一个Parameter 类
net.fc3.parameters() 是一个
ignored_params = list(map(id, net.fc3.parameters()))
net.fc3.parameters() 是一个<generator object parameters at 0x11b63bf00>
所以迭代的返回其中的parameter,这里有weight 和 bias
最终返回weight和bias所在内存的地址