大模型的分词算法中,经常遇到BPE, BBPE. 什么是BPE和BBPE? 如何理解这两个概念,一文通俗易懂解释、附案例说明。

BPE(Byte Pair Encoding)是一种基于频率统计的子词分词算法,通过不断合并语料中出现频率最高的相邻符号对来构建词表,从而在词表大小和泛化能力之间取得平衡。

BBPE(Byte-Level BPE)则将最小单位从字符扩展到UTF-8字节,先以256个字节作为基础词表,再执行BPE合并,因此理论上能够编码任意文本,不存在OOV问题。GPT-2、GPT-3、GPT-4等模型均采用了BBPE思想。

以往的博客有一个共同问题:

它们讲的是算法流程,但没有讲清楚“为什么要这么干”。

我换一个更接近人类学习语言的例子,让大家迅速理解这两个算法的思想。


先忘掉BPE

假设你是个刚学英语的小孩。

你见过下面这些单词:

play
playing
played
player
playground

老师问:

你发现什么规律了吗?

你会发现:

play

经常出现。

后面变化的是:

ing
ed
er
ground

于是你的大脑自然形成:

play + ing
play + ed
play + er
play + ground

而不是:

p+l+a+y+i+n+g

事实上:

BPE就是在模拟这种学习过程。


第一步:把所有单词拆成最小单位

训练语料:

play
playing
played
player

初始状态:

p l a y
p l a y i n g
p l a y e d
p l a y e r

此时词表:

p
l
a
y
i
n
g
e
d
r

模型现在什么都不懂。

它只知道:

字符

第二步:统计谁总是挨着出现

观察:

p l
l a
a y

出现次数:

Pair 次数
p l 4
l a 4
a y 4
y i 1
i n 1
n g 1
y e 2

BPE规则:

谁出现最多,我先记住谁。

于是:

p+l

被合并。

得到新Token:

pl

词表变成:

pl
a
y
...

语料变成:

pl a y
pl a y i n g
pl a y e d
pl a y e r

第三步:继续找最高频Pair

现在统计:

(pl,a)
(a,y)

次数:

(pl,a)=4
(a,y)=4

假设先选:

(pl,a)

合并:

pla

语料变:

pla y
pla y i n g
pla y e d
pla y e r

第四步

统计:

(pla,y)=4

最高。

合并:

play

语料:

play
play i n g
play e d
play e r

这时候发生了什么?

模型突然发现:

play

是个高频结构。

于是:

play

成为一个独立Token。


这就是BPE最核心思想:

高频结构保留,低频结构拆开。


为什么这样更好?

看一句话:

I am playing football

如果按字符:

I
a
m
p
l
a
y
i
n
g
...

14个以上Token。


如果BPE:

I
am
play
ing
football

可能只剩5个Token。


节省大量计算。


再举一个中文例子

假设训练数据:

人工智能
人工客服
人工审核
人工标注

初始化:

人 工 智 能
人 工 客 服
人 工 审 核
人 工 标 注

统计:

(人,工)

出现:

4次

最高。


合并:

人工

语料:

人工 智能
人工 客服
人工 审核
人工 标注

继续统计:

(人工,智能)

1次

(人工,客服)

1次

...

都不高。


于是最终词表可能有:

人工

但没有:

人工智能
人工客服

这意味着:

模型学会了:

人工

这个概念。


看到新词:

人工翻译

也能理解。

因为:

人工 + 翻译

这就是BPE最大的价值

不是记住单词。

而是记住:

高频子词(Subword)

那BBPE又是什么?

这里很多人第一次学会懵。

因为名字只差一个B。

实际上差别非常大。


BPE:

字符
↓
合并
↓
Token

BBPE:

字节(Byte)
↓
合并
↓
Token

什么叫字节?

电脑不认识:

A
你
😊

电脑只认识:

01010101

这种二进制。


例如:

字符:

A

ASCII:

65

字符:

B

ASCII:

66

所以:

AB

实际上:

65
66

BBPE训练过程

假设语料:

cat
cat
cat
car

转换字节:

c = 99
a = 97
t = 116
r = 114

得到:

99 97 116
99 97 116
99 97 116
99 97 114

统计:

99+97

出现:

4次

最高。


合并:

CA

(新Token)

编号:

256

语料变:

256 116
256 116
256 116
256 114

再统计:

256+116

出现:

3次

继续合并:

CAT

编号:

257

最后:

cat

变成一个Token。


为什么GPT不用普通BPE?

来看这个例子:

hello

训练过。


突然用户输入:

hello😊

普通BPE可能没见过:

😊

直接傻了。


