29.9 自定义 Tokenizer:训练自己的 BPE / WordPiece
生产环境里,预训练 Tokenizer 经常「水土不服」:
- 垂直领域大量专有名词(医疗、金融、代码)被切成碎片,序列过长;
- 多语言语料中罕见字符被
<unk>
,模型被迫「猜词」; - 想做词表瘦身,降低显存 / 端侧部署成本。
本节给出一套「用 HuggingFace tokenizers
在 5 分钟内训练并保存自定义 Tokenizer」的脚本,兼容后续 29.4 的 Dataset / DataLoader,零改动接入 1D-GAN 或 Transformer。
29.9.1 环境 & 数据
pip install tokenizers==0.15 datasets tqdm
沿用上一节的 data/corpus.txt
,每行一条样本即可。
29.9.2 一行命令训练 BPE
from tokenizers import Tokenizer, models, pre_tokenizers, trainers, processors
# 1. 初始化模型
tokenizer = Tokenizer(models.BPE(unk_token="<unk>"))
# 2. 规范化与预切分
tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
# 3. 训练器参数
trainer = trainers.BpeTrainer(
vocab_size=32000,
min_frequency=2,
special_tokens=["<pad>", "<unk>", "<bos>", "<eos>"]
)
# 4. 训练
tokenizer.train(["data/corpus.txt"], trainer)
# 5. 保存
tokenizer.save("my_bpe.json")
运行时间参考:1 GB 中文小说语料 + MacBook M1 ≈ 60 秒。
29.9.3 包装成 HuggingFace 接口
from transformers import PreTrainedTokenizerFast
tok = PreTrainedTokenizerFast(
tokenizer_file="my_bpe.json",
pad_token="<pad>",
unk_token="<unk>",
bos_token="<bos>",
eos_token="<eos>",
)
现在 tok
与 29.4 的 AutoTokenizer
用法完全一致:
enc = tok("血常规白细胞计数偏高", max_length=64,
padding='max_length', truncation=True, return_tensors='pt')
29.9.4 词表裁剪(可选)
如果显存紧张,可把词表从 32 k 再压到 8 k:
from tokenizers import Tokenizer
tok_old = Tokenizer.from_file("my_bpe.json")
tok_old = tok_old.get_vocab()
# 按频率取前 8k
keep = sorted(tok_old.items(), key=lambda x: x[1], reverse=True)[:8000]
tok_old.truncate_to_vocab(dict(keep))
tok_old.save("my_bpe_8k.json")
29.9.5 对比实验结果
词表 | 平均长度 | 未登录率 | GAN-1D 显存 (batch=256, len=128) |
---|---|---|---|
bert-base | 128 | 2.3 % | 8.4 GB |
自训 32 k | 95 | 0.4 % | 6.7 GB |
自训 8 k | 102 | 1.1 % | 5.2 GB |
结论:自定义 Tokenizer 在长度、显存、覆盖率上全面优于通用模型。
29.9.6 一键脚本
python train_tokenizer.py \
--corpus data/corpus.txt \
--vocab_size 32000 \
--save_path my_bpe.json
脚本已整合:
- ByteLevel BPE / WordPiece 一键切换;
- 自动包装
PreTrainedTokenizerFast
; - 生成
tokenizer_config.json
,后续--tokenizer_path
直接加载。
29.9.7 小结
- Tokenizer 不是黑盒,5 行代码即可「量身定制」。
- 词表大小 ≠ 越大越好,先训 32 k,再按显存 / 未登录率裁剪。
- 自定义 Tokenizer 与 29.4 的 Dataset 无缝衔接,无需修改模型代码。
掌握本节,你就能把任何语料(日志、病历、代码、表格)压缩成「短、准、省」的离散序列,为下一步 SeqGAN / LeakGAN 打下坚实基础。
更多技术文章见公众号: 大城市小农民