【问题标题】:How to predict the probability of an empty string using BERT如何使用 BERT 预测空字符串的概率
【发布时间】:2022-01-26 18:19:20
【问题描述】:

假设我们有一个这样的模板语句:

  • “____ 家是我们的聚会场所。”

我们有一个形容词列表来填空,例如:

  • “黄色”
  • “大”
  • ""

请注意,其中一个是空字符串。

目标是在给定句子上下文的情况下比较概率以选择最有可能描述“房子”的词。如果它更有可能什么都没有,也应该考虑到这一点。

我们可以预测每个单词填空的概率,但是我们如何预测没有形容词来描述“房子”的概率呢?

预测一个单词的概率:

from transformers import BertTokenizer, BertForMaskedLM
import torch
from torch.nn import functional as F

# Load BERT tokenizer and pre-trained model
tokenizer = BertTokenizer.from_pretrained('bert-large-uncased')
model = BertForMaskedLM.from_pretrained('bert-large-uncased', return_dict=True)

targets = ["yellow", "large"]
sentence = "The [MASK] house is our meeting place."

# Using BERT, compute probability over its entire vocabulary, returning logits
input = tokenizer.encode_plus(sentence, return_tensors = "pt") 
mask_index = torch.where(input["input_ids"][0] == tokenizer.mask_token_id)[0] 
with torch.no_grad():
    output = model(**input) 

# Run softmax over the logits to get the probabilities
softmax = F.softmax(output.logits[0], dim=-1)

# Find the words' probabilities in this probability distribution
target_probabilities = {t: softmax[mask_index, tokenizer.vocab[t]].numpy()[0] for t in targets}
target_probabilities

这会输出单词列表及其相关概率:

{'yellow': 0.0061520976, 'large': 0.00071377633}

如果我尝试向列表中添加一个空字符串,我会收到以下错误:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-62-6f726220a108> in <module>
     18 
     19 # Find the words' probabilities in this probability distribution
---> 20 target_probabilities = {t: softmax[mask_index, tokenizer.vocab[t]].numpy()[0] for t in targets}
     21 target_probabilities

<ipython-input-62-6f726220a108> in <dictcomp>(.0)
     18 
     19 # Find the words' probabilities in this probability distribution
---> 20 target_probabilities = {t: softmax[mask_index, tokenizer.vocab[t]].numpy()[0] for t in targets}
     21 target_probabilities

KeyError: ''

这是因为 BERT 的词汇表中不包含空字符串,所以我们无法查找模型中不存在的东西的概率。

我们应该如何获得没有单词可以填空的概率?模型可以做到这一点吗?使用空标记 [PAD] 而不是空字符串有意义吗? (我只见过[PAD]用在句尾,使一组句子的长度相同。)

【问题讨论】:

    标签: python nlp huggingface-transformers bert-language-model


    【解决方案1】:

    解决这个问题的一种方法是通过添加每个标记的 log-softmax 来比较句子分数。

    首先,我应该说,当您对它们使用 softmax 时,BERT 中的 logits 分数并不是真正的概率。但这似乎是一种可以接受的方法。所以,我也会使用它。

    其次,您还应该考虑形容词有多个标记的情况。我的解决方案还解决了多个令牌的问题。

    这里是代码修复:

    targets = ["", "yellow", "large", "very large"]
    target_log_P = {t: None for t in targets}
    for target in target_log_P:
         input = tokenizer.encode_plus(sentence.replace("[MASK]", target), return_tensors = "pt")
         output = model(**input)
         target_log_P[target] = sum([
             torch.log(F.softmax(output.logits[0][i], dim=-1)[idx])
             for i, idx in enumerate(input['input_ids'][0])
         ]).item()
    

    也许有一个管道,我在这里的解决方案不是标准方式,但它似乎工作......

    结果如下:

    >>> target_log_P
    {'': -37.5234375, 'yellow': -37.08171463012695, 'large': -35.85972213745117, 'very large': -46.483154296875}
    

    【讨论】:

    • 谢谢!我有一个问题,当我多看这个解决方案时,你认为为多词目标中的每个词应用一个掩码而不是一个掩码更有意义吗?
    • 我试图通过在词汇表中搜索其 softmax-normalized logit 来查找模型看不到目标词的“概率”,但是这个解决方案将目标词暴露给直接在句子中使用它来建模。我不确定这是否可行
    • 问题是 bert 在双向设置中报告令牌分数。更改一个标记会从左到右更改所有其他标记的上下文。仅更改一个掩码可能会起作用,但更改掩码的长度也会更改所有其他单词在其右侧的位置,因此当您仅检查被掩码部分的分数时,情况会更加糟糕。无论如何,在这个解决方案中,您仍然需要在字典中搜索并为每个条目分配分数。但分数代表了该词汇选择的总体结果。
    • 我刚刚发现了这个关于拥抱脸的相关讨论,关于实施class transformers.FillMaskPipeline:github.com/huggingface/transformers/pull/10222
    猜你喜欢
    • 2020-04-03
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 2019-09-16
    • 1970-01-01
    • 2013-02-04
    相关资源
    最近更新 更多