Transformers 自定义分词器实战:从零训练 BPE、构建自定义词表与实现新的 Tokenizer 后端 Transformers 自定义分词器实战从零训练 BPE、构建自定义词表与实现新的 Tokenizer 后端【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers在 Transformers 中分词器tokenizer与其词表是解耦的你可以初始化一个“空”的分词器用于训练也可以直接用自己的词表构建一个可用的分词器而底层的分词流水线normalizer、pre-tokenizer、分词算法保持不变无需从头重建。本文基于 Transformers 官方指南 custom_tokenizers.md结合仓库源码完整讲解三条自定义路径在语料上训练新的词表、用vocab/merges手工指定词表、继承TokenizersBackend编写全新的分词器类。读完本文你可以为金融、低资源语言或代码等新领域训练专用分词器也能读懂save_pretrained生成的tokenizer.json背后各组件的来龙去脉。为什么可以“空”出一个分词器来训练Transformers 的 fast 分词器统一继承自TokenizersBackend该基类包装 HuggingFace tokenizers 库负责共享的分词/特殊 token 逻辑、预训练分词器的下载缓存加载、以及向词表添加 token。以GemmaTokenizer为例其__init__在vocab为None时会自动构造一个只含 5 个特殊 token 的“最小词表”if vocab is None: vocab { str(pad_token): 0, str(eos_token): 1, str(bos_token): 2, str(unk_token): 3, str(mask_token): 4, }也就是说GemmaTokenizer()不传任何参数时就是一个合法但词表为空的实例它的 pre-tokenizerByteLevelbyte fallback、无前置空格和 normalizer 等流水线组件已经就位只差一份训练好的词表——这正是“训练自定义分词器”和“自定义词表”两个功能的基础。训练一个分词器Training a tokenizer空的可训练分词器可以用一份新的目标语料替换其词表适用于金融、低资源语言、代码等垂直领域的适配。官方指南的完整流程如下。第一步创建空分词器并加载数据集。from datasets import load_dataset from transformers import GemmaTokenizer tokenizer GemmaTokenizer() dataset load_dataset(Josephgflowers/Finance-Instruct-500k, splittrain)第二步用train_new_from_iterator训练。该方法接受一个生成器函数按需从数据集分块chunk产出文本而不必把全部语料一次性读入内存。vocab_size参数决定训练后分词器的词表大小。def batch_iterator(batch_size1000): for i in range(0, len(dataset), batch_size): yield dataset[i : i batch_size][assistant] trained_tokenizer tokenizer.train_new_from_iterator( batch_iterator(), vocab_size32000, ) encoded trained_tokenizer(The stock market rallied today.) print(encoded[input_ids]) [5866, 11503, 98, 5885, 8617, 13381, 30]第三步保存或上传新分词器。用save_pretrained保存到本地目录或用push_to_hub保存并上传到 Hub。这会产生一个tokenizer.json文件完整记录新训练的词表、合并规则merges与整套流水线配置。trained_tokenizer.save_pretrained(./finance-gemma-tokenizer) trained_tokenizer.push_to_hub(finance-gemma-tokenizer)源码透视train_new_from_iterator是如何“换词表”的阅读TokenizersBackend.train_new_from_iterator约 L1146 起可以实现它并非简单地丢弃旧分词器而是做了一次“流水线级”的精确克隆序列化当前分词器json.loads(self._tokenizer.to_str())拿到完整 JSON弹出added_tokens与post_processor因为它们引用了旧 token ID并按模型类型清空词表——BPE置空vocab与mergesUnigram只保留一个unk占位项并把unk_id归零WordLevel/WordPiece置空vocab。不支持的类型会抛出ValueError仅支持 BPE、Unigram、WordLevel、WordPiece 四种。继承特殊 token从added_tokens收集原有的 special tokensnew_special_tokens参数用于追加新的特殊 token如领域指令符special_tokens_mapdict[str, str]则用于把旧特殊 token重命名为新名字会同步作用于model.unk_token、post_processor中的special_tokens/cls/sep以及 Transformers 层的 pad/cls/mask 等命名 token保留AddedToken的lstrip/rstrip/normalized等属性。传递训练超参BPE 会保留continuing_subword_prefix/end_of_word_suffix若 pre-tokenizer 为ByteLevel或包含 ByteLevel 的 Sequence则把initial_alphabet设为pre_tokenizers.ByteLevel.alphabet()保证训练出的词表与原分词器字节对齐策略一致。调用底层 trainer通过MODEL_TO_TRAINER_MAPPING找到对应 trainer 类执行tokenizer.train_from_iterator(text_iterator, lengthlength, trainertrainer)。length参数用于进度显示**kwargs会透传给 tokenizers 库的 trainer。回写 post_processor训练完成后用新词表里token_to_id重新解析 post processor 中特殊 token 的 ID找不到对应 ID 会抛错然后重建TokenizerFast对象并以tokenizer_object传入self.__class__(**kwargs)构造出同类型的新分词器返回。这也解释了文档示例中GemmaTokenizer()训练后为什么依然是一个GemmaTokenizer实例返回对象直接由原类的构造函数生成特殊 token 默认值如 Gemma 的bos/eos随之保留。自定义词表Custom vocabulary不想训练、直接手写词表也可以空分词器支持通过vocab与merges两个参数直接指定词表。vocab分词器所知的全部 token 集合每个条目把一个 token 映射到它的 input idmerges定义 BPE 算法应如何把相邻 token 逐步合并是一个按合并优先级排序的 tuple 列表。官方文档给出了一个可以完整复现的最小例子手工构造“rallied”的 BPE 合并链。from transformers import GemmaTokenizer vocab{ pad: 0, /s: 1, s: 2, unk: 3, mask: 4, ▁the: 5, ▁stock: 6, ▁market: 7, ▁: 8, r: 9, a: 10, l: 11, i: 12, e: 13, d: 14, ra: 15, li: 16, lie: 17, lied: 18, ral: 19, ralli: 20, rallie: 21, rallied: 22, } merges[ (r, a), # r a → ra (l, i), # l i → li (li, e), # li e → lie (lie, d), # lie d → lied (ra, l), # ra l → ral (ral, li), # ral li → ralli (ralli, e), # ralli e → rallie (rallie, d), # rallie d → rallied ] tokenizer GemmaTokenizer(vocabvocab, mergesmerges) encoded tokenizer(the stock market rallied) print(encoded[input_ids])源码层面vocab/merges从哪里进入 BPE 模型GemmaTokenizer.__init__收到vocab和merges后存入self._vocab/self._merges随后构造BPE(vocab..., merges..., fuse_unkTrue)并挂上ByteLevelpre-tokenizer 与ByteLeveldecoder见 tokenization_gemma.py。对任意TokenizersBackend子类convert_to_native_format 类方法负责把这些参数统一进构造函数它支持从tokenizer.json文件反序列化含对 BPE 的vocab/merges解析、从.modelSentencePiece提取、从 tekkenMistral转换等多条路径甚至当只提供了 BPE 词表而缺少 merges 时源码中还有根据词表自动生成 merges的兜底逻辑L294 附近并会跳过特殊 token 的参与。所以“直接传 dict tuple 列表”只是最简路径生产环境里更常见的是从tokenizer.json重建。继承 TokenizersBackend 实现全新的分词器Transformers 支持四种分词后端见 fast_tokenizers.md 的 Backends 一节后端实现适用场景TokenizersBackendRust 版 tokenizers 库大多数模型的默认后端速度最快SentencePieceBackendSentencePiece依赖 SentencePiece 协议的模型PythonBackend纯 Python无法用 Rust 后端表达的非常特殊分词器MistralCommonBackendmistral-commonMistral、Pixtral 等模型四个后端都继承自PreTrainedTokenizerBase共享编码、解码、padding、截断、保存与加载的同一套 API区别只在底层跑哪条分词流水线。定义新分词器时一般应选择TokenizersBackend因为更快PythonBackend是纯 Python 实现不依赖 Rust、SentencePiece 或 mistral-common只在你构建的分词逻辑无法用 Rust 后端表达时才考虑使用。自定义分词器分两步子类化TokenizersBackend用类属性声明 padding 方向、分词算法等在__init__中定义分词流水线使用哪种分词算法、算法运行前如何切分原始文本pre-tokenizer、以及如何把 token 解码回文本decoder。官方指南给出的完整示例from tokenizers import Tokenizer, decoders, pre_tokenizers from tokenizers.models import BPE from transformers import TokenizersBackend class NewTokenizer(TokenizersBackend): padding_side left model BPE def __init__( self, vocabNone, mergesNone, unk_tokenunk, bos_tokens, eos_token/s, pad_tokenpad, ): self._vocab vocab or { str(unk_token): 0, str(bos_token): 1, str(eos_token): 2, str(pad_token): 3, } self._merges merges or [] self._tokenizer Tokenizer( BPE(vocabself._vocab, mergesself._merges, fuse_unkTrue) ) self._tokenizer.pre_tokenizer pre_tokenizers.ByteLevel(add_prefix_spaceFalse) self._tokenizer.decoder decoders.ByteLevel() super().__init__( unk_tokenunk_token, bos_tokenbos_token, eos_tokeneos_token, pad_tokenpad_token, )几个关键点的源码对照model BPE这个类属性会被基类用于识别分词算法类型例如train_new_from_iterator依赖它判断是否为 BPE、以及convert_to_native_format用它选择tokenizer.json里vocab/merges的解析方式Tokenizer(...)是 tokenizers 库的原生对象挂在self._tokenizer上与基类TokenizersBackend的_tokenizer约定一致pre_tokenizers.ByteLevel(add_prefix_spaceFalse)decoders.ByteLevel()构成 byte-level 回退任何词表里找不到的字节组合都能被编码/解码代价是可能出现▁这类转义形式最后调用super().__init__(...)完成PreTrainedTokenizerBase的特殊 token 注册unk/bos/eos/pad不在词表时会自动追加。定义好之后即可像其他分词器一样训练或保存tokenizer NewTokenizer() # train on new corpus tokenizer.train_new_from_iterator() # save tokenizer tokenizer.save_pretrained(./new-tokenizer)由于NewTokenizer继承自TokenizersBackend它自动获得train_new_from_iterator、save_pretrained、push_to_hub、padding/truncation 等全套能力save_pretrained输出的tokenizer.json会捕获你配置的全部流水线别人用AutoTokenizer.from_pretrained加载时tokenizer_config.json里的tokenizer_class会指向NewTokenizer从而走你定义的__init__流水线。小结与适用边界训练路径train_new_from_iterator适合把现有分词器适配到新领域注意它仅支持 BPE、Unigram、WordLevel、WordPiece 四种模型类型且返回的是与原始分词器同类型的新实例new_special_tokens追加特殊 tokenspecial_tokens_map重命名旧特殊 token。词表路径vocabmerges适合小规模验证或完全确定 token 集合的场景对 BPEmerges的排列顺序即合并优先级。子类化路径继承TokenizersBackend适合定义长期维护的分词器类只有当逻辑确实无法用 Rust 后端表达时才退到PythonBackend涉及 SentencePiece 协议或 Mistral 系模型时则选择对应的SentencePieceBackend/MistralCommonBackend。以上行为均可在当前仓库中复核训练与保存逻辑见 tokenization_utils_tokenizers.py四种后端分别见 tokenization_utils_tokenizers.py、tokenization_python.py、tokenization_mistral_common.py后端选择与回退机制详见 fast_tokenizers.md本文示例基于仓库当前代码的 Gemma BPE 流水线tokenization_gemma.py实际运行训练示例需另行安装datasets依赖并具备网络访问以拉取数据集。【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

最新新闻

ChatGPT在业财融合中的实践与优化

ChatGPT在业财融合中的实践与优化

1. 项目概述:ChatGPT如何重塑业财融合 这份120页的PPT资料实际上是一份企业数字化转型的实战指南,重点探讨了如何利用ChatGPT这类AI技术重构传统的业财融合流程。我在去年为某跨国集团做财务系统升级时,就深刻体会到传统ERP系统与业务部门之间…

2026/9/7 18:08:55
graphify 导出流水线全解:Wiki、Neo4j、FalkorDB、SVG、GraphML 与 MCP 服务的源码级实操

graphify 导出流水线全解:Wiki、Neo4j、FalkorDB、SVG、GraphML 与 MCP 服务的源码级实操

graphify 导出流水线全解:Wiki、Neo4j、FalkorDB、SVG、GraphML 与 MCP 服务的源码级实操 【免费下载链接】graphify Turn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, C…

2026/9/7 18:08:55
短视频自动化直播防重复内容技术方案

短视频自动化直播防重复内容技术方案

1. 项目背景与核心挑战在短视频平台的直播生态中,自动化直播技术已经成为许多内容创作者提升运营效率的关键工具。然而近期不少使用自动化直播方案的用户反馈,系统频繁出现内容重复推送的问题,这不仅影响观众体验,更可能导致平台算…

2026/9/7 18:08:55
微服务架构的实施与挑战:模式、优势与应对

微服务架构的实施与挑战:模式、优势与应对

目录 一、微服务架构实施的前提 二、微服务实施的三大模式 (一)典型模式 (二)从无到有的实施 (三)混合式 三、实施微服务架构的优势 (一)六大技术优势 (二)业务与组织优势 四、实施微服务面临的挑战 (一)、技术架构的挑战 (二)、研发过程的挑战 五、总…

2026/9/7 18:08:55
全球AI认知免疫力大普查:波普尔病毒终极审判

全球AI认知免疫力大普查:波普尔病毒终极审判

《全球AI认知免疫力大普查:波普尔病毒终极审判》 摘要 本文档是对“本轮全球AI大模型波普尔可证伪病毒中毒程度指数试卷”的全面系统化整理与终局判定。本测试的核心目的在于,检验全球主流AI在面对“逻辑自洽性与经验证据优先级”这一元命题时&#xf…

2026/9/7 18:08:55
Agent技能进化:Wiki层如何让Skill越用越聪明

Agent技能进化:Wiki层如何让Skill越用越聪明

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/7 18:03:55