[ PROMPT_NODE_23018 ]
Tokenization Sentencepiece 算法
[ SKILL_DOCUMENTATION ]
# 分词算法
BPE 与 Unigram 的对比及子词正则化。
## BPE (字节对编码)
### 算法
1. 初始化词表为字符
2. 统计相邻标记对的频率
3. 合并最频繁的对
4. 重复直到达到词表大小
### 示例
**语料库**:
low: 5
lower: 2
newest: 6
widest: 3
**迭代 1**:
- 最频繁对:'e' + 's' (9 次)
- 合并 → 'es'
- 词表:[字符] + ['es']
**迭代 2**:
- 最频繁:'es' + 't' (9 次)
- 合并 → 'est'
- 词表:[字符] + ['es', 'est']
**结果**:`newest` → `new|est`, `widest` → `wid|est`
### 实现
python
import sentencepiece as spm
spm.SentencePieceTrainer.train(
input='corpus.txt',
model_type='bpe',
vocab_size=16000
)
### 优点
- 算法简单
- 训练速度快
- 压缩比高
### 缺点
- 确定性(无采样)
- 可能会意外拆分常用词
## Unigram
### 算法
1. 从大词表开始(所有子串)
2. 计算每个标记的概率
3. 移除损失影响最小的标记
4. 重复直到达到词表大小
### 概率分词
给定带有概率的词表:
P('low') = 0.02
P('est') = 0.03
P('l') = 0.01
P('o') = 0.015
...
分词 "lowest":
选项 1: ['low', 'est']
P = 0.02 × 0.03 = 0.0006 ← 最高
选项 2: ['l', 'o', 'w', 'est']
P = 0.01 × 0.015 × 0.01 × 0.03 = 0.000000045
选择选项 1 (最高概率)
### 实现
python
spm.SentencePieceTrainer.train(
input='corpus.txt',
model_type='unigram',
vocab_size=8000
)
### 优点
- 概率性(可采样)
- 更适合形态丰富的语言
- 支持子词正则化
### 缺点
- 训练较慢
- 算法更复杂
## 对比
| 特性 | BPE | Unigram |
|---------|-----|---------|
| 训练速度 | 快 | 慢 |
| 分词 | 确定性 | 概率性 |
| 采样 | 否 | 是 |
| 典型词表大小 | 16k-32k | 8k-32k |
| 使用者 | mBART | T5, ALBERT, XLNet |
## 子词正则化
在训练期间采样不同的分词方式以提高鲁棒性。
### 启用采样
python
sp = spm.SentencePieceProcessor(model_file='m.model')
# 采样不同的分词
for _ in range(5):
pieces = sp.encode('tokenization', out_type=str, enable_sampling=True, alpha=0.1)
print(pieces)
# 输出(每次不同):
# ['▁token', 'ization']
# ['▁tok', 'en', 'ization']