HuggingFace transformers AutoTokenizer分词出现额外#字符问题咨询
问题成因
你观测到的带##前缀的拆分结果是BERT类分词器WordPiece子词分词策略的正常输出,不属于程序异常:
- BERT系列模型预训练阶段使用固定容量的词表,无法覆盖所有专有名词、缩写、生僻组合词,因此设计了子词拆分逻辑:不在内置词表的单词会被拆分为多个在词表中存在的子词,非首段的子词会添加
##前缀作为标识,方便模型识别该子词属于原单词的后缀部分。你测试文本中的CTO、TLR、Pty都属于不在预训练词表的专有名词,所以会被拆分为CT+##O、T+##LR、P+##ty,只要你使用的是BERT架构的分词器,都会出现相同表现,这是预训练阶段就确定的分词规则。 - 你当前使用的代码存在冗余无效操作:
tokenizer.tokenize(tokenizer.decode(tokenizer.encode(sequence)))这段逻辑完全重复:tokenizer.encode已经完成了文本到token id的转换,你又通过decode将id转回文本,再调用tokenize重新分词,属于无效操作,直接调用tokens = tokenizer.tokenize(sequence)即可得到相同的分词结果。
解决方案
根据你的使用场景选择对应处理方式:
- 如果你只是需要将拆分后的tokens还原为原文本,直接调用分词器自带的
convert_tokens_to_string方法即可,该方法会自动去除##标识,将子词拼接回完整单词,示例代码:
from transformers import AutoTokenizer tokenizer = AutoTokenizer.from_pretrained("tokenizer_bert.json") sequence = "CTO at TLR Communications Pty Ltd" tokens = tokenizer.tokenize(sequence) # 还原为原输入文本 original_text = tokenizer.convert_tokens_to_string(tokens)
- 如果你必须获取无拆分的完整单词分词结果,不建议强行修改BERT类分词器的拆分逻辑:BERT预训练时就是使用子词拆分的数据训练的,强行关闭子词拆分,会将所有词表外的单词替换为
[UNK]未知标识,严重降低模型推理效果。 - 如果你不需要依赖BERT架构的模型,只是需要无拆分的分词结果,可以换用基于完整词表的英文分词器,比如spaCy即可。
内容的提问来源于stack exchange,提问作者Ciaran
相关产品推荐
相关产品推荐

