You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按频率重排GPT2Tokenizer Token ID引发未识别Token问题排查

问题:重排GPT2Tokenizer Token ID后部分Token无法识别

我尝试通过按频率重排现有GPT2Tokenizer的Token ID创建新分词器,理论上Token ID顺序不影响性能和可用性,但实际出现部分Token无法识别的情况。因特定需求必须采用该方式,附上相关代码及输出,询问问题成因。


原分词器测试代码及输出

top_amt = 10000
old_tokenizer = GPT2Tokenizer.from_pretrained("EleutherAI/gpt-neo-125M")
inputs = old_tokenizer("Hello, my dog is cute", return_tensors="pt")
print("input ids: ", inputs['input_ids'])

输出:

input ids:  tensor([[15496,    11,   616,  3290,   318, 13779]])

词频统计与Token重排代码及输出

# 统计词频
tokens_to_id = dict(list(tokenizer.get_vocab().items()))

# 获取频率
frequencies = np.zeros(len(tokens_to_id))
for i, sample in enumerate(tokenized_val['input_ids']):
  for token in sample:
    frequencies[token] += 1

# 排序
sorted_indices = np.argsort(frequencies)[::-1]
#toptenk = sorted_indices[:top_amt]
print("Top 10 tokens: ", tokenizer.decode(toptenk[:10]))

# 去重并重分配ID
top_tokens = {tokenizer.decode([sorted_indices[i]]):i for i in range(len(sorted_indices))}
top_keys = list(top_tokens.keys())
top_tokens = {top_keys[i]: i for i in range(len(top_keys))}
print("Occurrences of least used token: ", top_keys[top_amt], frequencies[top_tokens[top_keys[top_amt]]])

输出:

Top 10 tokens:  <|endoftext|>.
 and the, to a was it
Occurrences of least used token:   Often 477.0

新分词器创建与测试代码及输出

vocab_file_path = 'reduced_vocab.json'
with open(vocab_file_path, 'w') as f:
    f.write(json.dumps(top_tokens))

print(f"Reduced vocabulary file saved to {vocab_file_path}")
new_tokenizer = GPT2Tokenizer(vocab_file=vocab_file_path, merges_file="merges.txt", pad_token='<|endoftext|>')
new_tokenizer.save_pretrained("TinyStoriesTokenizer")
print("Tokenizer saved.")
inputs = new_tokenizer("Hello, my dog is cute", return_tensors="pt")
print("input ids: ", inputs['input_ids'])

输出:

Reduced vocabulary file saved to reduced_vocab.json
Tokenizer saved.
input ids:  tensor([[564,   5,   0,   0,   0,   0]])

问题成因分析

1. BPE合并规则与新词汇表不匹配

GPT2系列分词器基于Byte-Pair Encoding(BPE),其merges.txt文件记录了BPE的合并步骤,这些步骤是和原分词器的Token ID直接绑定的。当你重排Token ID后,原merges.txt中的合并规则指向的是旧ID,与新词汇表的ID完全不对应,导致分词器无法按照正确的路径合并出"my"、"dog"这类Token,只能尝试拆分到更低层级的单元,甚至无法匹配到有效Token。

2. 词汇表构建时的去重操作导致Token丢失

你在构建top_tokens时,先通过{tokenizer.decode([sorted_indices[i]]):i}生成字典,再通过{top_keys[i]: i}去重。但部分Token解码后可能出现重复的字符串(比如某些控制字符、特殊编码的Token),去重会直接覆盖掉重复键对应的ID,导致这些Token在新词汇表中丢失。当分词时遇到对应序列,无法找到匹配的Token,最终输出0(GPT2Tokenizer默认无unk_token,会将无法匹配的内容映射到无效ID或默认值)。

3. 特殊Token的处理冲突

你将<|endoftext|>设为pad_token,但在重排Token ID时,该Token的ID被改变,而原merges.txt中可能包含与该特殊Token相关的合并规则,进一步加剧了分词逻辑的混乱,导致部分常规Token的合并路径完全失效。

内容的提问来源于stack exchange,提问作者Cade Harger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:10:00