BPE Tokenizer 完整入门:从汉字编码到 GPT-2 风格 Byte-Level BPE
2026/5/16 8:00:21 网站建设 项目流程

BPE Tokenizer 完整入门:从汉字编码到 GPT-2 风格 Byte-Level BPE

主题:汉字如何进入 GPT-2 风格 tokenizer,BPE 的统计算法是什么,完整算例是什么,还有 BPE、WordPiece、Unigram、SentencePiece 等算法的区别,以及主流大模型是否还在使用 BPE。


0. 一句话总览

大模型不能直接吃人类文字,它只能处理整数 token id。

所以文本进入大模型前,要经过:

原始文本 ↓ 字符编码,例如 Unicode / UTF-8 ↓ tokenizer 切分 ↓ token id 序列 ↓ embedding 向量 ↓ Transformer

BPE tokenizer 的本质是:

用统计方法找出训练语料中最常一起出现的相邻片段,把它们合并成更大的 token,从而压缩文本长度。

GPT-2 风格 BPE 的特殊点是:

它不是直接从 Unicode 字符开始,而是先把文本转成 UTF-8 字节,然后对字节序列做 BPE 合并。


1. 汉字在计算机里先怎么表示?

1.1 Unicode:给每个字符一个编号

例如:

中 → Unicode 码点 U+4E2D 国 → Unicode 码点 U+56FD 人 → Unicode 码点 U+4EBA

Unicode 负责回答:

这个字符在全世界字符表里的编号是多少?

但 Unicode 码点还不是计算机真正存储的字节。


1.2 UTF-8:把 Unicode 码点变成字节

计算机最终存的是字节,即 8-bit 数据。

例如:

中 → U+4E2D → UTF-8: E4 B8 AD 国 → U+56FD → UTF-8: E5 9B BD

所以:

中国 → E4 B8 AD E5 9B BD

大部分常用汉字在 UTF-8 里是 3 个字节。

字符UnicodeUTF-8 字节字节数
AU+0041411
U+4E2DE4 B8 AD3
U+56FDE5 9B BD3
😂U+1F602F0 9F 98 824

2. GPT-2 风格 BPE 如何处理汉字?

GPT-2 风格 tokenizer 的链路是:

汉字文本 ↓ UTF-8 bytes ↓ byte-to-unicode 映射 ↓ BPE merge 合并 ↓ token 字符串 ↓ vocab 查询 ↓ token id

重点:

GPT-2 风格 BPE 看到的不是“中”这个汉字本身,而是“中”的 UTF-8 字节序列。


2.1 以“中”为例

中 ↓ Unicode U+4E2D ↓ UTF-8 E4 B8 AD

十进制就是:

E4 B8 AD = 228 184 173

GPT-2 tokenizer 会把每个 byte 映射成一个可打印的 Unicode 字符。

大致可以理解为:

0xE4 → ä 0xB8 → ¸ 0xAD → ľ

于是:

中 → E4 B8 AD → ä ¸ ľ → 举

注意:

举不是乱码,而是 GPT-2 byte-level tokenizer 的内部 byte 表示。


2.2 以“中国”为例

中 → E4 B8 AD 国 → E5 9B BD

所以:

中国 → E4 B8 AD E5 9B BD

经过 GPT-2 的 byte-to-unicode 映射,大致变成:

中国 → ä¸ľåĽ½

然后 BPE 会根据 merge 表决定是否合并:

ä + ¸ → ä¸ ä¸ + ľ → 举 # 可以表示“中” å + Ľ → åĽ åĽ + ½ → åĽ½ # 可以表示“国” 举 + åĽ½ → ä¸ľåĽ½ # 可以表示“中国”

如果训练语料里“中国”非常常见,最终可能合并成一个 token。

如果没有学到整个“中国”,可能拆成:

中国 → 中 / 国

如果中文语料很少,甚至可能拆得更碎:

中国 → E4 / B8 / AD / E5 / 9B / BD

3. tokenizer 的“学习”是不是统计?

是的。

BPE tokenizer 的学习主要是统计,不是语义理解。

它学的不是:

“中国”是什么意思? “苹果”是水果还是公司? “Transformer”是什么神经网络?

它学的是:

哪些相邻符号经常一起出现? 哪些片段值得合并成一个 token? 怎样用有限词表压缩训练语料?

