Loading...

目录


Train VS Eval

在完成模型的训练后,我们需要在测试集/验证集上完成模型的验证,以确保模型具有泛化能力、不会出现过拟合等问题。在PyTorch中,训练和评估的流程基本一致,区别在于训练过程需要更新模型的参数,而评估过程则不需要更新参数。

设置模型状态

  • 训练状态:模型的参数应该支持反向传播的修改。
    1
    model.train()
  • 验证/测试状态:不应该修改模型参数。
    1
    model.eval()

训练流程

  1. 读取数据:使用for循环从DataLoader中读取全部数据。
    1
    for data, label in train_loader:
  2. 将数据转移到GPU上(以.cuda()为例):
    1
    data, label = data.cuda(), label.cuda()
  3. 初始化优化器的梯度:
    1
    optimizer.zero_grad()
  4. 将数据输入模型进行训练,并计算损失函数:
    1
    2
    output = model(data)
    loss = criterion(output, label)
  5. 将损失反向传播回网络,并更新模型参数:
    1
    2
    loss.backward()
    optimizer.step()

验证/测试流程

与训练流程基本一致,但有以下不同:

  • 预先设置torch.no_grad(),并将模型调至eval模式。
  • 不需要将优化器的梯度置零
  • 不需要将损失反向传播回网络
  • 不需要更新优化器

对比

训练过程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
def train(epoch):
model.train()
train_loss = 0
for data, label in train_loader:
data, label = data.cuda(), label.cuda()
optimizer.zero_grad()
output = model(data)
loss = criterion(output, label)
loss.backward()
optimizer.step()
train_loss += loss.item() * data.size(0)
train_loss /= len(train_loader.dataset)
print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))

验证过程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def val(epoch):
model.eval()
val_loss = 0
running_accu = 0
with torch.no_grad():
for data, label in val_loader:
data, label = data.cuda(), label.cuda()
output = model(data)
preds = torch.argmax(output, 1)
loss = criterion(output, label)
val_loss += loss.item() * data.size(0)
running_accu += torch.sum(preds == label.data)
val_loss /= len(val_loader.dataset)
print('Epoch: {} \tValidation Loss: {:.6f}'.format(epoch, val_loss))

计算模型指标

可以使用sklearn.metrics中的classification_report函数来计算模型的准确率、召回率、F1值等指标:

1
2
3
4
5
from sklearn.metrics import classification_report

# 替换以下代码中的labels和preds为模型预测出来的所有label和preds
# target_names替换为类别名称,即可得到模型的分类报告
print(classification_report(labels.cpu(), preds.cpu(), target_names=class_names))


训练集、验证集和测试集

模型设计

  • 模型架构:包括模型的层数以及每层的神经元数量。
  • 可训练权重参数:模型内置的可训练参数。

模型训练的参数

这些是模型外置参数,如学习率、优化策略等。

数据集分类

  • 训练集(Train Set):用于模型拟合的数据样本,用于通过梯度下降进行学习。
  • 验证集(Validation Set):在模型训练过程中单独留出的样本集,用于调整模型的超参数和进行初步评估。
    • 可以用来发现模型或参数问题,如模型在验证集上的发散、奇怪的结果、mAP不增等情况。
    • 有助于验证模型的泛化能力,并通过对比不同模型来选择最优模型。
    • 通常在几个epoch后运行一次,以观察效果,但过于频繁会影响训练速度。
  • 测试集(Test Set):用来评估模型最终的泛化能力,不应用于调参或特征选择等。

测试集的分类:

  • “test-dev” 代表开发测试集(Development Test Set),通常用于开发和调试阶段,用来评估模型的表现,并且通常会反复使用以进行参数调整和模型改进。

  • “test-std” 代表标准测试集(Standard Test Set),通常用于最终评估模型的性能,并且不会用于模型的开发或者调整。它可以看作是一个独立的、固定的测试集,用于评估模型在真实场景下的表现。

数据集的作用与特点

类别 是否被训练到 作用 使用次数 缺陷
验证集 调超参数 多次使用 可能低估泛化误差
测试集 验证泛化性能 仅一次使用 数据量大,测试耗时

验证集和测试集的互相转化

  • 验证集是必需的,用于“人工调参”过程。
  • 训练集、验证集和测试集应遵循相同的数据分布,以进行有效的调参。
  • 测试集存在的目的是为了验证模型的泛化能力。

验证集的作用

  • 使用提前终止(early stopping)策略,基于validation_data的分类精度来防止过拟合。
  • 通过validation_data而非test_data设置超参数,避免对test_data过拟合。
  • validation_data被视为帮助学习合适超参数的训练数据,与test_data分离开,采用分离法(hold out method)。

参考链接