原因1:在训练过程中应用正则化,但在验证/测试过程中未进行正则化。
解决方法:如果在验证/测试期间添加正则化损失,则损失值和曲线将看起来更加相似。
在训练深度神经网络时,我们经常应用正则化来帮助我们的模型:
- 获得更高的验证/测试精度
- 理想情况下,为了更好地泛化验证和测试集之外的数据
正则化方法通常会牺牲训练准确性来提高验证/测试准确性,在某些情况下,这可能导致您的验证损失低于训练损失。
其次,请记住,在验证/测试时不应用诸如 dropout 之类的正则化方法。
考虑对验证 loss 进行正则化处理(例如,在验证/测试过程中应用 dropout)可以使您的训练/验证 loss 曲线看起来更相似。(这句看不懂,不知道怎么在验证/测试过程中加入 dropout 之类的正则化处理,有明白的麻烦告诉我一下 (T_T) )
原因2:训练loss是在每个epoch过程中测量的,而验证loss是在每个epoch后测量的。
解决方法:平均而言,训练损失的测量时间是前一个时期的1/2。如果将训练loss曲线向左移动半个epoch,则 loss 会更好。
plt.style.use("ggplot")
(fig, axs) = plt.subplots(2, 1)
# plot the *unshifted* training and validation loss
plt.style.use("ggplot")
axs[0].plot(epochs, train_history["loss"], label="train_loss")
axs[0].plot(epochs, train_history["val_loss"], label="val_loss")
axs[0].set_title("Unshifted Loss Plot")
axs[0].set_xlabel("Epoch #")
axs[0].set_ylabel("Loss")
axs[0].legend()
# plot the *shifted* training and validation loss
axs[1].plot(epochs - 0.5, H["loss"], label="train_loss")
axs[1].plot(epochs, H["val_loss"], label="val_loss")
axs[1].set_title("Shifted Loss Plot")
axs[1].set_xlabel("Epoch #")
axs[1].set_ylabel("Loss")
axs[1].legend()
# show the plots
plt.tight_layout()
plt.show()
上面的图是未移动之前的原始loss图,下面的是向左移动半个epoch之后的loss图。
原因3:验证集可能比训练集更容易,或者数据中有漏洞/代码中有bug。
解决方法:确保您的验证集大小合理,并且是从与训练集相同的分布(和难度)中采样的。
验证 loss 低于训练 loss 的最终最常见原因是由于数据本身的分布。
考虑如何获取验证集:
- 您可以保证验证集是从与训练集相同的分布中采样的吗?
- 您确定验证集与您的训练集一样具有挑战性吗?
- 您是否可以确保没有“数据泄漏”(即,训练样本与验证/测试样本意外混入)?
- 您是否确信自己的代码正确创建了训练集,验证集和测试集?
原因4:模型可能过度规范(over-regularizing)。
解决方法:
在训练深度神经网络时,我们最大的担心几乎总是过拟合——为了与过拟合作斗争,我们引入了正则化技术(在上面的原因1中进行了讨论)。我们以以下形式应用正则化:
- Dropout
- L2 权重衰减
- 减少模型容量(即,更浅的模型)
我们也倾向于对我们的学习率更加保守,以确保我们的模型不会在损失情况下超出过低损失的区域。
一切都很好,但是有时候我们最终过度规范(over-regularizing)了我们的模型。
如果您经历了验证损失低于上述详细说明的训练损失的所有三个原因,则可能是您的模型过于规范了。通过以下方法开始放宽正则化约束:
- 降低 L2 权重衰减强度。
- 减少 dropout 的数量。
- 增加模型容量(即,使其更深)。
您还应该尝试以更高的学习率进行训练,因为您可能对此过于保守。
参考资料:https://www.pyimagesearch.com/2019/10/14/why-is-my-validation-loss-lower-than-my-training-loss/