【问题标题】:BERT embeddings in batchesBERT 批量嵌入
【发布时间】:2021-05-06 20:24:06
【问题描述】:

我正在关注this post提取句子的嵌入,对于单个句子,步骤描述如下:

    text = "After stealing money from the bank vault, the bank robber was seen " \
           "fishing on the Mississippi river bank."
    
    # Add the special tokens. 
    marked_text = "[CLS] " + text + " [SEP]"
    
    # Split the sentence into tokens. 
    tokenized_text = tokenizer.tokenize(marked_text)
    
    # Mark each of the 22 tokens as belonging to sentence "1". 
    segments_ids = [1] * len(tokenized_text)
    
    # Convert inputs to PyTorch tensors 
    tokens_tensor = torch.tensor([indexed_tokens]) 
    segments_tensors = torch.tensor([segments_ids])
    
    # Load pre-trained model (weights) 
    model = BertModel.from_pretrained('bert-base-uncased',
                                 output_hidden_states = True,
                                      )
    
    # Put the model in "evaluation" mode, meaning feed-forward operation. 
    model.eval()
    
    with torch.no_grad():
        outputs = model(tokens_tensor, segments_tensors)
        hidden_states = outputs[2]

我想为一批序列执行此操作。这是我的示例代码:

seql = ['this is an example', 'today was sunny and', 'today was']
encoded = [tokenizer.encode(seq, max_length=5, pad_to_max_length=True) for seq in seql]

encoded
[[2, 2511, 1840, 3251, 3], 
 [2, 1663, 2541, 1957, 3], 
 [2, 1663, 2541, 3, 0]]

但由于我使用的是批处理,因此序列需要具有相同的长度。所以我介绍了一个填充标记(第 3 句),它让我对以下几点感到困惑:

  • pad_token (0) 的段 id 应该是什么?

  • 在将张量提供给模型时是否应该使用注意力掩蔽以忽略填充?在示例中,仅使用了标记和分段张量。

    outputs = model(tokens_tensor, segments_tensors)
    
  • 如果我不使用批处理而是使用单个句子,那么我可能不需要填充标记。与批量相比,这样做会更好吗?

【问题讨论】:

    标签: pytorch bert-language-model


    【解决方案1】:

    您可以使用一个函数(填充、截断)完成所有需要的工作

    encode_plus

    查看参数:the docs

    你可以对序列列表做同样的事情

    batch_encode_plus

    docs

    【讨论】:

    • 我对使用 encode_plus 持怀疑态度,因为文档说它已被弃用。
    • Tonenizer 对象现在是一个可调用对象,默认情况下它表现为 encode_plus。如果您向标记器提供单个示例,它将表现为encode_plus,如果您提供一批示例,它将表现为batch_encode_plus。但它仍然是相同的行为。
    • 我测试了 ''tokenizer.batch_encode_plus(seql, max_length=5)'' 并没有填充较短的序列
    • 如果您查看文档填充默认为禁用,则必须在函数调用中将填充参数设置为 True。
    • 在您的情况下,您有一个固定的 max_length ,您需要的是: tokenizer.batch_encode_plus(seql, add_special_tokens=True, max_length=5, padding="max_length") 'max_length': 填充到最大值使用参数 max_length 指定的长度。 True 或 'longest':填充到批处理中最长的序列(如果仅提供单个序列,则不填充)。
    猜你喜欢
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 2015-09-26
    • 2021-01-16
    • 1970-01-01
    • 2020-12-08
    • 2020-10-27
    相关资源
    最近更新 更多