为什么 Huggingface t5 分词器会忽略一些空格?

Ber*_*abi 7 huggingface-transformers huggingface-tokenizers sentencepiece

我正在使用 T5 模型和分词器来执行下游任务。我想向标记生成器添加某些空格,例如行结尾(\\t)和制表符(\\t)。添加这些标记可以工作,但不知何故标记器总是忽略第二个空格。因此,它将序列标记\xe2\x80\x9c\\n\\n\xe2\x80\x9d为单行结尾,并将序列"\\n\\n\\n\\n"标记为两个行结尾,依此类推。请参阅下文进行重现。

\n
from transformers import T5Tokenizer\ntokenizer = T5Tokenizer.from_pretrained("t5-large")\ntokenizer.add_tokens(["\\n"])\n\ntokenizer.encode("\\n") # returns [32100, 1] as expected\ntokenizer.encode("\\n\\n") # returns [32100, 1] but expected would be [32100, 32100, 1]\ntokenizer.encode("\\n\\n\\n\\n") # returns [32100, 32100, 1] but expected would be [32100, 32100, 32100, 32100, 1]\n
Run Code Online (Sandbox Code Playgroud)\n

这种行为背后的原因是什么?这是一个错误还是与分词器工作原理相关的东西?我注意到这只发生在添加的空格上,而不会发生在其他字符上。

\n

有没有办法防止分词器忽略重复的空格?

\n

Ber*_*abi 4

tokenize该行为通过默认情况下如何剥离标记的方法来解释T5Tokenizer。我们可以做的是将标记“ \n”作为特殊标记添加到标记生成器中。因为特殊令牌永远不会分离,所以它会按预期工作。

这有点hacky但似乎有效。

from tokenizers import AddedToken
tokenizer.add_special_tokens({"additional_special_tokens": [AddedToken("\n")]})
print(tokenizer.special_tokens_map)
Run Code Online (Sandbox Code Playgroud)

然后它会'\n'在不跳过任何事件的情况下对 进行标记。请注意,AddedToken 很重要,因为不知何故以下内容不起作用

tokenizer.add_special_tokens({"additional_special_tokens": ["\n"]})
Run Code Online (Sandbox Code Playgroud)

编辑

在花了更多时间之后,我实际上找到了一种将其添加为普通令牌而不使用特殊令牌的方法。问题的主要原因是在标记化之前就在幕后发生的标准化过程。添加新标记时,您可以指定是否应对其进行标准化。通过将 Normalize 设置为 False,可以避免标记生成器删除连续出现的添加标记。

from tokenizers import AddedToken
tokenizer.add_tokens(AddedToken("\n", normalized=False))
Run Code Online (Sandbox Code Playgroud)

您可以在此链接上找到更多信息:https://huggingface.co/course/en/chapter6/4 ?fw=pt