填充和注意掩码在 GPT 语言模型的批量输入中无法按预期工作

Posted

技术标签:

【中文标题】填充和注意掩码在 GPT 语言模型的批量输入中无法按预期工作【英文标题】:padding and attention mask does not work as intended in batch input in GPT language model 【发布时间】:2020-06-20 02:10:57 【问题描述】:

以下代码无批处理:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()
context=torch.tensor([tokenizer.encode("This is")])
output, past = model(context)
token = torch.argmax(output[..., -1, :])
print(tokenizer.decode(token.item()))

output: ' a'

这工作正常。现在,我将其扩展到批处理设置:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch

tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()

context=[torch.tensor(tokenizer.encode("This is ")),torch.tensor(tokenizer.encode("Hello How are "))]
context=pad_sequence(context,batch_first=True)

mask=torch.tensor([[1,1,0],[1,1,1]])
output, past = model(context,attention_mask=mask)
token = torch.argmax(output[..., -1, :],dim=1)
tokenizer.decode(token)

output: '\n you'

这里\n 是第一个上下文的下一个标记,you 是批处理的第二个上下文的下一个标记。 但是第一个上下文的预期下一个令牌是a,因为所有设置都是相同的。此外,如果您将第二个上下文减少到 2 个令牌,您将在此批处理设置中获得 a。很明显,模型无法理解填充。 此外,注意面具不起作用。因为, 填充序列this is 的下一个标记后为0(零)。并且根据注意掩码 ([1,1,0]),应该避免这个零,并且应该只关注标记 thisis。这种注意力屏​​蔽不起作用的证据是:

使用注意掩码 [1,1,1],这意味着即使在填充零上也要注意,你会得到相同的输出 这是\n

使用字符串this is!。这里! 在词汇矩阵中的索引为零。你再次得到相同的输出,即\n

只有在没有批处理设置和注意掩码的情况下,才有可能获得理想的输出(现在看来,这并不重要,因为它无论如何都没有效果)

然后找到this,提示使用pad_token。所以我使用如下:

from transformers import GPT2LMHeadModel, GPT2Tokenizer
import torch
from torch.nn.utils.rnn import pad_sequence  

tokenizer = GPT2Tokenizer.from_pretrained("gpt2",pad_token="<PAD>")
model = GPT2LMHeadModel.from_pretrained('gpt2')
model.eval()

context=[torch.tensor(tokenizer.encode("This is <PAD> ")),torch.tensor(tokenizer.encode("Hello How are"))]
context=torch.stack(context)
print(context)
mask=torch.tensor([[1,1,0],[1,1,1]])

output, past = model(context,attention_mask=mask)
token = torch.argmax(output[..., -1, :],dim=1)
tokenizer.decode(token)

output: 'The you'

这里The 是第一个上下文的下一个标记,you 是批处理的第二个上下文的下一个标记。这也行不通。因为The 不希望用于第一个上下文。

如何在gpt/gpt2模型的批量设置中使用变长序列?

【问题讨论】:

【参考方案1】:

我不确定这是否有帮助,但您不需要实现自己的注意力屏蔽和填充。 Transformers 库提供了 encode_plus() 和 batch_encode_plus() 函数,它们将执行标记化、生成注意掩码并为您进行填充。结果以 Python 字典的形式出现。

【讨论】:

以上是关于填充和注意掩码在 GPT 语言模型的批量输入中无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

一文看懂多模态大型语言模型GPT-4

预训练语言模型整理(ELMo/GPT/BERT...)

使用drawRect的Createjs掩码在Safari中不起作用

如何使用布尔掩码在 pandas DataFrame 中用 nan 替换“任何字符串”?

Unity ui 掩码在谷歌像素设备上不起作用

ChatGPT基础知识系列之Prompt