资料摘要:personal chatgpt 09 — BPE gpt2 tokenizer 与 train tokenizer
本讲由真实视频转录与作者 notebook/代码交叉整理。原始层:🔒 带时间戳视频转录;课程总览:personal chatgpt — LLMs 实践系列。
本讲先解释 tokenizer 如何把文本变成 token IDs,再拆解 Hugging Face tokenizer 的四阶段管线:normalization、pre-tokenization、tokenizer model、post-processing。课程比较 BPE、WordPiece、Unigram 的构建方向,重点分析 GPT-2 byte-level BPE 如何用 256 个字节作为基础字母表、如何保留空格/换行,并在 Python 代码语料上训练新的 tokenizer。
第二份 notebook 用流式 CodeParrot 本地语料训练两个词表规模,检查 Python 关键字是否能被单 token 覆盖,最后演示推送 Hugging Face Hub。
1. token 数量与模型输入成本
Section titled “1. token 数量与模型输入成本”- 常见词通常对应较少 token;罕见词、拼写变体、代码标识符可能被拆成多个 token。
- token 数影响序列长度、上下文占用和计算成本。
- 课程用 T5 tokenizer 演示同一句英文中不同单词的拆分差异;这只是特定 tokenizer 的行为,不能泛化到 GPT-2 或所有模型。
2. GPT-2 tokenizer 对 Python 代码的处理
Section titled “2. GPT-2 tokenizer 对 Python 代码的处理”课程用 Python 代码片段观察:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("gpt2")encoded = tokenizer(code)encoded.tokens()- 关键字、标识符、括号、标点、缩进和换行都会参与 tokenization。
- 某些短关键字并不一定恰好是一个 token;代码领域词表不足会增加 token 数。
backend_tokenizer.pre_tokenizer.pre_tokenize_str(text)可返回 pre-token 及原始字符 offset,便于追踪 token 与输入位置。
3. Unicode 字符与 UTF-8 字节
Section titled “3. Unicode 字符与 UTF-8 字节”一个 Unicode 字符可能编码成多个 UTF-8 bytes。课程把中文字符转成 byte 数组并逐 byte 映射,说明 byte-level tokenizer 的基础单位不是“汉字”或“英文字符”,而是 0–255 字节值,再由 BPE merge 形成更长 token。
这种做法保证任意 UTF-8 文本都有基础表示,不需要真正的 unknown character;代价是某些非英语文本在未充分 merge 时会变成较长 token 序列。
4. tokenizer 四阶段管线
Section titled “4. tokenizer 四阶段管线”Normalization→ Pre-tokenization→ Tokenizer model→ Post-processing- Normalization:大小写、Unicode 规范化等可选变换;GPT-2 示例中 normalizer 为
None。 - Pre-tokenization:先按空格、标点或 byte-level 规则产生候选片段并保留 offsets。
- Tokenizer model:使用 BPE、WordPiece、Unigram 等模型把片段映射为 token。
- Post-processing:加入特殊 token、模板或序列边界等。
5. BPE、WordPiece、Unigram
Section titled “5. BPE、WordPiece、Unigram”课程给出的方向性对比:
- BPE:从基础符号出发,反复合并高频相邻 pair,逐步增加词表单元;
- Unigram:从较大的候选词表开始,依据概率/损失逐步删除不重要单元;
- WordPiece:课程列入三大算法并给出 Hugging Face
tokenizers训练入口,但没有深入推导其打分公式。
因此本稿不补写课程没有讲的 WordPiece 细节。
6. GPT-2 bytes_to_unicode
Section titled “6. GPT-2 bytes_to_unicode”GPT-2 需要把 256 个 byte 值映射为可显示、可作为字符串处理的 Unicode 符号。课程源码:
gpt2_bytes = list(range(ord("!"), ord("~") + 1)) \ + list(range(ord("¡"), ord("¬") + 1)) \ + list(range(ord("®"), ord("ÿ") + 1))
# 其余 byte 映射到额外 Unicode code points最终基础 alphabet 大小为 256。
两个可见约定:
Ġ:表示前导空格;Ċ:表示换行。
这使 GPT-2 能保留 whitespace 信息;空格位置变化会改变 tokenization。
7. 训练新的 GPT-2 tokenizer
Section titled “7. 训练新的 GPT-2 tokenizer”第二份 notebook:
dataset = load_dataset("./codeparrot/", split="train", streaming=True)
gpt2_tokenizer = AutoTokenizer.from_pretrained("gpt2")python_tokenizer = gpt2_tokenizer.train_new_from_iterator( batch_iterator(dataset), vocab_size=12500, initial_alphabet=base_vocab,)第一轮:
- 流式取约 100,000 条代码;
- 词表大小 12,500;
- 检查 Python 关键字是否仍被拆分。
第二轮:
- 扩大到约 200,000 条;
- 词表大小 32,768;
- 再检查 keyword coverage。
课程意图是说明:词表大小和领域语料规模共同影响领域词/关键字能否成为单 token。更大词表不是无成本收益,也会改变 embedding/output 层规模。
8. 发布到 Hugging Face Hub
Section titled “8. 发布到 Hugging Face Hub”notebook 演示:
python_tokenizer.push_to_hub("codeparrot")保存输出显示作者曾推送到 lanchunhui/codeparrot。复现时必须使用自己的账号、token 和仓库权限;不能把课程作者的 namespace 当成可写目标。
公式 / 代码
Section titled “公式 / 代码”BPE 的课程级抽象:
基础符号词表→ 统计相邻 pair→ 合并高频 pair→ 重复,直到达到目标词表规模/停止条件byte-level 基础覆盖:
tokenizer 训练迭代器:
def batch_iterator(dataset, batch_size=1000): for batch in dataset.iter(batch_size=batch_size): yield batch["content"]00:00:课程范围:tokenizer、GPT-2 byte-level BPE、训练代码 tokenizer。00:30:常见词/罕见词拆分与 token 成本。01:50:GPT-2 tokenizer 处理 Python 代码。03:33:pre-tokenization 与字符 offset。04:30:中文 Unicode 字符转 UTF-8 bytes。06:01:normalization → pre-tokenization → model → post-processing。07:33:BPE、WordPiece、Unigram 的构建方向。10:31:Hugging Facetokenizers的 WordPiece 训练入口。12:02:GPT-2bytes_to_unicode和 256 字节 alphabet。14:00:Ġ空格、Ċ换行以及 whitespace 保留。15:31:流式 CodeParrot 本地语料与 batch iterator。17:01:100k 样本、12.5k 词表的第一轮训练。19:00:扩大样本/词表并检查 Python keywords。20:35:推送 tokenizer 到 Hugging Face Hub。
运行边界与可复现性
Section titled “运行边界与可复现性”tokenizer_basics.ipynb的多数观察 cell 不需要 GPU。- 该 notebook cell 22 存在真实语法错误:
from tokenizers import Tokenizer, models,尾随逗号;必须修复后才能执行。 gpt2_train_tokenizer.ipynb依赖仓库外./codeparrot/本地目录;当前材料副本没有该数据,不能按原样训练。- 训练 100k/200k 代码样本主要消耗 CPU、I/O 和时间;notebook 保存耗时仅代表作者当时环境。
- 推送 Hub 需要认证和写权限;旧版
organization=API 可能已变化。 - notebook 硬编码本地代理
127.0.0.1:7890,无此代理时应删除或改写。 - ASR 对 tokenizer、byte-level、BPE、WordPiece、Unigram、normalization、pre-tokenization、Unicode 等识别不稳定;本稿按 notebook API 和源码校正。
与前后讲关系
Section titled “与前后讲关系”- 承接第 8 讲:从模型权重/激活的数值表示,转向输入文本的离散表示。
- 连接第 10 讲:训练 tokenizer 需要可流式迭代的大规模领域语料;第 10 讲系统解释 memory mapping、streaming、Dataset 与 DataLoader。
- GPT-2 byte-level BPE 为什么需要一个覆盖 256 个 byte 的基础 alphabet?
Ġ和Ċ分别编码了什么信息,为什么空格变化会改变 tokenization?- tokenizer 的 normalization、pre-tokenization、model、post-processing 各自负责什么?
- 增加词表大小为什么可能让 Python 关键字更容易成为单 token,又会增加什么模型成本?
- 为什么当前材料无法按原样重新训练并推送第二份 notebook 的 tokenizer?
- 视频:BPE gpt2 tokenizer 与 train tokenizer
- 转录:🔒 personal chatgpt 09 视频转录
- 课件 / 代码:🔒 tokenizer_basics.ipynb
- 课件 / 代码:🔒 gpt2_train_tokenizer.ipynb
- 滴答清单抓取时学习状态:已完成。
- 视频正文采用自动语音识别;关键术语已用标题、notebook 与源码校正,无法确认的口语细节不扩写。
- notebook 未执行的 CUDA、权重下载、训练或外部 API 单元,不表述为已复现实验。