https://zh.d2l.ai/chapter_deep-learning-computation/read-write.html
model = nn.Sequential(nn.Linear(10,100), nn.ReLU(), nn.Linear(100,10))
torch.save(model, 'model.pt')
m = torch.load('model.pt')
从上面的代码运行发现,pytorch可以直接保存网络结构和参数,不知道有什么限制没有。
https://pytorch.org/tutorials/beginner/saving_loading_models.html
torch.save(): “The disadvantage of this approach is that the serialized data is bound to the specific classes and the exact directory structure used when the model is saved.”
当网络结构发生改变的时候,用torch.save()保存的模型,在load的时候相比于state_dict会遇到一些麻烦,你可以自己试一下。
请问clone.eval()是做什么的呀
我发现采用sequential定义的网络,可以采用net[0]这种方式访问和保存单层的参数。但是像这一节最后实现的MLP里面这样直接在__init__里写的话,是不行的。不知道这样写的话,如何保存单层的参数呢。
temp = {'hidden.weight':net.state_dict()['hidden.weight'],'hidden.bias':net.state_dict()['hidden.bias']}
torch.save(temp,'hidden.params')
state_dict()返回的是有序字典,可以通过字典的键值访问想要的参数。
clone_hidden.load_state_dict(torch.load('hidden.params'),strict=False)
利用load_state_dict()从保存到文件加载参数时可能会遇到字典不匹配的问题,可以加上strict=False,参考官方文档
这样应该是不能保存一层的参数的,需要使用Sequential或者ModuleList来注册网络
用来让模型“准备好”,以便下面的语句接收测试数据。
你第一行的字典键值的命名似乎有点问题,执行
clone_hidden.load_state_dict(torch.load(‘hidden.params’),strict=False)
会报错
_IncompatibleKeys(missing_keys=[‘weight’, ‘bias’], unexpected_keys=[‘hidden.weight’, ‘hidden.bias’])
改成
temp = {‘weight’:net.state_dict()[‘hidden.weight’],‘bias’:net.state_dict()[‘hidden.bias’]}
就没有问题了,确实实现了隐藏层weight和bias的参数复制
从train模式调整为test模式,不再进行训练更改梯度
这样写应该行
torch.save(net.hidden.state_dict(), 'mlp.hidden.params')
clone = MLP()
clone.hidden.load_state_dict(torch.load('mlp.hidden.params'))
Q1: 即使不需要将经过训练的模型部署到不同的设备上,存储模型参数还有什么实际的好处?
A1: 可用于在训练模型过程中生成checkout文件(存储模型参数),必要时可以go back,方便后续梯度下降时找到局部最优点。
Q2: 假设我们只想复用网络的一部分,以将其合并到不同的网络架构中。比如说,如果你想在一个新的网络中使用之前网络的前两层,你该怎么做?
A2: 使用保存模型某层参数的办法,保存网络的前两层,然后再加载到新的网络中使用。
# 如何保存和加载模型的某层参数
torch.save(net.hidden.state_dict(), 'mlp.hidden.params')
clone = MLP()
clone.hidden.load_state_dict(torch.load('mlp.hidden.params'))
print(clone.hidden.weight == net.hidden.weight)
Q3: 如何同时保存网络架构和参数?你会对架构加上什么限制?
A3: pytorch本身提供同时保存网络架构和参数的方法
model = nn.Sequential(nn.Linear(20, 256), nn.ReLU(), nn.Linear(256, 10))
torch.save(model, 'model.pt')
m = torch.load('model.pt')
print(m)
如果你是用类实现的网络结构,那么你在别的文件里load的时候需要重新实现一下类,否则load不了,找不到那个类
Q2:
# 保存参数模型
torch.save(net.state_dict(), 'mlp.params')
# 读取参数文件
clone = MLP()
params = torch.load('mlp.params')
required_para = ['hidden.weight', 'output.bias']
pretrained_dict = {k: v for k, v in params.items() if k in required_para}
# print(pretrained_dict)
clone.load_state_dict(pretrained_dict, strict=False)
print(clone)
# clone.eval() # Sets the module in evaluation mode.
test和validation的时候开,关闭梯度计算和优化参数,只调用forward
设置为评估模式,保持参数不变,不会更新参数
自己可以定义一下__getitem__方法,因为Module没定义,所以MLP也不会继承,你可以Ctrl+B跳到Module搜这个函数,再去Sequential去看这个函数,前者没,后者有,这个函数就是操作符,你可以定义这个函数去实现如何返回子Module。