T5的Slow与Fast分词器输出不一致问题求助(SentencePiece分词)
问题解决:普通T5分词器拆分特殊token
</s>的处理方案 问题现象
使用T5TokenizerFast分词时,特殊token如</s>能被正确识别为单个token,输出符合预期:
['▁', '</s>', '▁Hello', '▁', '<sep>', '</s>']
但使用普通PreTrainedTokenizer(非Fast版本)时,</s>被拆分为多个子token:
['▁</', 's', '>', '▁Hello', '<sep>', '</s>']
核心原因
T5TokenizerFast基于SentencePiece的快速实现,会自动优先匹配词汇表中的完整特殊token;而普通T5分词器默认不会将</s>这类符号序列视为不可拆分的特殊单元,除非明确将其注册为特殊token。
解决方案
要让普通分词器正确识别</s>为单个token,需将其注册为不可拆分的特殊token,而不仅仅是添加普通token。具体操作如下:
步骤1:正确注册特殊token
初始化普通分词器时,通过add_special_tokens方法将</s>标记为EOS token,并将自定义的<sep>加入additional_special_tokens(确保也不被拆分):
from transformers import T5Tokenizer # 初始化普通T5分词器 tokenizer = T5Tokenizer('new_sp.model', extra_ids=0) # 注册特殊token,确保</s>和<sep>被视为整体 tokenizer.add_special_tokens({ 'eos_token': '</s>', 'additional_special_tokens': ['<sep>'] }) # 测试分词结果 print(tokenizer.convert_ids_to_tokens(tokenizer.encode("</s> Hello <sep>")))
步骤2:验证词汇表
如果自定义的new_sp.model中未包含</s>和<sep>作为单个token,需先将这些token添加到词汇表,再注册为特殊token:
# 先添加token到词汇表 tokenizer.add_tokens(['</s>', '<sep>']) # 再注册为特殊token tokenizer.add_special_tokens({ 'eos_token': '</s>', 'additional_special_tokens': ['<sep>'] })
验证结果
执行上述代码后,普通分词器的输出会和Fast版本一致,</s>和<sep>都会被识别为单个token,不会被拆分。
内容的提问来源于stack exchange,提问作者canP
相关产品推荐
相关产品推荐

