HuggingFace使用小写词表分词时如何保留原文本大小写Token
问题描述
使用HuggingFace加载本地全小写Bert词表执行文本分词任务时,存在参数逻辑冲突:
- 设置
lowercase=False时,含大写字符的词汇无法匹配小写词表,会被标记为[UNK]
复现代码及输出:vocab_path = '....' ## 本地词表存储路径 tokenizer = BertWordPieceTokenizer(os.path.join(vocab_path, "vocab.txt"), lowercase=False) text = 'The Quick Brown fox' output = tokenizer.encode(text) output.tokens # 运行结果: ['[CLS]', '[UNK]', '[UNK]', '[UNK]', 'fox', '[SEP]'] - 设置
lowercase=True时,词表可以正常匹配所有词汇,但输出token会被统一转为小写,丢失原文本的大小写格式
对应输出:tokenizer = BertWordPieceTokenizer(os.path.join(vocab_path, "vocab.txt"), lowercase=True) output = tokenizer.encode(text) output.tokens # 运行结果: ['[CLS]', 'the', 'quick', 'brown', 'fox', '[SEP]'] - 目标输出:在不修改现有全小写词表的前提下,得到保留原文本大小写的分词结果:
['[CLS]', 'The', 'Quick', 'Brown', 'fox', '[SEP]']
实现方法
不需要修改词表,也不需要改动分词器底层逻辑,利用分词器返回的偏移量映射即可实现:
- 初始化分词器时保持
lowercase=True,确保分词逻辑可以正确匹配全小写词表,BertWordPieceTokenizer默认会返回切分位置的偏移量字段 - 遍历分词结果,特殊标记直接保留,普通token根据偏移量从原始输入文本中截取对应位置的字符串,替换分词器返回的小写结果即可
可直接运行的参考代码:
import os from tokenizers import BertWordPieceTokenizer vocab_path = '....' # 替换为本地词表实际存储路径 tokenizer = BertWordPieceTokenizer( os.path.join(vocab_path, "vocab.txt"), lowercase=True ) text = 'The Quick Brown fox' output = tokenizer.encode(text) final_tokens = [] for token, (start_idx, end_idx) in zip(output.tokens, output.offsets): # 特殊token直接保留,普通token从原文本截取对应片段保留原始大小写 if token in {"[CLS]", "[SEP]", "[PAD]", "[UNK]", "[MASK]"}: final_tokens.append(token) else: final_tokens.append(text[start_idx:end_idx]) print(final_tokens) # 输出: ['[CLS]', 'The', 'Quick', 'Brown', 'fox', '[SEP]']
说明:分词器的偏移量是基于原始输入文本计算的切分边界,和内部是否做小写转换无关,切分位置完全准确,不会出现错位问题,分词匹配逻辑和原生
lowercase=True的效果完全一致,仅替换输出的文本形式。
内容的提问来源于stack exchange,提问作者palash
相关产品推荐
相关产品推荐

