PyTorch
张量
张量是一种专门的数据结构,与数组和矩阵非常相似。张量类似于 NumPy 的 ndarrays,但张量可以在 GPU 或其他硬件加速器上运行,张量也针对自动微分进行了优化。
默认情况下,张量是在 CPU 上创建的。我们需要使用 .to 方法将张量显式地移动到 GPU(在检查 GPU 是否可用后)。请记住,跨设备复制大型张量在时间和内存方面可能代价高昂!
将结果存储到操作数中的操作称为就地操作。它们用 后缀表示。例如:x.copy(y)、x.t_() 将会改变 x。
数据加载
PyTorch 提供了两个数据基本类型:torch.utils.data.DataLoader 和 torch.utils.data.Dataset,它们使您可以使用预加载的数据集以及您自己的数据。
神经网络
torch.nn 命名空间提供了构建您自己的神经网络所需的所有构建块。PyTorch 中的每个模块都是 nn.Module 的子类。
自动微分
在训练神经网络时,最常用的算法是 反向传播。在此算法中,参数(模型权重)会根据损失函数相对于给定参数的 梯度 进行调整。
为了计算这些梯度,PyTorch 有一个内置的微分引擎,称为 torch.autograd。它支持任何计算图的梯度自动计算。当我们需要计算损失函数相对于这些变量的梯度,我们设置了这些张量的requiresgrad 属性。可以在创建张量时设置requires_grad的值,或者之后使用x.requires_grad(True)方法。要计算这些导数,我们调用loss.backward(),然后从w.grad和b.grad中检索值。
要阻止一个张量被跟踪历史,可以调用.detach()方法将其与计算历史分离,并阻止它未来的计算记录被跟踪。为了防止跟踪历史记录(和使用内存),可以将代码块包装在 with torch.no_grad(): 中。
优化
在训练循环中,优化分三个步骤进行:
调用optimizer.zero_grad()重置模型参数的梯度。默认情况下,梯度会累加;为了防止重复计数,我们在每次迭代中显式地将其归零。
使用loss.backward()反向传播预测损失。PyTorch 将损失相对于每个参数的梯度存储起来。
在获得梯度后,我们调用optimizer.step()根据反向传播中收集的梯度调整参数。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39def train_loop(dataloader, model, loss_fn, optimizer):
size = len(dataloader.dataset)
# Set the model to training mode - important for batch normalization and dropout layers
# Unnecessary in this situation but added for best practices
model.train()
for batch, (X, y) in enumerate(dataloader):
# Compute prediction and loss
pred = model(X)
loss = loss_fn(pred, y)
# Backpropagation
loss.backward()
optimizer.step()
optimizer.zero_grad()
if batch % 100 == 0:
loss, current = loss.item(), batch * batch_size + len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
def test_loop(dataloader, model, loss_fn):
# Set the model to evaluation mode - important for batch normalization and dropout layers
# Unnecessary in this situation but added for best practices
model.eval()
size = len(dataloader.dataset)
num_batches = len(dataloader)
test_loss, correct = 0, 0
# Evaluating the model with torch.no_grad() ensures that no gradients are computed during test mode
# also serves to reduce unnecessary gradient computations and memory usage for tensors with requires_grad=True
with torch.no_grad():
for X, y in dataloader:
pred = model(X)
test_loss += loss_fn(pred, y).item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= num_batches
correct /= size
print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
保存和加载模型
保存和加载模型权重
PyTorch 模型将学习到的参数存储在内部状态字典中,称为 state_dict。这些可以通过 torch.save 方法持久化。
1 | model = models.vgg16(weights='IMAGENET1K_V1') |
要加载模型权重,您需要首先创建一个相同模型的实例,然后使用 load_state_dict() 方法加载参数。1
2
3model = models.vgg16() # we do not specify ``weights``, i.e. create untrained model
model.load_state_dict(torch.load('model_weights.pth', weights_only=True))
model.eval()
注意请务必在推理之前调用 model.eval() 方法,以将 dropout 和批归一化层设置为评估模式。如果不这样做,将产生不一致的推理结果。
保存和加载具有形状的模型
1 | torch.save(model, 'model.pth') |
参考文献
https://pytorch.ac.cn/tutorials/beginner/basics/tensor_tutorial.html