估计给定句子的标记概率/逻辑,而不计算整个句子

Jac*_*sac 5 python nlp huggingface-transformers

我有这样一句话 "I like sitting in my new chair and _____ about life"

我有一组特定的令牌,例如["watch", "run", "think", "apple", "light"]

我想计算每个标记作为该不完整句子中的下一个单词出现的概率。希望我应该知道 的概率"think"高于"apple"例如。

我正在使用 pytorch-transformers (特别是 GPT2LMHeadModel),一个可能的解决方案是评估每个标记的完整句子的分数,但是当要评估的标记数量约为 100 或 1000 时,计算时间开始太长了。

必须可以仅处理该句子一次,并以某种方式使用隐藏状态来计算标记集的概率,但我不知道该怎么做。

有任何想法吗?提前致谢


编辑:

实际代码如下所示(每次估计完整句子的概率)。对于每个句子,运行该score()方法大约需要 0.1 秒,如果我想评估数千个单词,则需要几个小时。

from pytorch_transformers import GPT2Tokenizer, GPT2LMHeadModel
import pandas as pd

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


def score(sentence):
    tokenize_input = tokenizer.tokenize(sentence)
    tensor_input = torch.tensor([tokenizer.convert_tokens_to_ids(tokenize_input)])
    loss = model(tensor_input, labels=tensor_input)
    return -loss[0].item()


candidates = ["watch", "run", "think", "apple", "light"]
sent_template = "I like sitting in my new chair and {} about life"
print({candidate: score(sent_template.format(candidate)) for candidate in candidates})
Run Code Online (Sandbox Code Playgroud)

cro*_*oik 4

您的示例产生了以下输出,并在我的环境中花费了大约 48.5 秒的时间(有 282 个候选者)完成(我只进行了 3 次运行):

{'watch': -5.406847953796387
, 'run': -5.533411502838135
, 'think': -4.525279521942139
, 'apple': -6.158637046813965
, 'light': -5.835141658782959}
Run Code Online (Sandbox Code Playgroud)

正如评论中提到的,我认为您可以使用过去的参数和快速分词器来节省一些计算,如下面的评论示例所示:

{'watch': -5.406847953796387
, 'run': -5.533411502838135
, 'think': -4.525279521942139
, 'apple': -6.158637046813965
, 'light': -5.835141658782959}
Run Code Online (Sandbox Code Playgroud)

输出:

{'watch': -5.406846046447754
, 'run': -5.533413887023926
, 'think': -4.525280952453613
, 'apple': -6.158637046813965
, 'light': -5.835141181945801}
Run Code Online (Sandbox Code Playgroud)

这里的运行时间为 40.5 秒,有 282 个候选者(又是 3 个周期)。您还看到我失去了一些精确度。

非常感谢patrickvonplaten,他给了我关于过去实现的很好的解释。