模型讀取和存儲
總結下來,就是幾個函數
- torch.load()/torch.save()
通過python的pickle完成序列化與反序列化.完成內存<-->磁盤轉換.
- Module.state_dict()/Module.load_state_dict()
state_dict()獲取模型參數.load_state_dict()加載模型參數
讀寫Tensor
我們可以直接使用save
函數和load
函數分別存儲和讀取Tensor
。save
使用Python的pickle實用程序將對象進行序列化,然后將序列化的對象保存到disk,使用save
可以保存各種對象,包括模型、張量和字典等。而laod
使用pickle unpickle工具將pickle的對象文件反序列化為內存。
下面的例子創建了Tensor
變量x
,並將其存在文件名同為x.pt
的文件里。
import torch
from torch import nn
x = torch.ones(3)
torch.save(x, 'x.pt')
然后我們將數據從存儲的文件讀回內存。
x2 = torch.load('x.pt')
x2
輸出:
tensor([1., 1., 1.])
我們還可以存儲一個Tensor
列表並讀回內存。
y = torch.zeros(4)
torch.save([x, y], 'xy.pt')
xy_list = torch.load('xy.pt')
xy_list
輸出:
[tensor([1., 1., 1.]), tensor([0., 0., 0., 0.])]
存儲並讀取一個從字符串映射到Tensor
的字典。
torch.save({'x': x, 'y': y}, 'xy_dict.pt')
xy = torch.load('xy_dict.pt')
xy
輸出:
{'x': tensor([1., 1., 1.]), 'y': tensor([0., 0., 0., 0.])}
state_dict
在PyTorch中,Module
的可學習參數(即權重和偏差),模塊模型包含在參數中(通過model.parameters()
訪問)。state_dict
是一個從參數名稱隱射到參數Tesnor
的字典對象。
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.hidden = nn.Linear(3, 2)
self.act = nn.ReLU()
self.output = nn.Linear(2, 1)
def forward(self, x):
a = self.act(self.hidden(x))
return self.output(a)
net = MLP()
net.state_dict()
輸出:
OrderedDict([('hidden.weight', tensor([[ 0.2448, 0.1856, -0.5678],
[ 0.2030, -0.2073, -0.0104]])),
('hidden.bias', tensor([-0.3117, -0.4232])),
('output.weight', tensor([[-0.4556, 0.4084]])),
('output.bias', tensor([-0.3573]))])
注意,只有具有可學習參數的層(卷積層、線性層等)才有state_dict
中的條目優化器(optim
)也有一個state_dict
,其中包含關於優化器狀態以及所使用的超參數的信息。
optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
optimizer.state_dict()
輸出:
{'state': {}, 'param_groups': [{'lr': 0.001, 'momentum': 0.9, 'dampening': 0, 'weight_decay': 0, 'nesterov': False, 'params': [139952370292992, 139952370293784, 139952370294144, 139952370293496]}]}
保存和加載模型
PyTorch中保存和加載訓練模型有兩種常見的方法:
- 僅保存和加載模型參數(
state_dict
) - 保存和加載整個模型
保存和加載state_dict
(推薦方式)
保存:
torch.save(model.state_dict(), PATH) # 推薦的文件后綴名是pt或pth
加載:
model = TheModelClass(*args, **kwargs)
model.load_state_dict(torch.load(PATH))
保存和加載整個模型
保存:
torch.save(model, PATH)
加載:
model = torch.load(PATH)
我們采用推薦的方法一來實驗一下:
X = torch.randn(2, 3)
Y = net(X)
PATH = "./net.pt"
torch.save(net.state_dict(), PATH)
net2 = MLP()
net2.load_state_dict(torch.load(PATH))
Y2 = net2(X)
Y2 == Y
輸出:
tensor([[1],
[1]], dtype=torch.uint8)
因為這net
和net2
都有同樣的模型參數,那么對同一個輸入X
的計算結果將會是一樣的。上面的輸出也驗證了這一點。
此外,還有一些其他使用場景,例如GPU與CPU之間的模型保存與讀取、使用多塊GPU的模型的存儲等等,使用的時候可以參考官方文檔。