变压器中的馈送解码器输入
Feed decoder input in transformers
读取this tutorial on how to implement an Encoder/Decoder transformer I had some doubts on the training process. Specifically as reported by the original paper解码器应该迭代地使用最后一次迭代输出作为解码器的输入。然而,训练步骤实现为
@tf.function(input_signature=train_step_signature)
def train_step(inp, tar):
tar_inp = tar[:, :-1]
tar_real = tar[:, 1:]
with tf.GradientTape() as tape:
predictions, _ = transformer([inp, tar_inp],
training = True)
loss = loss_function(tar_real, predictions)
gradients = tape.gradient(loss, transformer.trainable_variables)
optimizer.apply_gradients(zip(gradients, transformer.trainable_variables))
其中 tar_inp
只是一个没有 EOS 标记的标记化句子,tar_real
是同一个句子移动了一个位置。
然而,我本以为目标输入(解码器输入)会被先前的预测迭代地连接起来(或者在教师强制下一次增加一个地面真值标记)。
为什么不是这样?
这个特定示例实际上使用了教师强制,但它不是一次提供一个 GT 令牌,而是提供整个解码器输入。但是,由于解码器仅使用自回归(即从右到左)注意力,因此在生成第 i
个标记时,它只能关注标记 0...i-1
。因此,这样的训练相当于教师一次强制一个标记,但速度要快得多,因为所有这些标记都是并行预测的。
读取this tutorial on how to implement an Encoder/Decoder transformer I had some doubts on the training process. Specifically as reported by the original paper解码器应该迭代地使用最后一次迭代输出作为解码器的输入。然而,训练步骤实现为
@tf.function(input_signature=train_step_signature)
def train_step(inp, tar):
tar_inp = tar[:, :-1]
tar_real = tar[:, 1:]
with tf.GradientTape() as tape:
predictions, _ = transformer([inp, tar_inp],
training = True)
loss = loss_function(tar_real, predictions)
gradients = tape.gradient(loss, transformer.trainable_variables)
optimizer.apply_gradients(zip(gradients, transformer.trainable_variables))
其中 tar_inp
只是一个没有 EOS 标记的标记化句子,tar_real
是同一个句子移动了一个位置。
然而,我本以为目标输入(解码器输入)会被先前的预测迭代地连接起来(或者在教师强制下一次增加一个地面真值标记)。
为什么不是这样?
这个特定示例实际上使用了教师强制,但它不是一次提供一个 GT 令牌,而是提供整个解码器输入。但是,由于解码器仅使用自回归(即从右到左)注意力,因此在生成第 i
个标记时,它只能关注标记 0...i-1
。因此,这样的训练相当于教师一次强制一个标记,但速度要快得多,因为所有这些标记都是并行预测的。