所以 BPE tokenizer 更像一个统计压缩器。


4. BPE 算法的核心原理

BPE 全称 Byte Pair Encoding,字节对编码。

它最早是数据压缩算法,后来被用作 NLP 的子词切分算法。

核心规则非常简单:

1. 把文本拆成最小符号 2. 统计所有相邻符号 pair 的出现次数 3. 找到出现次数最高的 pair 4. 把这个 pair 合并成一个新符号 5. 更新语料 6. 重复,直到词表大小达到目标

一句话:

哪两个相邻片段最常一起出现,就先把它们合并。


5. BPE 的完整小白算例

为了让小白容易理解,先用英文字符演示。

假设训练语料是:

low lower lowest newer wider

我们先把每个词拆成字符:

low → l o w </w> lower → l o w e r </w> lowest → l o w e s t </w> newer → n e w e r </w> wider → w i d e r </w>

其中</w>表示词尾。

为什么要有词尾?

因为要区分:

low

和:

lower 里面的 low

词尾可以帮助 tokenizer 学到“某个片段在词尾出现”。


5.1 第 1 轮:统计相邻 pair

对每个词统计相邻符号。

例如:

low → l o w </w>

里面有:

(l, o) (o, w) (w, </w>)
lower → l o w e r </w>

里面有:

(l, o) (o, w) (w, e) (e, r) (r, </w>)

统计整个语料,假设得到:

pair次数
l o3
o w3
e r3
r </w>3
w e2
其他1

假设我们选择第一个最高频 pair:

l + o → lo

5.2 第 1 轮合并后的语料

low → lo w </w> lower → lo w e r </w> lowest → lo w e s t </w> newer → n e w e r </w> wider → w i d e r </w>

词表新增:

lo

5.3 第 2 轮:重新统计 pair

现在重新统计,可能最高频是:

lo + w → low

合并后:

low → low </w> lower → low e r </w> lowest → low e s t </w> newer → n e w e r </w> wider → w i d e r </w>

词表新增:

low

5.4 第 3 轮:继续统计

可能最高频是:

e + r → er

合并后:

low → low </w> lower → low er </w> lowest → low e s t </w> newer → n e w er </w> wider → w i d er </w>

词表新增:

er

5.5 继续重复

BPE 会一直重复:

统计 pair → 找最高频 → 合并 → 更新语料

直到达到目标词表大小。

最后词表里可能有:

l o w e r lo low er lower new wide ...

6. BPE 的数学表达

设训练语料中每个序列是:

sᵢ = [x₁, x₂, ..., xₘ]

每一轮统计所有相邻 pair:

count(a, b) = Σᵢ Σⱼ 1[(xⱼ, xⱼ₊₁) = (a, b)]

选择出现次数最多的 pair:

(a*, b*) = argmax count(a, b)

然后定义新符号:

c = a* b*

把所有:

a* b*

替换成:

c

这就是 BPE 的核心。


7. BPE 训练伪代码

deftrain_bpe(corpus,vocab_size):# 1. 初始切分:字符级或 byte 级corpus_symbols=split_to_initial_symbols(corpus)# 2. 初始词表vocab=set(all_symbols(corpus_symbols))# 3. 合并规则merges=[]whilelen(vocab)<vocab_size:pair_counts={}# 4. 统计所有相邻 pairforseqincorpus_symbols:fora,binzip(seq,seq[1:]):pair_counts[(a,b)]=pair_counts.get((a,b),0)+1# 5. 找最高频 pairbest_pair=max(pair_counts,key=pair_counts.get)# 6. 合并new_symbol=best_pair[0]+best_pair[1]merges.append(best_pair)vocab.add(new_symbol)# 7. 更新语料corpus_symbols=merge_pair(corpus_symbols,best_pair,new_symbol)returnvocab,merges

核心就三句话:

统计 pair 选最高频 pair 合并 pair

8. GPT-2 风格 Byte-Level BPE 的特殊流程

传统 BPE 可以从字符开始。

GPT-2 风格 BPE 从 byte 开始。

完整流程是:

原始文本 ↓ 正则预切分 ↓ UTF-8 bytes ↓ byte-to-unicode 映射 ↓ BPE pair 统计与合并 ↓ vocab.json + merges.txt

8.1 为什么要从 byte 开始?

因为任何文本都能变成 UTF-8 bytes。

