Python 文本二值分类训练中的波动损失

Python 文本二值分类训练中的波动损失,python,machine-learning,pytorch,huggingface-transformers,allennlp,Python,Machine Learning,Pytorch,Huggingface Transformers,Allennlp,我正在使用文档文本二进制分类任务对a进行微调,并使用Tensorboard监视一些检查点的度量 即使F1的分数和准确度都很高,我也对训练损失的波动感到困惑 我在网上读到这样的原因可能是: 学习率太高,但我尝试了3个值(1e-4、1e-5和1e-6),它们都产生了相同的效果 小批量。我使用的是Sagemaker笔记本电脑p2.8xlarge,具有8xK80 GPU。可用于避免CUDA内存不足错误的每个GPU的批大小为1。因此,总批量为8。我的直觉是,对于包含57K个示例(每个历元7K个步骤)的数

我正在使用文档文本二进制分类任务对a进行微调,并使用Tensorboard监视一些检查点的度量

即使F1的分数和准确度都很高,我也对训练损失的波动感到困惑

我在网上读到这样的原因可能是:

  • 学习率太高,但我尝试了3个值(1e-4、1e-5和1e-6),它们都产生了相同的效果
  • 小批量。我使用的是Sagemaker笔记本电脑p2.8xlarge,具有8xK80 GPU。可用于避免CUDA内存不足错误的每个GPU的批大小为1。因此,总批量为8。我的直觉是,对于包含57K个示例(每个历元7K个步骤)的数据集来说,8的bs太小了。不幸的是,这是我能使用的最高值
在这里,我报告了F1的趋势、精度、损耗和平滑损耗。灰色线表示学习率为1e-6,粉色线表示学习率为1e-5

我重新总结了我培训的所有信息:

  • 批量大小:1 x 8GPU=8
  • 学习率1e-41e-51e-6(所有测试均未改善损失)
  • 型号Longformer
  • 数据集
    • 培训集:57K个示例
    • 开发集:12K示例
    • 测试集:12K个示例

原因可能是什么?尽管F1成绩和精度都很好,但这算是一个问题吗?

我将首先告诉您波动的原因,然后告诉您可能的解决方法

原因

当你训练一个网络时,你要计算一个可以减少损失的梯度。为了做到这一点,您需要反向传播损失。现在,理想情况下,根据数据中的所有样本计算损失,因为这样,基本上每个样本都可以考虑,并且得到一个可以捕获所有样本的梯度。实际上,这是不可能的,因为在所有样本上计算梯度的计算复杂性

因此,我们使用小批量作为近似值!我们的想法不是考虑所有的样本,而是说我根据一些小样本集计算梯度,但作为一种权衡,我丢失了关于梯度的信息

经验法则:较小的批量大小会产生嘈杂的梯度,但它们收敛速度更快,因为每个历元都有更多的更新。如果批大小为1,则每个历元将有N个更新。如果为N,则每个历元只有1次更新。另一方面,更大的批量提供了更多的信息梯度,但它们收敛速度较慢,增加了计算复杂性。

这就是为什么对于较小的批量,您会观察到不同的损失/波动,因为梯度很嘈杂

解决方案:累积梯度

在内存问题的情况下,您可以使用累积梯度的概念来对抗波动性丢失。它计算每个小批次后的损失和梯度,但不是更新每个批次上的权重,而是等待并累积连续批次上的梯度。然后在指定批次数后,根据累积梯度最终更新参数


在本页的文档中,您可以找到如何应用它:

这是由于批量较小造成的。这是否会被认为是模型预测的问题?你认为高bs也能提高f1成绩吗?f1成绩取决于准确率和召回率。如果增加批量大小,可以得到平滑的损失曲线。但是F1成绩取决于你的模型在所有级别上的表现。所以,每节课的例子数量也会影响f1成绩。所以,也许,保持固定的bs,减少训练集的大小会是一种改进吗?减少训练集的大小应该没有帮助。如果您的评估指标/结果看起来不错,这可能不是一个大问题。你在小批量中看到这一点的原因是,你可以得到一个“简单”的批量,比如说5/8的例子非常简单,而3/8的例子有点难。如果您想尝试增加批处理大小,您可能可以尝试梯度累积和/或梯度检查点,这两种方法都可以让您在一个步骤中完成更多处理,但代价是速度变慢