趋近智
正如我们所讨论的,仅仅衡量神经网络在训练数据上的表现并不能说明全部情况。一个模型可能在其训练样本上达到非常低的误差,但当面对新的、未见过的数据时却表现糟糕。这种差异突出了学习与记忆之间的区别。我们需要一种方法来评估模型在开发过程中实际表现如何,而无需接触最终测试数据。这正是验证集的作用。
核心思路很简单:在训练开始前,您会留出部分数据集,这部分数据在训练过程中模型绝不会接触到(这意味着,模型的梯度将不会基于这些数据计算)。这部分预留的数据就是您的验证集。其余部分则用于模型训练(即训练集)。
通常,您可以这样划分数据:
区分验证集和测试集很重要。可以将验证集看作您的彩排或模拟考试。您用它来微调方法(调整超参数,决定何时停止训练)。测试集是期末考试,只进行一次,以了解您真实的学习效果。在开发过程中反复使用测试集,就好像提前研究期末考试题目一样;您的最终分数将无法准确反映您的知识水平。
验证集在开发过程中主要有两个用途:
训练损失持续下降,而验证损失在大约第30个周期开始上升,这表明过拟合开始发生。
在训练循环中加入验证检查相对简单。在每个周期后(或有时更频繁),您会使用验证数据进行一次前向传播,计算损失和任何其他相关指标(如准确率),但非常重要的是,您不会基于这些验证数据执行反向传播或更新权重。
以下是一个类似 Python 的伪代码片段,说明了此过程:
# 假设数据集已划分为 train_data, validation_data
# 假设 model, optimizer, loss_function 已定义
for epoch in range(num_epochs):
# --- 训练阶段 ---
model.train() # 将模型设置为训练模式(与 Dropout 等层相关)
total_train_loss = 0
for batch in train_data:
inputs, targets = batch
optimizer.zero_grad() # 重置梯度
outputs = model(inputs) # 前向传播
loss = loss_function(outputs, targets) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新权重
total_train_loss += loss.item()
avg_train_loss = total_train_loss / len(train_data)
print(f"Epoch {epoch+1}: Training Loss = {avg_train_loss}")
# --- 验证阶段 ---
model.eval() # 将模型设置为评估模式
total_val_loss = 0
with torch.no_grad(): # 禁用验证的梯度计算
for batch in validation_data:
inputs, targets = batch
outputs = model(inputs) # 仅前向传播
loss = loss_function(outputs, targets)
total_val_loss += loss.item()
# 如果需要,计算准确率等其他指标
avg_val_loss = total_val_loss / len(validation_data)
print(f"Epoch {epoch+1}: Validation Loss = {avg_val_loss}")
# --- 检查点 / 早停逻辑(使用 avg_val_loss)---
# (更多内容请参阅早停部分)
# 如果验证损失有所改善,则保存模型等。
# --- 最终评估(在训练循环之后)---
# 根据验证表现加载最佳模型
# 在 test_data 上进行评估(该数据之前从未被使用)
因此,验证集是构建高效机器学习模型的迭代过程中不可或缺的一部分。它提供了指导训练、防止过拟合以及选择最有可能在新、未见过数据上表现良好的模型配置所需的反馈。没有它,您将如同盲人摸象,不确定模型在训练数据上的改进是否真的能转化为有意义的泛化能力。
这部分内容有帮助吗?
nn.Module的train()和eval()方法以及torch.no_grad()上下文管理器,这些对于实现训练和验证循环非常重要。© 2026 ApX Machine Learning用心打造