如何取消 BERT 代币的代币化?

Jay*_*Jay 6 python tokenize bert-language-model huggingface-transformers huggingface-tokenizers

我有一个句子,我需要返回特定单词左右两侧 N 个 BERT 标记对应的文本。

from transformers import BertTokenizer
tz = BertTokenizer.from_pretrained("bert-base-cased")
sentence = "The Natural Science Museum of Madrid shows the RECONSTRUCTION of a dinosaur"

tokens = tz.tokenize(sentence)
print(tokens)

>>['The', 'Natural', 'Science', 'Museum', 'of', 'Madrid', 'shows', 'the', 'R', '##EC', '##ON', '##ST', '##R', '##UC', '##TI', '##ON', 'of', 'a', 'dinosaur']
Run Code Online (Sandbox Code Playgroud)

我想要的是获取与令牌马德里左侧和右侧的4个令牌相对应的文本。所以我想要标记: ['Natural', 'Science', 'Museum', 'of', 'Madrid', 'shows', 'the', 'R', '##EC'] 然后将它们转换为原文。在本例中,它将是“马德里自然科学博物馆展示 REC”。

有没有办法做到这一点?

cro*_*oik 11

除了Jindrich提供的有关信息丢失的信息之外,我想补充一点,huggingface 提供了一个内置方法来将令牌转换为字符串(丢失的信息仍然丢失!)。该方法称为convert_tokens_to_string

tz.convert_tokens_to_string(tokens[1:10])
Run Code Online (Sandbox Code Playgroud)

输出:

'Natural Science Museum of Madrid shows the REC'
Run Code Online (Sandbox Code Playgroud)


Jin*_*ich 5

不幸的是,BERT 使用的单词片段标记化并不是无损的,即,永远不能保证在去标记化后得到相同的句子。这与使用完全可恢复的 SentencePiece 的 RoBERTa 有很大区别。

您可以获得所谓的预标记化文本,其中合并以 开头的标记##

pretok_sent = ""
for tok in tokens:
     if tok.startswith("##"):
         pretok_sent += tok[2:]
     else:
         pretok_sent += " " + tok
pretok_sent = pretok_sent[1:]
Run Code Online (Sandbox Code Playgroud)

此代码片段重建了示例中的句子,但请注意,如果句子包含标点符号,则标点符号将与其他标记保持分离,这就是预标记化。该句子可以如下所示:

'This is a sentence ( with brackets ) .'
Run Code Online (Sandbox Code Playgroud)

从预标记化到标准句子是有损步骤(您永远无法知道原始句子中是否存在以及有多少额外空格)。您可以通过应用去标记化规则来获得标准句子,例如在sacremoses中。

import sacremoses
detok = sacremoses.MosesDetokenizer('en')
detok(sent.split(" "))
Run Code Online (Sandbox Code Playgroud)

这导致:

'This is a sentence (with brackets).'
Run Code Online (Sandbox Code Playgroud)