自定义特殊标记[SP][EMPTY]未被Bert分词器识别的技术问题
解决BertWordPieceTokenizer训练的特殊标记被BertTokenizer识别为[UNK]的问题
问题根源
你遇到的问题有两个核心原因:
- 用
tokenizers库训练时虽然把[SP]、[EMPTY]加入了词汇表,但transformers的BertTokenizer加载单独的vocab.txt文件时,不会自动把这些自定义标记注册为特殊标记,只会默认识别官方的那几个,所以自定义标记会被当成未知字符输出[UNK]。 - 你输入句子里的
[CLS]、[SEP]被当成了普通文本,tokenizer把它们拆成了转义后的\[CLS\],而不是识别为特殊标记。
两种解决办法
办法1:加载时手动指定特殊标记
在创建BertTokenizer的时候,通过additional_special_tokens参数把自定义标记传进去,同时同步训练时的配置(比如do_lower_case=False):
from tokenizers import BertWordPieceTokenizer from transformers import BertTokenizer vocab_size=50_000 path = '/content/drive/MyDrive/text.txt' # 训练tokenizer special_tokens = ['[PAD]', '[UNK]', '[CLS]', '[SEP]', '[MASK]', '[SP]', '[EMPTY]'] tokenizer = BertWordPieceTokenizer(clean_text=True, handle_chinese_chars=False, strip_accents=False, lowercase=False) tokenizer.train(files=path, vocab_size=vocab_size, min_frequency=5, limit_alphabet=1000, wordpieces_prefix='##', special_tokens=special_tokens) tokenizer.save_model('/content/drive/MyDrive/', 'new') # 加载时手动传入自定义特殊标记 tokenizer = BertTokenizer.from_pretrained( '/content/drive/MyDrive/new-vocab.txt', additional_special_tokens=['[SP]', '[EMPTY]'], do_lower_case=False, strip_accents=False ) # 正确使用特殊标记:用tokenizer的属性,不要直接写字符串 sen = f"{tokenizer.cls_token} تم اجتياز الامتحان بنجاح {tokenizer.additional_special_tokens[0]} {tokenizer.additional_special_tokens[1]} {tokenizer.sep_token}" print(tokenizer.tokenize(sen))
办法2:保存完整tokenizer配置(更省心)
不要只存词汇表,直接保存tokenizers训练好的完整tokenizer文件,再用transformers的BertTokenizerFast加载,这样会自动保留所有配置,包括特殊标记:
from tokenizers import BertWordPieceTokenizer from transformers import BertTokenizerFast vocab_size=50_000 path = '/content/drive/MyDrive/text.txt' # 训练tokenizer special_tokens = ['[PAD]', '[UNK]', '[CLS]', '[SEP]', '[MASK]', '[SP]', '[EMPTY]'] tokenizer = BertWordPieceTokenizer(clean_text=True, handle_chinese_chars=False, strip_accents=False, lowercase=False) tokenizer.train(files=path, vocab_size=vocab_size, min_frequency=5, limit_alphabet=1000, wordpieces_prefix='##', special_tokens=special_tokens) # 保存完整的tokenizer配置文件 tokenizer.save('/content/drive/MyDrive/new_tokenizer.json') # 直接加载完整配置 tokenizer = BertTokenizerFast.from_pretrained('/content/drive/MyDrive/new_tokenizer.json') # 用tokenizer属性构建句子,避免转义问题 sen = f"{tokenizer.cls_token} تم اجتياز الامتحان بنجاح {tokenizer.additional_special_tokens[0]} {tokenizer.additional_special_tokens[1]} {tokenizer.sep_token}" print(tokenizer.tokenize(sen))
重要提醒
别直接在输入句子里写[CLS]这种字符串,要用tokenizer自带的属性(比如tokenizer.cls_token),这样才能保证被识别成特殊标记,不会被转义拆分。
内容的提问来源于stack exchange,提问作者FQ912
相关产品推荐
相关产品推荐

