我正在从事自然语言处理的关系分类任务,我对学习过程有一些疑问。我使用 PyTorch 实现了一个卷积神经网络,我正在尝试选择最好的超参数。
我注意到的常见行为是,即使在 1000 个 epoch 之后,我的验证损失仍在缓慢下降,而我的指标(宏观 F1 分数)也在缓慢增加。这两个指标都在波动,可能是由于要分类的 4 个类别不平衡(5%、3%、30%、62%)。我使用的是 Adam,所以学习率不是我自己设定的(它是自适应的)。我在最大池化后使用 dropout 0.5,并使用大小为 50 的小批量。
在书籍和在线教程中,我看到关于何时停止训练的情节非常清楚。例如,当训练损失变得小于验证损失时,或者当验证损失达到平台时。情况似乎并非如此,所以我向更多导航神经网络用户寻求建议:
- 为什么网络在这么多时期(而且如此缓慢)之后仍在学习?这是一种合理的行为吗?我是否需要运行模型 2000 甚至 3000 epoch 才能获得最佳的宏 f1 分数?过度拟合有风险,不是吗?
- 我的网络仅由词嵌入和位置嵌入提供,所以我想知道这种行为是否可以由(i)对于任务而言过于复杂的网络架构,(ii)过于简单而无法建模的网络架构任务的复杂性,(iii)输入的信息量不足以区分类别,因此网络学习困难(因此学习缓慢)。我的网络架构并不深:它有一个嵌入层 + 卷积层 + 最大池层 + softmax。
- 一个附带问题:假设 1000 个 epoch 就足够了。当我需要比较多个模型的性能(或比较不同的超参数组合)时,我需要选择和比较哪个分数?“最后最好的” f1 分数(比如在 980 纪元)或最后报告的分数(即在 1000 纪元的分数)?
你有什么建议吗?如果有不清楚的地方,请告诉我!
=====
更新
按照Djib2011的建议,我用不同的学习率训练了网络,特别是lr=0.001
(默认)lr=0.01
、、lr=0.1
. 我使用更多的 epoch(即 3000 个)训练网络,以确定我可以停止训练的时刻。我注意到的是,提高学习率并没有帮助,默认情况下会给出最好的结果lr=0.001
。但是,目前还不清楚何时停止。
你有其他建议来解决这个问题吗?除了学习率,优化器背后可能还有其他问题(例如,网络容量小)?先感谢您!
=====
更新#2
在尝试了具有不同学习率和 3000 个 epoch 的不同优化算法(即 RMSProp、AdaDelta、Admax、SGD)后,我注意到在这些不同设置下的行为仍然相同(没有收敛,许多 epoch 几乎没有减少训练和验证损失)。
因此,我通过在(训练)批处理循环内移动 3 行:、、、而不是在循环后运行它们来optimizer.zero_grad()
修改loss.backward()
pytorch实现。optimizer.step()
因此,这是在每个 epoch 执行训练和测试的编辑代码:
# Iterate over epochs
for epoch in range(1, n_epochs+1):
train_loss = 0
model.train()
train_predictions = []
train_true_labels = []
# Iterate over training batches
for i, (inputs, labels) in enumerate(train_loader):
inputs, labels = Variable(inputs).to(device), Variable(labels).to(device)
optimizer.zero_grad() # set gradients to zero
preds = model(inputs)
preds.to(device)
# Compute the loss and accumulate it to print it afterwards
loss = loss_criterion(preds, labels)
train_loss += loss.detach()
pred_values, pred_encoded_labels = torch.max(preds.data, 1)
pred_encoded_labels = pred_encoded_labels.cpu().numpy()
train_predictions.extend(pred_encoded_labels)
train_true_labels.extend(labels)
loss.backward() # backpropagate and compute gradients
optimizer.step() # perform a parameter update
# Evaluate on development test
predictions = []
true_labels = []
dev_loss = 0
model.eval()
for i, (inputs, labels) in enumerate(dev_loader):
inputs, labels = Variable(inputs).to(device), Variable(labels).to(device)
preds = model(inputs)
preds.to(device)
loss = loss_criterion(preds, labels)
dev_loss += loss.detach()
pred_values, pred_encoded_labels = torch.max(preds.data, 1)
pred_encoded_labels = pred_encoded_labels.cpu().numpy()
predictions.extend(pred_encoded_labels)
true_labels.extend(labels)
因此,我使用我的默认配置(Adam,lr=0.001)再次训练了网络,令人惊讶的是,我在 epoch 22 处获得了收敛(见下图)。我认为问题就在那里,你同意吗?你有什么额外的建议吗?再次感谢!