当保存和加载模型时,需要熟悉三个核心功能:
- torch.save :将序列化对象保存到磁盘。此函数使用Python的pickle 模块进行序列化。使用此函数可以保存如模型、tensor、字典等各种对象。
- torch.load :使用pickle的unpickling 功能将pickle对象文件反序列化到内存。此功能还可以有助于设备加载数据。
- torch.nn.Module.load_state_dict :使用反序列化函数 state_dict 来加载模型的参数字典。
状态字典:state_dict
# 定义模型
class TheModelClass(nn.Module):
def __init__(self):
super(TheModelClass, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
# 初始化模型
model = TheModelClass()
# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
# 打印模型的状态字典
print("Model's state_dict:")
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
# 打印优化器的状态字典
print("Optimizer's state_dict:")
for var_name in optimizer.state_dict():
print(var_name, "\t", optimizer.state_dict()[var_name])
*输出
Model's state_dict:
conv1.weight torch.Size([6, 3, 5, 5])
conv1.bias torch.Size([6])
conv2.weight torch.Size([16, 6, 5, 5])
conv2.bias torch.Size([16])
fc1.weight torch.Size([120, 400])
fc1.bias torch.Size([120])
fc2.weight torch.Size([84, 120])
fc2.bias torch.Size([84])
fc3.weight torch.Size([10, 84])
fc3.bias torch.Size([10])
Optimizer's state_dict:
state {}
param_groups [{'lr': 0.001, 'momentum': 0.9, 'dampening': 0, 'weight_decay':
0, 'nesterov': False, 'params': [4675713712, 4675713784, 4675714000, 4675714072,
4675714216, 4675714288, 4675714432, 4675714504, 4675714648, 4675714720]}]
保存和加载推理模型
保存/加载state_dict
- 保存
torch.save(model.state_dict(), PATH)
- 加载
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
model.eval()
在运行推理之前,务必调用model.eval() 去设置 dropout 和 batch normalization 层为评估模式。如果不这么做,可能导致 模型推断结果不一致。
保存和加载 Checkpoint 用于推理/继续训练
- 保存
torch.save({
'epoch': epoch,
'model_state_dict': model.state_dict(),
'optimizer_state_dict': optimizer.state_dict(),
'loss': loss,
...
}, PATH)
- 加载
model = TheModelClass(*args, **kwargs)
optimizer = TheOptimizerClass(*args, **kwargs)
checkpoint = torch.load(PATH)
model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']
model.eval()
# - or -
model.train()
当保存成 Checkpoint 的时候,可用于推理或者是继续训练,保存的不仅仅是模型的 state_dict。保存优化器的 state_dict 也很重要, 因为它包含作为模型训练更新的缓冲区和参数。
请记住在运行推理之前,务必调用model.eval() 去设置 dropout 和 batch normalization 为评估。如果不这样做,有可能得到不一致的推断结果。 如果你想要恢复训练,请调用model.train() 以确保这些层处于训练模式。