所以 byte-level BPE 有一个巨大优点:

不会真正遇到 OOV,也就是不会出现“这个字符完全无法编码”。

中文、日文、韩文、emoji、生僻字、特殊符号、乱码,都能编码。


8.2 GPT-2 风格 BPE 的两个文件

训练完成后,通常得到两个核心文件:

vocab.json merges.txt

其中:

vocab.json:token 字符串 → token id merges.txt:BPE 合并规则和优先级

推理时不再统计,而是直接用merges.txt里的合并顺序。


9. GPT-2 风格 BPE 推理时如何编码?

训练阶段:

统计语料 → 学 vocab 和 merges

推理阶段:

输入文本 → 按已有 merges 合并 → 查 vocab → token id

假设 merge rank 是:

(ä, ¸) rank 100 (ä¸, ľ) rank 101 (å, Ľ) rank 200 (åĽ, ½) rank 201 (举, åĽ½) rank 5000

输入:

中国

先变成:

ä ¸ ľ å Ľ ½

按 merge rank 合并:

ä ¸ ľ å Ľ ½ → ä¸ ľ å Ľ ½ → 举 å Ľ ½ → 举 åĽ ½ → 举 åĽ½ → ä¸ľåĽ½

最后查词表:

ä¸ľåĽ½ → token_id

如果词表里没有“中国”这个整体 token,就会停在更小的粒度:

举 / åĽ½

也就是:

中 / 国

10. 中文在 BPE 中为什么可能被切碎?

原因不是中文本身不能被 BPE 表示,而是训练语料决定合并规则。

如果训练语料主要是英文,那么英文片段会被大量合并:

transform attention function return

中文片段出现较少,就不一定能合并成较大的 token。

于是中文可能更碎:

我正在学习Transformer

可能被切成:

我 / 正 / 在 / 学 / 习 / Transformer

也可能更碎到 byte 级。

因此,一个 tokenizer 对中文是否友好,取决于:

1. 中文语料占比 2. 词表大小 3. 是否 byte-level 或 byte fallback 4. 是否专门优化中日韩文本 5. 是否优化代码、数学、Markdown 等结构文本

11. BPE 的优点和缺点

11.1 优点

优点解释
简单算法就是统计 pair + 贪心合并
训练和推理都容易优化
稳定编码确定性强
可逆byte-level BPE 可以 lossless decode
无 OOVbyte-level BPE 可以表示任意文本
压缩有效高频片段会变成短 token 序列

11.2 缺点

缺点解释
贪心每一步只看局部最高频 pair,不保证全局最优
不懂语义合并依据是频率,不是语义
对语料敏感训练语料偏英文,中文就可能碎
词表浪费高频但无语义价值的片段也可能进词表
多语言公平性问题不同语言 token 压缩率可能差别很大

12. 有没有比 BPE 更好的算法?

有。

主流替代方案包括:

WordPiece Unigram Language Model SentencePiece byte fallback / hybrid tokenizer 直接 byte-level language model

13. WordPiece:比 BPE 更关注“组合价值”

WordPiece 是 BERT 系列常用的 tokenizer。

BPE 主要看:

哪个 pair 出现次数最多?

WordPiece 更关心:

合并这个 pair 后,是否能更好解释语料?

一种直观分数可以写成:

score(a, b) = freq(a, b) / (freq(a) × freq(b))

这个分数表达的是:

a 和 b 是不是强绑定?还是只是因为 a、b 各自都太常见,所以碰巧一起出现很多?

例如:

New York

如果NewYork经常强绑定,那么 WordPiece 倾向于把它们看作更有价值的组合。

BPE 更像:

出现次数多就合并

WordPiece 更像:

绑定关系强、对建模有收益才合并

14. Unigram LM:更像真正的概率模型

Unigram Language Model 是 SentencePiece 中常用的一类算法。

它和 BPE 的方向相反。

BPE 是:

从小词表开始,不断合并,词表变大

Unigram LM 是:

先准备一个很大的候选词表,然后删除贡献小的 token,词表变小

14.1 Unigram LM 如何理解?

比如:

人工智能

可以有很多切法:

人工 / 智能 人 / 工 / 智 / 能 人工智能 人工 / 智 / 能

Unigram LM 给每个 token 一个概率:

P(人工) P(智能) P(人工智能) P(人) P(工) ...