但BBPE不会。

因为:

😊

也是字节组成。

例如:

240
159
152
138

(UTF-8编码)


那么:

hello😊

一定能拆成:

hello
240
159
152
138

一定能编码。


GPT为什么选BBPE

因为互联网有:

英文
中文
日文
韩文
Emoji
代码
乱码
特殊符号

如果普通BPE:

需要:

英文字符集
中文字符集
日文字符集
...

很麻烦。


BBPE只需要:

0~255

这256个字节。

理论上就能表示世界上所有文本。


最后用一句话彻底理解

把 BPE 想象成:

从“拼音识字”慢慢学习常见词根和词组。

例如:

p
→ pl
→ pla
→ play

逐步合并。


把 BBPE 想象成:

连字都不认,直接从电脑最底层的字节开始学习。

例如:

99
97
116
↓
ca
↓
cat

最终得到Token。


所以:

BPE = 字符级学习高频子词

BBPE = 字节级学习高频子词(GPT系列主流方案)

理解这一点后,你再去看 GPT Tokenizer 的 Token 数统计、Qwen Tokenizer、SentencePiece、WordPiece,基本就能一眼看懂它们到底在干什么了。

追问:BPE的名字是不是有误导性?B既然指的是Byte, 那为什么还要说是:BPE = 字符级学习高频子词 字符不应该是叫做Character吗?

这个疑问非常好,而且很多刚接触 Tokenizer 的人都会被这个名字绕晕。

实际上:

BPE 里的 B 根本不是 Byte。

很多人第一次看到:

BPE
BBPE

会自然理解成:

B = Byte
BB = Byte Byte

但这是错的。


BPE全称是什么?

BPE 的全称:

Byte Pair Encoding

这里的 Byte 确实是:

Byte
字节

但是这里有一个历史问题。


BPE最早根本不是分词算法

BPE最早诞生于1994年:

由:

Philip Gage

提出。

用于:

文件压缩

不是 NLP。


原始BPE处理的是:

字节流(Byte Stream)

例如:

65 66 65 66 65 66

即:

A B A B A B

它不断寻找:

AB

这种高频字节对。

然后替换。

例如:

ABABAB

变:

X X X

达到压缩目的。


所以名字里的:

Byte Pair Encoding

是历史遗留名称。


NLP后来借用了这个算法

2015年左右。

论文:

Neural Machine Translation of Rare Words with Subword Units

把BPE引入NLP。


但作者并没有真的处理Byte。

而是处理:

字符(Character)

例如:

l o w

统计:

(l,o)
(o,w)

然后不断合并。


所以实际流程:

Character
↓
Character Pair
↓
Merge
↓
Subword

但是大家仍然沿用:

BPE

这个名字。

没有改名。


因此严格来说:

现代NLP里的经典BPE其实是:

Character Pair Encoding

更准确。

只是没人这么叫。


那BBPE又是什么?

后来GPT-2团队发现:

字符级BPE有问题。


例如:

hello
你好
😊

字符集越来越大。

各种Unicode字符不好处理。


于是GPT-2提出:

我们不要从 Character 开始了。

改成:

UTF-8 Byte

开始。


流程变成:

Byte
↓
BPE
↓
Token

这时候才真正回到了:

Byte Pair Encoding

的原始含义。


所以有趣的现象出现了:

名称 实际处理对象
BPE(NLP传统) Character
BBPE(GPT-2) Byte
原始BPE(压缩算法) Byte

换句话说:

最开始的BPE是Byte。

后来NLP把它改成Character。

GPT-2又把它改回Byte。


为什么会出现BBPE这个名字?

严格来说:

GPT-2论文里甚至没有正式提出:

BBPE

这个术语。

GPT-2论文更多写的是:

Byte-level BPE

即:

BPE operating on bytes

后来社区为了区分:

Character-level BPE

Byte-level BPE

才逐渐出现:

BBPE

这个叫法。


最准确的理解方式

如果从工程角度分类:

BPE
├── Character-level BPE
│    (传统NLP)
│
└── Byte-level BPE
     (GPT-2/GPT-3/GPT-4)

所以你看到:

BPE = 字符级学习高频子词

并不是说:

B = Character

而是说:

NLP领域里常说的BPE,虽然名字来自 Byte Pair Encoding,但实际训练时通常以 Character 作为初始符号集合。

这也是为什么很多人第一次学习时会觉得名字和实现完全对不上——因为它本来就是一个从压缩领域“借用过来”的算法名,后来含义发生了演化。

posted @ 2026-06-19 12:44  AlphaGeek  阅读(61)  评论(0)    收藏  举报