博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PyTorch保存模型与加载模型+Finetune预训练模型使用
阅读量:7102 次
发布时间:2019-06-28

本文共 2767 字,大约阅读时间需要 9 分钟。

参数初始化参

数的初始化其实就是对参数赋值。而我们需要学习的参数其实都是Variable,它其实是对Tensor的封装,同时提供了data,grad等借口,这就意味着我们可以直接对这些参数进行操作赋值了。这就是PyTorch简洁高效所在。所以我们可以进行如下操作进行初始化,当然其实有其他的方法,但是这种方法是PyTorch作者所推崇的:

def weight_init(m):# 使用isinstance来判断m属于什么类型    if isinstance(m, nn.Conv2d):        n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels        m.weight.data.normal_(0, math.sqrt(2. / n))    elif isinstance(m, nn.BatchNorm2d):# m中的weight,bias其实都是Variable,为了能学习参数以及后向传播        m.weight.data.fill_(1)        m.bias.data.zero_()

Finetune

往往在加载了预训练模型的参数之后,我们需要finetune模型,可以使用不同的方式finetune。

局部微调:有时候我们加载了训练模型后,只想调节最后的几层,其他层不训练。其实不训练也就意味着不进行梯度计算,PyTorch中提供的requires_grad使得对训练的控制变得非常简单。
model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():
    param.requires_grad = False
# 替换最后的全连接层, 改为训练100类
# 新构造的模块的参数默认requires_grad为True
model.fc = nn.Linear(512, 100)
# 只优化最后的分类层
optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)
全局微调:有时候我们需要对全局都进行finetune,只不过我们希望改换过的层和其他层的学习速率不一样,这时候我们可以把其他层和新层在optimizer中单独赋予不同的学习速率。比如:
ignored_params = list(map(id, model.fc.parameters()))
base_params = filter(lambda p: id(p) not in ignored_params,
                     model.parameters())
optimizer = torch.optim.SGD([
            {'params': base_params},
            {'params': model.fc.parameters(), 'lr': 1e-3}
            ], lr=1e-2, momentum=0.9)
其中base_params使用1e-3来训练,model.fc.parameters使用1e-2来训练,momentum是二者共有的。

加载部分预训练模型:其实大多数时候我们需要根据我们的任务调节我们的模型,所以很难保证模型和公开的模型完全一样,但是预训练模型的参数确实有助于提高训练的准确率,为了结合二者的优点,就需要我们加载部分预训练模型。

pretrained_dict = model_zoo.load_url(model_urls['resnet152']) model_dict = model.state_dict() # 将pretrained_dict里不属于model_dict的键剔除掉 pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict} # 更新现有的model_dict model_dict.update(pretrained_dict) # 加载我们真正需要的state_dict model.load_state_dict(model_dict)

如果模型的key值和在大数据集上训练时的key值是一样的

我们可以通过下列算法进行读取模型
    model_dict = model.state_dict()
    pretrained_dict = torch.load(model_path)
 # 1. filter out unnecessary keys
    diff = {k: v for k, v in model_dict.items() if \
            k in pretrained_dict and pretrained_dict[k].size() == v.size()}
    pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict and model_dict[k].size() == v.size()}
    pretrained_dict.update(diff)
    # 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)
如果模型的key值和在大数据集上训练时的key值是不一样的,但是顺序是一样的
    model_dict = model.state_dict()
    pretrained_dict = torch.load(model_path)
    keys = []
    for k,v in pretrained_dict.items():
        keys.append(k)
    i = 0
    for k,v in model_dict.items():
        if v.size() == pretrained_dict[keys[i]].size():
            print(k, ',', keys[i])
            model_dict[k]=pretrained_dict[keys[i]]
        i = i + 1
    model.load_state_dict(model_dict)
如果模型的key值和在大数据集上训练时的key值是不一样的,但是顺序是也不一样的
自己找对应关系,一个key对应一个key的赋值

转载地址:http://txkhl.baihongyu.com/

你可能感兴趣的文章
python实训第四天
查看>>
5-4-3原则
查看>>
html图像入门
查看>>
C# Mongo Client 2.4.2创建索引
查看>>
我的第四个网页制作:列表标签
查看>>
【python进阶】详解元类及其应用2
查看>>
简单实用的菜单栏
查看>>
AMap行政区查询服务
查看>>
SpringBoot2.0源码分析(一):SpringBoot简单分析
查看>>
nginx一台服务器布置多个网站
查看>>
自定义String
查看>>
JAVA入门到精通-第25讲-泛型.异常
查看>>
15.回撤操作
查看>>
java 主流框架
查看>>
简单的增删改查
查看>>
iptables详解(8):iptables扩展模块之state扩展
查看>>
解决火狐访问(localhost)本地网站提示输入用户名密码
查看>>
ubuntu14.0.4.3 devstack 安装openstack
查看>>
String隐式共享
查看>>
[转载]Windows Phone
查看>>