一句话的概率是所有切分路径概率的总和或最优路径概率近似。

训练目标是:

让整个训练语料的概率最大

然后删除那些对语料概率贡献小的 token。


14.2 Unigram LM 的优点

优点解释
概率化比 BPE 的贪心频率更接近统计建模
多切分路径可以考虑一句话的多种切法
适合多语言尤其适合中文、日文这种无空格语言
可用于采样可以做 subword regularization,增强模型鲁棒性

缺点是:

训练更复杂 推理实现更复杂 工程速度可能不如 BPE 简单直接

15. SentencePiece:不是单一算法,而是 tokenizer 框架

SentencePiece 是一个语言无关的 tokenizer / detokenizer 框架。

它支持:

BPE Unigram LM char word

它的重要特点是:

可以直接从原始文本训练,不要求先按空格分词。

这对中文、日文、韩文很重要,因为这些语言不像英文那样天然用空格分词。

SentencePiece 通常用表示空格。

例如:

Hello world

可以内部表示成:

▁Hello ▁world

这样空格也成为 tokenizer 学习的一部分。


16. BPE、WordPiece、Unigram、SentencePiece 对比

方法核心思想训练方向优点缺点典型模型
BPE高频相邻 pair 合并小词表 → 大词表简单、快、稳定贪心、不懂语义GPT-2、RoBERTa、很多 GPT 类模型
Byte-Level BPE从 UTF-8 byte 开始做 BPEbyte → subword无 OOV、可逆、工程强某些语言可能碎GPT-2、OpenAI tiktoken、Qwen、DeepSeek LLM
WordPiece更关注合并带来的建模收益小词表 → 大词表比 BPE 更概率化实现复杂BERT、DistilBERT、MobileBERT
Unigram LM概率模型选择 token大词表 → 小词表理论优雅、多切分路径训练复杂T5/ALBERT 等 SentencePiece 系模型
SentencePiecetokenizer 框架支持 BPE/Unigram语言无关,适合中日韩本身不是单一算法LLaMA 1/2、T5、Gemma 等许多模型

17. 主流大模型是不是还在用 BPE?

结论:

是的,BPE 或 BPE 变体仍然是主流大模型 tokenizer 的核心路线之一,但不是唯一路线。

常见情况如下。

17.1 GPT-2 / RoBERTa / BART / DeBERTa

这些模型使用 BPE 或 byte-level BPE 类 tokenizer。

GPT-2 使用 byte-level BPE,词表大小约 50,257:

256 个 byte 基础 token + 约 50,000 个 BPE merge token + 特殊 token

17.2 OpenAI tiktoken 系列

OpenAI 的tiktoken是快速 BPE tokenizer,用于 OpenAI 模型。

它的核心仍是 BPE:

文本 → bytes → BPE token ids

它强调:

可逆 无损 可以处理任意文本 压缩文本长度

17.3 LLaMA 系列

LLaMA 1 / LLaMA 2 主要使用 SentencePiece tokenizer。

LLaMA 3 之后切换到更大的 tokenizer,词表约 128K,并更重视多语言和压缩效率。

LLaMA 3 的 tokenizer 通常被描述为 tiktoken/BPE 风格,Meta 官方也强调 LLaMA 3 使用 128K 词表来更高效编码语言。


17.4 Qwen 系列

Qwen 系列使用 BPE / tiktoken 风格 tokenizer。

Qwen-7B 的 tokenizer 说明中明确提到:

BPE tokenization on UTF-8 bytes using tiktoken

也就是说,Qwen 是典型的 byte-level BPE 路线。


17.5 DeepSeek 系列

DeepSeek LLM 官方说明中提到使用 Hugging Face Tokenizer 实现 Byte-level BPE,并使用专门设计的 pre-tokenizer。

所以 DeepSeek LLM / DeepSeek-R1 一类模型也属于 byte-level BPE 路线或其变体。


17.6 BERT 系列

BERT 使用 WordPiece。

它不是 BPE,但和 BPE 一样属于子词 tokenizer。

BERT 的 WordPiece 推理阶段常用贪心最长匹配:

unaffable → un / ##aff / ##able

17.7 T5 / ALBERT / 一些多语言模型

这些模型常用 SentencePiece / Unigram LM。

SentencePiece 对中日韩、多语言、无空格文本比较友好。


