在使用 PyTorch 进行模型训练时,为什么需要设置训练模式?如何计算每个 epoch 的平均损失?今天,我们来唠一唠。


一、模型的训练模式

在训练神经网络模型时,特别是在使用 PyTorch 框架时,我们通常会看到类似如下的代码:

1
model.train()

这行代码将模型设置为训练模式。这对于一些特定的层,如 Dropout 和 Batch Normalization,尤为重要。让我们深入了解一下原因。

1.1 Dropout 层

Dropout 是一种正则化技术,旨在防止过拟合。在训练过程中,Dropout 会随机地将一部分神经元的输出设为零,从而防止模型对训练数据过拟合。然而,在测试和评估模型时,我们希望使用所有的神经元。因此,Dropout 层在训练和测试时的行为有所不同:

  • 训练模式:随机屏蔽部分神经元。
  • 评估模式:使用所有神经元,不进行屏蔽。

1.2 Batch Normalization 层

Batch Normalization 通过在每个小批次上标准化输入来加速训练和提高稳定性。在训练和测试时,它的行为也不同:

  • 训练模式:使用当前批次的数据计算均值和方差进行标准化。
  • 评估模式:使用在训练过程中积累的全局均值和方差进行标准化。

因此,将模型设置为训练模式(model.train())确保了这些层在训练时表现正确。如果忘记了这一步,可能会导致训练效果不佳或者评估结果不准确。


二、计算每个 epoch 的平均损失

在训练过程中,我们需要跟踪模型的性能,其中一个常用的指标是损失(loss)。损失函数用于衡量模型预测值与实际值之间的误差。在每个 epoch 结束时,计算其平均损失是一个常见做法。以下是计算每个 epoch 平均损失的代码示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def train(model, device, trainloader, criterion, optimizer, num_epochs):
    model.train()
    train_losses = []
    for epoch in range(num_epochs):
        running_loss = 0.0
        for inputs, labels in tqdm(trainloader, desc=f"Epoch [{epoch+1}/{num_epochs}]"):
            inputs, labels = inputs.to(device), labels.to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        epoch_loss = running_loss / len(trainloader)
        train_losses.append(epoch_loss)
        print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}")
    return train_losses

2.1 详细解释:

  • Epoch:一个 epoch 表示模型完整地遍历一次训练数据集。在一个 epoch 内,模型会处理多个批次(batch)的数据。

  • Batch:为了处理大型数据集,训练数据通常被分割成多个小批次。每个批次中的数据量称为 batch size。

在每个 epoch 的训练过程中,我们会累加每个批次的损失到 running_loss 中。running_loss 记录了当前 epoch 中所有批次的总损失。

len(trainloader) 表示训练数据加载器中批次的数量。为了计算当前 epoch 的平均损失,我们将 running_loss 除以批次的数量 len(trainloader)。这种方法提供了一个衡量标准,表示在整个训练周期内,模型在所有训练数据上的平均损失。

2.2 代码解析:

1
epoch_loss = running_loss / len(trainloader)

这行代码计算当前 epoch 的平均损失。running_loss 是所有批次的总损失,将其除以批次数量,得到每个批次的平均损失。这有助于监控训练过程中损失的变化,判断模型是否在逐渐收敛。


总结

在训练模式下,Dropout 和 Batch Normalization 层的行为与评估模式不同,确保这些层在训练过程中表现正确至关重要。