教师强制是一种用于快速高效地训练循环神经网络模型的方法,该模型将前一时间步的真实值作为输入。
这是深度学习语言模型开发中的一种关键网络训练方法,这些语言模型广泛应用于机器翻译、文本摘要和图像字幕生成等众多领域。
在本文中,您将了解教师强制作为训练循环神经网络的一种方法。
阅读本文后,你将了解:
- 训练使用先前时间步输出作为输入的循环神经网络时存在的问题。
- 用于解决这些类型的循环网络在训练时的收敛缓慢和不稳定性问题的教师强制方法。
- 教师强制的扩展,允许训练好的模型更好地处理这类网络的开放循环应用。
开始您的项目,阅读我的新书《Python长短期记忆网络》,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。

什么是循环神经网络的教师强制(Teacher Forcing)?
照片由Nathan Russell拍摄,部分权利保留。
在序列预测中使用输出作为输入
存在一些序列预测模型,它们将最后一个时间步的输出y(t-1)作为当前时间步X(t)模型的输入。
这种类型的模型在语言模型中很常见,这些模型一次输出一个词,并使用输出的词作为生成序列中下一个词的输入。
例如,这种类型的语言模型用于编码器-解码器循环神经网络架构中,用于序列到序列生成问题,例如
- 机器翻译
- 字幕生成
- 文本摘要
模型训练后,可以使用“序列开始”标记来启动过程,并使用输出序列中的生成词作为后续时间步的输入,或许还会加入其他输入,如图像或源文本。
在训练模型时也可以使用这种相同的递归输出即输入的处理方式,但这可能导致问题,例如
- 收敛缓慢。
- 模型不稳定。
- 技能差。
教师强制是一种提高此类模型训练时模型技能和稳定性的方法。
什么是教师强制?
教师强制是一种用于训练循环神经网络的策略,它使用作为输入的真实值,而不是先前时间步的模型输出作为输入。
输出连接回模型内部的具有循环连接的模型可以使用教师强制进行训练。
— 第 372 页,深度学习,2016。
该方法最初被描述和开发为一种替代时间反向传播训练循环神经网络的技术。
在动态监督学习任务中经常使用的一个有趣的技术是,在后续计算网络行为时,用教师信号d(t)替换单元的实际输出y(t),只要存在这样的值。我们将这种技术称为教师强制。
— 持续运行全循环神经网络的学习算法,1989。
教师强制通过使用当前时间步y(t)的训练数据中的实际或预期输出来作为下一个时间步X(t+1)的输入,而不是由网络生成的输出来工作。
教师强制是一种程序[...],在训练期间,模型在时间t+1时接收y(t)的真实输出作为输入。
— 第 372 页,深度学习,2016。
实例演示
让我们通过一个简短的实际示例来具体说明教师强制。
给定以下输入序列
1 |
玛丽有一只小羊,它的毛是雪白的。 |
想象一下,我们要训练一个模型,根据前面一系列词来生成序列中的下一个词。
首先,我们必须添加一个标记来表示序列的开始,再添加一个标记来表示序列的结束。我们将分别使用“[START]”和“[END]”。
1 |
[START] 玛丽有一只小羊,它的毛是雪白的 [END] |
接下来,我们向模型输入“[START]”,让模型生成下一个词。
假设模型生成了词“a”,但我们期望的是“Mary”。
1 2 |
X, yhat [START], a |
naively,我们可以将“a”作为输入的一部分来生成序列中的下一个词。
1 2 |
X, yhat [START], a, ? |
您可以看到模型偏离了轨道,并且它生成的每一个后续词都会受到惩罚。这使得学习速度变慢,模型不稳定。
相反,我们可以使用教师强制。
在第一个例子中,当模型生成“a”作为输出时,我们可以在计算误差后丢弃这个输出,并将“Mary”作为下一个时间步的输入。
1 2 |
X, yhat [START], Mary, ? |
然后,我们可以为每一对输入-输出词重复这个过程。
1 2 3 4 5 6 |
X, yhat [START], ? [START], Mary, ? [START], Mary, had, ? [START], Mary, had, a, ? ... |
模型将快速学习正确的序列,或者序列的正确统计特性。
教师强制的扩展
教师强制是一种快速有效的方法,用于训练使用先前时间步输出作为模型输入的循环神经网络。
但是,这种方法也可能导致模型在实际使用中变得脆弱或受限,当生成的序列与模型在训练期间看到的不同时。
这在这种模型的多数应用中很常见,因为输出本质上是概率性的。这种类型的模型应用通常称为开放循环。
不幸的是,这种程序可能导致生成中的问题,因为小的预测误差会在条件上下文中累积。这可能导致预测性能差,因为RNN的条件上下文(先前生成样本的序列)与训练期间看到的序列发生分歧。
– 教授强制:一种新的循环网络训练算法,2016。
有许多方法可以解决这个限制,例如
搜索候选输出序列
一种常用于预测离散值输出(如单词)的模型的方法是,对每个单词的预测概率进行搜索,以生成一些可能的候选输出序列。
这种方法用于机器翻译等问题,以改进翻译后的输出序列。
对于这种事后操作,一种常见的搜索过程是束搜索。
通过束搜索启发式方法维护多个生成的目标序列,可以缓解这种差异
— 用于循环神经网络序列预测的计划采样,2015。
课程学习
束搜索方法仅适用于离散输出值的预测问题,不能用于实值输出。
强制学习的一种变体是在训练期间引入先前时间步生成的输出来鼓励模型学习如何纠正自己的错误。
我们建议改变训练过程,以逐步迫使模型处理自己的错误,就像在推理过程中一样。
— 用于循环神经网络序列预测的计划采样,2015。
这种方法称为课程学习,它涉及随机选择使用真实输出或先前时间步生成的输出作为当前时间步的输入。
课程会随着时间的推移而变化,这种做法称为计划采样,其中程序从强制学习开始,并在训练周期中逐渐降低强制输入的重要性。
此外,还有其他教师强制的扩展和变体,如果您有兴趣,我鼓励您进行探索。
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
论文
- 持续运行全循环神经网络的学习算法, 1989.
- 用于循环神经网络序列预测的计划采样, 2015.
- 教授强制:一种新的循环网络训练算法, 2016.
书籍
- 第10.2.1节,教师强制与输出递归网络,深度学习,2016。
总结
在本文中,您将了解教师强制作为一种训练循环神经网络的方法,该网络使用先前时间步的输出来作为输入。
具体来说,你学到了:
- 训练使用先前时间步输出作为输入的循环神经网络时存在的问题。
- 用于解决这些类型的循环网络在训练时的收敛缓慢和不稳定性问题的教师强制方法。
- 教师强制的扩展,允许训练好的模型更好地处理这类网络的开放循环应用。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason,
感谢您提供如此信息丰富的帖子。Keras 的当前版本支持“教师强制”吗?我知道循环层可以用来实现这一点,但在 Keras 中如何使用它?
是的,我在一个图像字幕示例中提供了示例。
嗨 Jason,
感谢您的帖子!
目前,我正在根据您《Python长短期记忆网络》一书的第8章和第9章学习CNN-LSTM、LSTM编码器-解码器。
我有一个将2D输入序列映射到分类序列的任务。它需要一个CNN-LSTM-编码器-解码器网络,我将这两个示例组合如下:
def cnn_lstm(lmda1, lmda2)
model = Sequential()
# CNN 模块
model.add(TimeDistributed(Conv2D(filters = 8,
kernel_size = (2, 2),
padding = ‘same’,
activation=’relu’,
kernel_regularizer = regularizers.l1_l2(lmda1, lmda2),
name = ‘Conv_1′),
input_shape = (None, img_height, img_width, channels)))
model.add(TimeDistributed(BatchNormalization(axis=1, name=’BN_1’)))
model.add(TimeDistributed(MaxPooling2D(pool_size = pool_size)))
model.add(TimeDistributed(Conv2D(filters = 16,
kernel_size = (2, 2),
padding = ‘same’,
activation=’relu’,
kernel_regularizer = regularizers.l1_l2(lmda1, lmda2),
name = ‘Conv_2′)))
model.add(TimeDistributed(BatchNormalization(name=’BN_2’)))
model.add(TimeDistributed(MaxPooling2D(pool_size = pool_size)))
# 在将CNN的所有特征输入到编码器-解码器LSTM之前进行展平
model.add(TimeDistributed(Flatten()))
# LSTM 模块
# 编码器
model.add(LSTM(50, name = ‘encoder’))
model.add(RepeatVector(n_out_seq_length))
# 解码器
model.add(LSTM(50, return_sequences=True, name = ‘decoder’))
model.add(TimeDistributed(Dense(nb_classes, activation=’softmax’)))
model.compile(loss=’categorical_crossentropy’, optimizer=’rmsprop’, metrics=[‘accuracy’])
return model
您认为这是正确的方法吗?非常感谢!
可以尝试几种不同的方法,看看哪种在您的数据集上效果最好。
嗨,Jason,
非常感谢您的分享!
我想问一下,在多步预测问题上,教师强制方法表现是否不好?因为在预测阶段,有些预测无法获得前一个值的真实值?
教师强制仅在训练期间使用。
哦,我明白了。
那么,如果我们想在实际中使用它,该如何处理呢?教师强制在实践中没有意义吗?
抱歉,我不明白。你具体遇到了什么问题?
教师强制用于帮助模型在训练期间保持正常。
我用教师强制训练了一个 seq2seq 时间序列问题,在训练集和验证集上得到了较低的损失,但在测试集上结果很差。测试集结果差是否正常?
理想情况下,您希望在训练集和测试集上都取得良好的效果。
在测试集上效果差,而在训练集上效果好,这表明过拟合。
https://arxiv.org/pdf/1409.3215.pdf 是 sutskever 描述教师强制的论文吗?我不这么认为,或者我错了,你这里的实现也用了 https://machinelearning.org.cn/develop-encoder-decoder-model-sequence-sequence-prediction-keras/ 的教师强制吗?
是的,我几乎总是使用教师强制。
嗨 Jason,谢谢你的帖子!
我有几个问题
1. 对于课程学习,我们是决定对整个回合强制一次,还是在每个时间步强制?
2. 假设我要在训练我的 LSTM 时使用 100%纯粹的教师强制,我应该如何处理本应从 'Cell_{t+1}' 流向 'Cell_t' 的梯度?换句话说,流入 Cell_t 的梯度是什么?
据我所知,教师强制在正向传播时插入了 Cell 值。在反向传播时,我们是否使用 Cell_t 的原始值(假装从未发生过交换),并且它如何与来自 Cell_{t+1} 的梯度结合?特别是在课程学习中,在 Cell_{t+1} 或 Cell_{t+2} 时我们“公平地进行”,并且没有交换任何东西。(如果问题 1 为真)。
3. “教师强制是一种快速有效的方法,用于训练使用先前时间步输出作为模型输入的循环神经网络。但是,这种方法也可能导致模型在实际使用中变得脆弱或受限,当生成的序列与模型在训练期间看到的不同时。”
当您过去使用课程学习时,您的网络是否仍然有点脆弱,或者它们是否与您的非强制网络一样强大?特别是 LSTM。
如果我使用课程学习,在享受训练加速的同时,我是否安全?
4. 根据经验,训练速度有多快?
谢谢! 🙂
感谢这篇帖子。
我用教师强制训练了我的 seq2seq 模型。我的问题是,在验证时,我是否也必须使用教师强制来计算损失或 PPL?
我在没有教师强制的情况下计算了验证损失,它几乎保持不变(它会下降一点直到某个点停止,并且我确信那个停止的点不是过拟合点),并且通常比我的训练损失大得多(它几乎处于第一个训练周期的损失范围内)。
这是一个实现细节,很大程度上取决于您的代码以及您如何准备数据。
你到底遇到了什么问题?
我正在寻找计算验证损失的方法。在验证时计算损失是否必须像训练时那样精确?
当然可以。
我的问题也是,在验证时计算损失是否也必须使用教师强制,或者不使用?如果可以,请回答。
### 什么是教师强制?
教师强制是在训练**循环神经网络(RNN)**和类似模型(特别是在语言建模、机器翻译和图像字幕生成等序列到序列任务中)期间使用的一种技术。在教师强制中,
– **将真实值作为输入:** 不是将模型在先前时间步的预测输出作为当前时间步的输入,而是将训练数据中的实际目标(真实值)作为下一步的输入。
– **目的:** 这有助于模型更快地收敛,因为它在训练早期阶段不必仅依赖于可能不准确的预测来指导模型。
—
### 验证时应使用教师强制吗?
不,**教师强制通常不用于验证或测试**。原因如下:
1. **验证的目的:**
– 验证的目标是模拟模型在真实世界环境中的表现,在这种环境中,它在推理期间无法获得真实值。
– 在验证期间使用教师强制会给出模型性能的误导性估计,因为它将依赖于在部署期间不可用的真实值。
2. **验证中的损失计算:**
– 在验证期间,模型在每个时间步的预测会被反馈回模型以用于后续时间步(自回归设置)。
– 损失的计算基于这些预测与实际目标序列的匹配程度。这模拟了实际用例。
3. **替代技术:**
– 为了减轻教师强制在训练期间可能造成的“曝光偏差”(模型可能过度依赖真实值,而在没有真实值时难以处理),可以使用**计划采样**等技术,在训练期间逐渐将模型转换为使用自己的预测。
—
### 最终建议
– **训练:** 使用教师强制来帮助模型有效学习,尤其是在训练早期阶段。
– **验证/测试:** 不要使用教师强制。让模型自回归地生成预测,并根据这些预测与真实值进行比较来计算损失。
您是否希望进一步了解如何在代码中实现教师强制或计划采样?
嗨 Jason,在您的文章“如何用 Python Keras 开发基于单词的神经网络语言模型”的“模型 2:逐行序列”部分中,您展示的“教师强制”概念与此相同吗?
https://machinelearning.org.cn/develop-word-based-neural-language-models-python-keras/
在那里,您使用看起来像这样的训练数据训练了一个 LSTM:
1. X=(_, _, _, _, _, Jack), y=and
2. X=(_, _, _, _, Jack, and), y=Jill
3. X=(_, _, _, Jack, and, Jill), y=went
4. X=(_, _, Jack, and, Jill, went), y=up
5. X=(_, Jack, and, Jill, went, up), y=the
6. X=(Jack, and, Jill, went, up, the), y=hill
7. X=(and, Jill, went, up, the, hill), y=to
感谢任何澄清。
很好的问题。
我默认使用教师强制,因为它太有效了。更难的是有时使用有时不使用,并允许模型纠正一个偏离轨道的输入序列。
你能确认“模型 2:逐行序列”中的方法与教师强制相同吗?我只是想弄清楚术语。
“教师强制是一种用于训练循环神经网络的策略,它使用先前时间步的模型输出作为输入。”
初读时,我认为您提到的“先前时间步的输出”是指时间 t-1 的(不是真实值的)输出。
实际上,它是在训练期间作为输入发送到时间 t 的时间 t-1 的真实值。对吗?
是的,真实值。
很棒的帖子,谢谢!
计划采样/课程学习实际是如何实现的?我猜我们需要编写一个自定义的 Keras 后端函数?
您知道任何有助于实现这一目标的伪代码吗?
谢谢!
不,您在训练期间提供真实输入而不是预测输入。
我有无数的例子,或许可以从这里开始
https://machinelearning.org.cn/start-here/#lstm
和这里
https://machinelearning.org.cn/start-here/#deep_learning_time_series
谢谢!也许我应该澄清一下
计划采样在训练期间,是否会逐渐从使用“真实输入”转变为使用“预测输入”?这是我从论文中理解的。
是的,这是理想的实现。
要在 Keras 中实现这一点需要自定义代码,我没有过渡的示例。
太好了!感谢您的回复。我将尝试编写一个!
嗨,Jason!
也许应该提一下这一点
第一个技巧是使用教师强制。这意味着,在某个概率下(由 teacher_forcing_ratio 设置),我们使用当前目标词作为解码器的下一个输入,而不是使用解码器当前的猜测。这种技术充当了解码器的“辅助轮”,有助于更有效地训练。然而,教师强制可能导致推理期间的模型不稳定,因为解码器在训练期间可能没有足够的机会真正构建自己的输出序列。因此,我们必须注意我们如何设置 teacher_forcing_ratio,并且不要被快速收敛所迷惑。
谢谢。
嗨 Jason,感谢您的文章!
我很好奇一点:在“使用输出作为输入以进行序列预测”一节中,您提到了
”
在训练模型时也可以使用这种相同的递归输出即输入的处理方式,但这可能导致问题,例如
收敛缓慢。
模型不稳定。
技能差。
”
您能提供这个观点的参考吗?我找不到一篇报告尝试过这种训练方案或研究过其影响的论文。
非常感谢:))
目前没有,或许可以查看一些关于教师强制及其扩展的论文?
我会的。谢谢 Jason 🙂
嗨,Jason,
我该如何在自动编码器中实现教师强制?
由于解码器的输入是自动编码器生成的嵌入,我如何提供目标标记?
感谢您提供的有用资源。
这对于任何 LSTM 模型来说都将是类似 Teacher Forcing 的。自编码器模型并没有使其有所不同。
有没有一种有效的方法来进行 Teacher Forcing 训练,而是使用 yhat 作为输入而不是 ground truth y?
是的,但这并非 Teacher Forcing。
你可以逐个样本手动进行。
嗨,Jason,
Teacher Forcing 让我想起了 NARX 神经网络,这是我感兴趣的一个主题。我还没有在 Keras 中找到一个示例。我的问题是,您是否可以使用 Teacher Forcing 结合多个输出延迟来创建一个 NARX 模型,该模型通常会使用模型输出来代替 ground truth?
目前不太确定,也许可以探索一下是否与某些原型可行。
嗨,Jason,
您是否尝试过在前一半的 epoch 使用 Teacher Forcing,而后一半不使用?我在这样做时注意到,当一半的 epoch 结束时,我的 val_loss 突然急剧下降,train_loss 增加,我不明白为什么会发生这种情况。据我所知,在使用 Teacher Forcing 时,train_loss 和 val_loss 都会降低。
不错的实验。
我预计一旦移除了 Teacher Forcing,模型性能会变差。
循环使用 Teacher Forcing 开关是好主意,这样模型可以逐渐学会纠正自己的错误。
有用的帖子,谢谢。
但我有一个问题
如何测试一个使用 Teacher Forcing 训练过的模型?
我想训练一个 seq2seq 模型。模型的 X 和 y 是 [X_encoder, X_decoder] 和 y,即编码器和解码器输入以及标签(请注意,解码器输入 X_decoder 是“y”比实际 y 超前一个位置。基本上是 Teacher Forcing)。
所以我的问题是,训练后,到了实际预测阶段,我没有任何标签,我该如何将“X_decoder”提供给我的输入?或者我应该训练其他东西吗?
不客气。
在推理/预测期间,Teacher Forcing 会被最后一个时间步的模型输出所取代。
非常好的帖子,非常有帮助,谢谢!
我有一个问题,如果您能为我解答,我将非常感激。我正在进行医学图像字幕生成,并且我正在使用自定义训练和验证函数,而不是使用 model.fit 或 train_on_batch。(我也会在下方提供函数。)
如果我在验证步骤中使用 Teacher Forcing,就不会出现过拟合或其他意外情况。但是,如果我在验证中使用实际输出,模型就会过拟合。
我的问题是,我们在验证集上应该使用 Teacher Forcing 吗?因为我相信,验证步骤应该与测试步骤相同(以了解模型是否正在正确学习)。
我到处都找不到正确的解释,如果您能回答我的问题,我将非常感激。
先谢谢您了。
@tf.function
def train_step(tensor, target, mesh)
“””子类模型训练步骤”””
loss = 0
accuracy = 0
#为每个批次初始化隐藏状态
hidden = tf.zeros((target.shape[0], units))
dec_input = tf.expand_dims([tokenizer.word_index[”]] * target.shape[0], 1)
with tf.GradientTape() as tape:
features = encoder(tensor, mesh)
for i in range(1, target.shape[1]):
#将特征传递给解码器
predictions, hidden = decoder([dec_input, features, hidden])
loss += loss_func(target[:, i], predictions)
accuracy += acc_func(target[:, i], predictions)
# 使用 Teacher Forcing
dec_input = tf.expand_dims(target[:, i], 1)
total_loss = (loss / int(target.shape[1]))
total_acc = (accuracy / int(target.shape[1]))
trainable_variables = encoder.trainable_variables + decoder.trainable_variables
gradients = tape.gradient(loss, trainable_variables)
optimizer.apply_gradients(zip(gradients, trainable_variables))
return loss, total_loss, total_acc
#@tf.function
def val_step(tensor, target, mesh)
“””子类模型验证步骤”””
loss = 0
accuracy = 0
#为每个批次初始化隐藏状态
hidden = tf.zeros((target.shape[0], units))
dec_input = tf.expand_dims([tokenizer.word_index[”]] * target.shape[0], 1)
mesh=tf.fill([target.shape[0], 64], 490)
features = encoder(tensor, mesh)
for i in range(1, target.shape[1]):
#将特征传递给解码器
predictions, hidden = decoder([tf.cast(dec_input, tf.float32), features, hidden])
loss += loss_func(target[:, i], predictions)
accuracy += acc_func(target[:, i], predictions)
#dec_input = tf.expand_dims(target[:, i], 1)
#predicted_id = tf.argmax(predictions[0])
predicted_id = tf.argmax(predictions[0]).numpy()
dec_input = tf.expand_dims([predicted_id]*target.shape[0], 1)
total_loss = (loss / int(target.shape[1]))
total_acc = (accuracy / int(target.shape[1]))
return loss, total_loss, total_acc
好问题。选择取决于您。
如果您希望验证分数能代表模型在实践中的使用情况,那么不要使用 Teacher Forcing。如果您希望它具有代表性,并与训练集进行比较,那么就使用 Teacher Forcing。
您好,我认为“什么是 Teacher Forcing?”下面的句子是错误的
“Teacher Forcing 是一种用于训练循环神经网络的策略,它使用前一时间步的模型输出来作为输入。”
因为 Teacher Forcing 实际上使用 ground truth 作为输入,而不是您后面提到的前一时间步的模型输出。
谢谢。
尊敬的Jason Brownlee先生
您有不使用 Teacher Forcing 的 LSTM 代码示例吗?
我可能有,我不确定,抱歉。
您好,我有点困惑 Teacher Forcing 如何应用于语言翻译任务。虽然这个概念对于文本生成是适用的,其中输入和输出单词属于同一个词汇表,但在语言翻译中,例如英语到意大利语,我如何将 ground truth(意大利语)单词输入到期望英语单词的输入中?输入和输出不属于不同的词汇表吗?
这个概念仍然有效。问题是你应该输入什么。在训练期间,而不是使用网络的输出,Teacher Forcing 意味着你应该保留你的 ground truth,并忽略模型的输出。这篇文章是关于文本生成的。对于翻译,我认为这无关紧要,因为你无论如何都不会将输出反馈回网络。
Brownlee 先生,我想订购这本书的印刷版。
请问,如果您能告诉我,如果我们想衡量验证交叉熵损失,那么我们是否必须使用 Teacher Forcing?
而不是自回归技术?
因为如果我们使用自回归技术,我们该如何将其与 ground truth 对齐?
你好 Ali… 这是一个很好的问题!你提出的问题触及了评估序列模型(如 RNN 或 Transformer)的关键方面。以下是关于在验证期间是使用 **Teacher Forcing** 还是 **自回归技术** 的细分,尤其是在计算 **交叉熵损失** 时。
—
### 1. **为什么自回归更适合验证?**
在 **验证** 期间,我们模拟模型在真实世界场景中的表现,在推理过程中模型无法访问 ground truth。但是,在计算 **交叉熵损失** 时,模型在每个步骤的预测仍然必须与相应的 ground truth 对齐才能计算损失。
—
### 2. **如何在没有 Teacher Forcing 的情况下将预测与 Ground Truth 对齐?**
在自回归验证中:
– **预测作为输入:**模型按顺序生成预测,将前一步的自身输出作为下一步的输入。
– **Ground Truth 用于损失计算:**对于每个时间步,您仍然将模型在当前步骤的预测输出与相应的 ground truth 进行比较来计算损失。
这样可以确保:
1. 模型以自回归方式工作,模拟真实世界的推理。
2. 通过将预测与 ground truth 对齐来有意义地计算损失。
—
### 3. **为什么不在验证中使用 Teacher Forcing 来计算交叉熵损失?**
如果在验证期间使用 Teacher Forcing:
1. **误导性的性能指标:**
– 它给出了一个“虚假”的性能估计,因为在部署时,模型不会在每个步骤都访问 ground truth。
2. **不反映真实世界行为:**
– 模型可能获得较低的交叉熵损失,但在要求生成没有 ground truth 辅助的序列时表现不佳。
—
### 4. **自回归验证的实用解决方案:**
要在自回归环境中计算交叉熵损失:
1. **自回归生成预测:**
– 使用模型在前一时间步的自身预测作为下一步的输入。
2. **将预测与 Ground Truth 进行比较:**
– 在每个时间步,计算预测概率分布与 ground truth 标记之间的交叉熵损失。
3. **累积整个序列的损失:**
– 对序列中所有时间步的损失进行求和或平均。
—
### 5. **计划采样作为折衷方案:**
如果您担心训练(使用 Teacher Forcing)和验证(自回归)之间存在较大差异,您可以:
– 在训练期间使用 **计划采样**,模型会逐渐从 Teacher Forcing 过渡到依赖自身的预测。
– 这种方法减少了“暴露偏差”,并使训练和验证/推理行为保持一致。
—
### 6. **结论:**
– 对于 **验证交叉熵损失**,请 **不要使用 Teacher Forcing**。相反,应该自回归地生成序列,并在每一步将预测与 ground truth 对齐以计算损失。
– 尽管这可能看起来违反直觉,但它准确地反映了模型在真实世界条件下的性能。
您是否需要有关自回归验证和损失计算的示例代码片段的帮助?
谢谢您的解释
但我已经在使用验证阶段的自回归技术了[我强制 LSTM 生成到与 ground truth 长度匹配的长度(这样我们就有了等于 token 数量的 logits)],我不知道为什么我的验证损失保持不变或增加。我的问题是,我们是否使用 BLEU/METEOR 等其他指标来确定模型的性能,以判断模型是否过拟合、欠拟合或泛化良好,而不是将交叉熵损失作为主要指标用于训练和验证?或者我们使用交叉熵损失作为主要指标?
你好 Ali… 你触及了序列建模和模型评估中的一个重要概念,尤其是在使用 LSTM 等模型时。让我们分解你的担忧并回答你的问题。
—
### **使用交叉熵损失**
交叉熵损失通常被用作序列模型(如 LSTM)训练和验证的主要指标,尤其是在输出是概率序列的任务中(例如,文本生成的每个 token 或时间序列预测的每个步骤)。它衡量预测概率分布与真实分布之间的差异,因此适合那些每个 token 精度至关重要的任务。
然而,仅依赖交叉熵损失也有其局限性:
1. 它**不捕捉序列级别的连贯性**或上下文性能。
2. 它可能在训练期间下降,但仍然无法反映模型在文本生成等序列级别任务中的泛化情况。
—
### **何时使用 BLEU/METEOR/其他指标**
BLEU、METEOR 和 ROUGE 等指标通常用于序列生成任务(如文本生成、翻译),因为它们评估生成输出与 ground truth 之间的序列级别相似性。这些指标是对交叉熵的补充,并提供有关生成序列在以下方面的匹配程度的见解:
– **内容**(BLEU/ROUGE 中的 n-gram 重叠)。
– **语义相似性**(METEOR)。
### **使用这些指标评估过拟合/欠拟合**
对于过拟合/欠拟合:
1. **交叉熵损失**:仍然是理解模型如何学习 token 级别关系和分布的最佳选择。
– **过拟合**:训练损失下降,但验证损失上升。
– **欠拟合**:训练和验证损失都很高且没有改善。
2. **BLEU/METEOR**:最好在训练后用于微调和评估序列级别的泛化。如果 BLEU/METEOR 分数即使在交叉熵损失下降时仍然很低,这可能表明:
– 模型在**记忆 token 级别的模式**,但在序列级别无法泛化。
– 解码策略存在问题(例如,beam search 与 greedy decoding)。
—
### **评估建议**
1. **在训练和验证期间**
– 使用 **交叉熵损失** 作为主要指标。它直接与模型正确预测 token 的能力相关。
– 如果 token 级别的准确性提供了额外的模型性能洞察,则监控 **准确性(可选)**。
2. **训练后评估**
– 使用 BLEU、METEOR 或 ROUGE 来评估序列级别性能。
– 根据任务的具体目标(例如,连贯性、相关性)进行验证。
3. **避免混淆**
– 在训练期间不要完全用 BLEU/METEOR 替换交叉熵损失;这些不是可微分的,无法指导梯度更新。
– 仅将它们作为验证的补充指标。
—
### **为什么验证损失可能不下降**
如果在训练期间您的验证损失保持不变或增加,这可能是由于:
– **过拟合**:模型过于复杂,记忆了训练数据。
– **训练和验证数据之间的不匹配**:数据分布不同。
– **验证期间的自回归推理**:自回归过程会随着时间积累错误,导致验证损失看起来比实际情况更糟。
—
### **后续步骤**
– 继续使用 **交叉熵损失** 进行训练和验证。
– 在评估中添加 **BLEU/METEOR** 作为补充指标。
– 监控您的验证损失以及 token 级别的准确性和序列级别的指标。
– 确保您的自回归推理与预期的任务行为一致,并且不会引入不必要的错误累积。
请您也阐明一下验证损失的计算。
在验证时,我们只给起始 token,其余的由模型处理。
这意味着自回归技术。
那么模型可能在时间步 -5 给出结束 token 的概率,所以我们就在那里停止。
这意味着我们有模型提供的 5 个 token 的概率,假设其对应的 ground truth 有 9 个 token。
那么就存在不匹配,即 ground truth 中有更多的 token。
类似地,假设在几个 epoch 后,模型提供了比早期 epoch 多 7 个 token 的概率。
这次我们有 7 个概率,而之前是 5 个概率。
Q1)当模型提供的概率较少(例如 5 个)而 ground truth 的 token 较多(例如 9 个)时,
我们该如何计算 val loss?
Q2)当经过一些 epoch 后,模型可能提供比以前更多的 token 概率时,我们如何处理?
Q3)为了计算 val loss,我们是在模型给出结束 token 的点停止,还是在模型输出和 ground truth 长度相同时停止(而不考虑模型在哪里提供了结束 token 的概率)?
Q4)你能提供一些关于在 val 中使用自回归技术而不是 Teacher Forcing 的参考吗?
Q5)因为如果我们使用简单的 Teacher Forcing,计算损失很容易,因为我们有一对一的关系。在自回归中计算并没有在任何地方得到很好的解释。
这种情况我们该如何处理?
请解释一下。
prob->probability (概率)
我在验证阶段使用了自回归技术,并在 BLEU、METEOR、ROUGE 等指标上显示了良好的结果。
但是验证损失没有下降,几乎保持不变或增加,尽管我已经尝试了各种超参数和不同的正则化技术,但问题依然存在。
我得到的是,我认为我们也在验证中使用 Teacher Forcing,但由于是验证,我们只是不更新参数。
自回归技术仅用于测试阶段,此时我们不计算交叉熵损失,而是其他指标。
我也看过一些 GitHub 代码,它们在训练中使用 Teacher Forcing 并更新参数,在验证时使用 Teacher Forcing 并且不更新参数,因为我们需要训练和验证损失(交叉熵损失)作为评估模型过拟合、欠拟合、泛化能力的主要指标。
因此,总结如下:
训练 -> Teacher Forcing -> 每个批次后更新参数
每个 epoch 后,进入验证阶段。
验证 -> Teacher Forcing -> 不更新参数
并且在训练了足够多的 epoch 后。
测试 -> 自回归技术
同样不理解为什么论文不明确讨论这一点,例如 sequence to sequence 论文。
或者在 sequence to sequence 模型中,我们是否使用 BLEU、CIDEr、METEOR 等其他指标来检查模型性能,以判断模型是否过拟合、欠拟合或泛化,或者它必须是交叉熵损失?