18. 对中文大模型来说,tokenizer 设计为什么重要?

因为 token 数直接影响:

训练成本 推理成本 上下文长度利用率 显存占用 attention 计算量

Transformer 注意力复杂度近似是:

O(n²)

其中n是 token 数。

如果中文一句话被切得很碎,token 数变多,那么:

上下文窗口被浪费 推理变慢 训练成本变高 长文本能力下降

所以中文友好的 tokenizer 会尽量让常见中文词、短语、标点组合、换行结构、代码符号成为更高效的 token。


19. 从工程角度如何判断一个 tokenizer 好不好?

一个好的 tokenizer 应该满足:

指标解释
压缩率高同样文本 token 数少
无 OOV任意字符都能编码
可逆decode(encode(text)) = text
多语言公平中文、英文、代码都不要太浪费
代码友好对缩进、换行、括号、关键字优化
数学/Markdown 友好对公式、符号、表格结构友好
编码速度快推理服务中 tokenizer 不能成为瓶颈
词表大小合适太小会碎,太大会增加 embedding 参数

20. BPE 为什么还没被淘汰?

因为 BPE 虽然不是理论最优,但工程优势非常强:

简单 确定 快 容易实现 容易并行 容易部署 可逆性好 byte-level 后没有 OOV

所以今天很多大模型仍然使用 BPE 或 BPE 变体。

它就像工程中的“足够好且足够稳定”的方案。


21. 最终总结

21.1 汉字进入 GPT-2 风格 BPE 的过程

中 ↓ Unicode U+4E2D ↓ UTF-8 E4 B8 AD ↓ byte-to-unicode ä ¸ ľ ↓ BPE merge 举 ↓ vocab 某个 token id

21.2 BPE 的核心算法

1. 拆成最小符号 2. 统计所有相邻 pair 3. 找出现次数最多的 pair 4. 合并成新 token 5. 更新语料 6. 重复直到词表达到目标大小

公式:

(a*, b*) = argmax count(a, b)

然后:

a* b* → a*b*

21.3 BPE 的本质

统计压缩,不是语义理解

它学到的是:

哪些片段经常一起出现,值得用一个 token 表示

不是:

这些片段到底是什么意思

21.4 更高级的 tokenizer 算法

BPE:最高频 pair 合并,简单稳定 WordPiece:更关注合并对建模概率的收益 Unigram LM:概率模型,从大候选词表中删除低贡献 token SentencePiece:语言无关 tokenizer 框架,支持 BPE 和 Unigram Byte-level BPE:从 UTF-8 byte 开始,无 OOV,可逆

21.5 主流大模型是否使用 BPE

答案是:

大量主流大模型仍然使用 BPE 或 BPE 变体。

包括:

GPT-2:byte-level BPE OpenAI tiktoken 系:BPE Qwen:UTF-8 byte-level BPE / tiktoken 风格 DeepSeek LLM:Byte-level BPE RoBERTa/BART/DeBERTa:BPE 类 LLaMA 3:大词表 tiktoken/BPE 风格

但也有很多模型使用其他路线:

BERT:WordPiece T5/ALBERT/部分多语言模型:SentencePiece / Unigram LLaMA 1/2:SentencePiece

22. 参考资料

  1. Hugging Face Transformers tokenizer summary: https://huggingface.co/docs/transformers/en/tokenizer_summary
  2. Hugging Face LLM Course: Byte-Pair Encoding tokenization: https://huggingface.co/learn/llm-course/en/chapter6/5
  3. Hugging Face LLM Course: WordPiece tokenization: https://huggingface.co/learn/llm-course/en/chapter6/6
  4. Google Research Blog: A Fast WordPiece Tokenization System: https://research.google/blog/a-fast-wordpiece-tokenization-system/
  5. SentencePiece paper: https://arxiv.org/abs/1808.06226
  6. SentencePiece GitHub: https://github.com/google/sentencepiece
  7. OpenAI tiktoken GitHub: https://github.com/openai/tiktoken
  8. Meta Llama 3 introduction: https://ai.meta.com/blog/meta-llama-3/
  9. DeepSeek LLM GitHub FAQ: https://github.com/deepseek-ai/DeepSeek-LLM
  10. Qwen tokenizer note: https://huggingface.co/Qwen/Qwen-7B/blob/main/tokenization_qwen.py

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询