到目前為止,我們討論了如何處理數據以及如何構建、訓練和測試深度學習模型。然而,在某些時候,我們希望對學習的模型感到滿意,我們希望保存結果以供以后在各種情況下使用(甚至可能在部署中進行預測)。此外,在運行較長的訓練過程時,最佳做法是定期保存中間結果(檢查點),以確保如果我們被服務器的電源線絆倒,我們不會損失幾天的計算量。因此,是時候學習如何加載和存儲單個權重向量和整個模型了。本節解決這兩個問題。
import torch
from torch import nn
from torch.nn import functional as F
import flax
import jax
from flax import linen as nn
from flax.training import checkpoints
from jax import numpy as jnp
from d2l import jax as d2l
import numpy as np
import tensorflow as tf
6.6.1. 加載和保存張量
對于單個張量,我們可以直接調用load
和save
函數分別進行讀寫。這兩個函數都需要我們提供一個名稱,并且save
需要將要保存的變量作為輸入。
我們現在可以將存儲文件中的數據讀回內存。
tensor([0, 1, 2, 3])
x2 = jnp.load('x-file.npy', allow_pickle=True)
x2
Array([0, 1, 2, 3], dtype=int32)
我們可以存儲張量列表并將它們讀回內存。
y = torch.zeros(4)
torch.save([x, y],'x-files')
x2, y2 = torch.load('x-files')
(x2, y2)
(tensor([0, 1, 2, 3]), tensor([0., 0., 0., 0.]))
(array([0., 1., 2., 3.]), array([0., 0., 0., 0.]))
(Array([0., 1., 2., 3.], dtype=float32),
Array([0., 0., 0., 0.], dtype=float32))
我們甚至可以編寫和讀取從字符串映射到張量的字典。當我們想要讀取或寫入模型中的所有權重時,這很方便。
{'x': tensor([0, 1, 2, 3]), 'y': tensor([0., 0., 0., 0.])}
{'x': array([0., 1., 2., 3.]), 'y': array([0., 0., 0., 0.])}
array({'x': Array([0, 1, 2, 3], dtype=int32), 'y': Array([0., 0., 0., 0.], dtype=float32)},
dtype=object)
array({'x': <tf.Tensor: shape=(4,), dtype=int32, numpy=array([0, 1, 2, 3], dtype=int32)>, 'y': <tf.Tensor: shape=(4,), dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>},
dtype=object)
6.6.2. 加載和保存模型參數
保存單個權重向量(或其他張量)很有用,但如果我們想保存(并稍后加載)整個模型,它會變得非常乏味。畢竟,我們可能散布著數百個參數組。出于這個原因,深度學習框架提供了內置功能來加載和保存整個網絡。需要注意的一個重要細節是,這會保存模型參數而不是整個模型。例如,如果我們有一個 3 層的 MLP,我們需要單獨指定架構。這樣做的原因是模型本身可以包含任意代碼,因此它們不能自然地序列化。因此,為了恢復模型,我們需要用代碼生成架構,然后從磁盤加載參數。讓我們從我們熟悉的 MLP 開始。
class MLP(nn.Module):
def __init__(self):
super().__init__()
self.hidden = nn.LazyLinear(256)
self.output = nn.LazyLinear(10)
def forward(self, x):
return self.output(F.relu(self.hidden(x)))
net = MLP()
X = torch.randn(size=(2, 20))
Y = net(X)
評論
查看更多