【问题标题】:Why we need a decoder_start_token_id during generation in HuggingFace BART?为什么我们在 HuggingFace BART 的生成过程中需要一个 decoder_start_token_id?
【发布时间】:2021-03-02 09:58:12
【问题描述】:

在 HuggingFace 的代码生成阶段: https://github.com/huggingface/transformers/blob/master/src/transformers/generation_utils.py#L88-L100

他们传递了decoder_start_token_id,我不确定他们为什么需要这个。而在 BART 配置中,decoder_start_token_id 实际上是2 (https://huggingface.co/facebook/bart-base/blob/main/config.json),即句尾标记</s>

我尝试了一个简单的例子:

from transformers import *

import torch
model = BartForConditionalGeneration.from_pretrained('facebook/bart-base')
tokenizer = BartTokenizer.from_pretrained('facebook/bart-base')
input_ids = torch.LongTensor([[0, 894, 213, 7, 334, 479, 2]])
res = model.generate(input_ids, num_beams=1, max_length=100)

print(res)

preds = [tokenizer.decode(g, skip_special_tokens=True, clean_up_tokenization_spaces=True).strip() for g in res]
print(preds)

我得到的结果:

tensor([[  2,   0, 894, 213,   7, 334, 479,   2]])
['He go to school.'] 

虽然不影响最终的“分词解码”结果。但我觉得很奇怪,我们生成的第一个令牌实际上是2(</s>)。

【问题讨论】:

  • 他们目前正在讨论它(link)。

标签: nlp pytorch huggingface-transformers


【解决方案1】:

您可以在encoder-decoder models 的代码中看到解码器的输入标记从原始标记右移(参见函数shift_tokens_right)。这意味着要猜测的第一个标记始终是 BOS(句子的开头)。您可以检查您的示例中是否属于这种情况。

为了让解码器理解这一点,我们必须选择一个总是跟着 BOS 的第一个令牌,那么它可能是哪个?博斯?显然不是,因为它必须跟随常规标记。填充令牌?也不是一个好的选择,因为它后面跟着另一个填充令牌或 EOS(句末)。那么,EOS 呢?嗯,这是有道理的,因为训练集中的任何东西都不会跟随它,因此没有下一个令牌发生冲突。另外,句首跟在句尾后面不是很自然吗?

【讨论】:

  • 是的,你说得有道理。我只是混淆了实现,但实际上,我们可以将“decoder_start_token_id”作为 BOS,这也是很自然的。但我认为这只是一种实现偏好。
  • 我认为它会在解码后的句子中连续生成两个 BOS 令牌。解码器最终会学会在第一个 BOS 之后放置第二个 BOS。它可以工作,但会混淆解码器。对我来说,使用未修改的标记作为输入并预测左移版本似乎更自然:BOS 永远不会出现在另一个标记之后。
猜你喜欢
  • 1970-01-01
  • 2023-03-07
  • 2019-06-09
  • 2011-03-01
  • 2013-12-03
  • 2011-08-27
  • 2020-11-08
  • 2010-10-02
相关资源
最近更新 更多