跳转到内容

输入关键词开始搜索

    资料摘要:personal chatgpt 09 — BPE gpt2 tokenizer 与 train tokenizer

    视频摘要更新 2026-08-02置信度 high待阅读原始来源 ↗#深度#大模型#课程#personal-chatgpt

    本讲由真实视频转录与作者 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。

    • 常见词通常对应较少 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 与输入位置。

    一个 Unicode 字符可能编码成多个 UTF-8 bytes。课程把中文字符转成 byte 数组并逐 byte 映射,说明 byte-level tokenizer 的基础单位不是“汉字”或“英文字符”,而是 0–255 字节值,再由 BPE merge 形成更长 token。

    这种做法保证任意 UTF-8 文本都有基础表示,不需要真正的 unknown character;代价是某些非英语文本在未充分 merge 时会变成较长 token 序列。

    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、模板或序列边界等。

    课程给出的方向性对比:

    • BPE:从基础符号出发,反复合并高频相邻 pair,逐步增加词表单元;
    • Unigram:从较大的候选词表开始,依据概率/损失逐步删除不重要单元;
    • WordPiece:课程列入三大算法并给出 Hugging Face tokenizers 训练入口,但没有深入推导其打分公式。

    因此本稿不补写课程没有讲的 WordPiece 细节。

    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。

    第二份 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 层规模。

    notebook 演示:

    python_tokenizer.push_to_hub("codeparrot")

    保存输出显示作者曾推送到 lanchunhui/codeparrot。复现时必须使用自己的账号、token 和仓库权限;不能把课程作者的 namespace 当成可写目标。

    BPE 的课程级抽象:

    基础符号词表
    → 统计相邻 pair
    → 合并高频 pair
    → 重复,直到达到目标词表规模/停止条件

    byte-level 基础覆盖:

    initial alphabet=256|\text{initial alphabet}|=256

    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 Face tokenizers 的 WordPiece 训练入口。
    • 12:02:GPT-2 bytes_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。
    • 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 和源码校正。
    • 承接第 8 讲:从模型权重/激活的数值表示,转向输入文本的离散表示。
    • 连接第 10 讲:训练 tokenizer 需要可流式迭代的大规模领域语料;第 10 讲系统解释 memory mapping、streaming、Dataset 与 DataLoader。
    1. GPT-2 byte-level BPE 为什么需要一个覆盖 256 个 byte 的基础 alphabet?
    2. ĠĊ 分别编码了什么信息,为什么空格变化会改变 tokenization?
    3. tokenizer 的 normalization、pre-tokenization、model、post-processing 各自负责什么?
    4. 增加词表大小为什么可能让 Python 关键字更容易成为单 token,又会增加什么模型成本?
    5. 为什么当前材料无法按原样重新训练并推送第二份 notebook 的 tokenizer?
    • 视频:BPE gpt2 tokenizer 与 train tokenizer
    • 转录:🔒 personal chatgpt 09 视频转录
    • 课件 / 代码:🔒 tokenizer_basics.ipynb
    • 课件 / 代码:🔒 gpt2_train_tokenizer.ipynb
    • 滴答清单抓取时学习状态:已完成
    • 视频正文采用自动语音识别;关键术语已用标题、notebook 与源码校正,无法确认的口语细节不扩写。
    • notebook 未执行的 CUDA、权重下载、训练或外部 API 单元,不表述为已复现实验。