ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

从Tokenizer到Post Training:大模型训练全链路解析

从Tokenizer到Post Training:大模型训练全链路解析 “东锡 NLP”这次的内容主线定得很清楚先讲 tokenizer再讲 post training。这个顺序实际上很符合大模型技术栈的学习路径——先搞清楚文本是怎么被切碎并转成数字输入模型的再去理解预训练之后的后续训练post training阶段如何重塑模型行为。很多同学一上来就盯着 SFT、RLHF 看反而忽略了 tokenizer 和模型训练之间的一致性关系等真到自己做领域模型、自己调词表、自己续训的时候才发现问题全堆在一起。这次我们就把这条主线路过一遍从 tokenizer 的核心机制、训练与扩展到预训练基座和 post training 各阶段的划分、数据构造与实验验证。同时给出一个可以直接套用的 NLP 科普内容制作框架。适合想做 NLP 技术内容选题、正在接触大模型训练或者只是想把基础概念补完整的读者。整篇文章不是单纯的术语罗列而是按“能理解 — 能复现 — 能讲给别人听”三层来组织。1. 核心内容速览维度说明内容主线从 tokenizer 开始再到 post training贯穿大模型数据处理全程tokenizer 部分覆盖分词粒度、BPE/WordPiece/Unigram、中文场景、词表扩展、embedding 对齐post training 部分覆盖 continual pretraining、SFT、DPO/偏好对齐以及各阶段数据规模与效果差异可复现平台本地 Python 3.8HuggingFacetokenizers/transformers简单显存环境即可完成大部分观察实验训练类实验续训/SFT 需要 GPU建议从 7B 或更小参数模型开始显存占用取决于模型尺寸与精度科普内容形态图文、表格、代码、视频脚本的可复用结构适合读者NLP 初学者、想入门大模型训练的人、做技术内容输出的写作者需要说明这篇文章的重点不是吹某个模型而是把 tokenizer 和 post training 这两块知识串成一条“可讲解、可验证、可复现”的链条。下面内容里不会给一个封闭的一站式脚本而是会用公开库和通用方法演示方便你换成自己的语料继续测试。2. 为什么 tokenizer 是 NLP 科普的必经起点在 NLP 技术栈里tokenizer 长期被低估。模型表现不稳定、训练数据有效长度不足、多语言能力偏弱、加领域词效果不明显很多时候源头都在 tokenizer。2.1 tokenizer 决定了模型看到什么文本一个句子在进入模型前需要被切成 token 序列每个 token 对应词表中的 id。这个切分方式直接决定模型能处理的字符覆盖范围一句话能被切得多碎长文本能保留多少上下文新增领域词是否需要额外的特殊 token训练语料里出现频率很低但仍然重要的人类可读字符会不会被拆成不可理解的碎片。以中文为例“自然语言处理”在不同 tokenizer 下可能被切成一个 token、两个 token也可能被切成“自”“然”“语”“言”这种单字序列。对于同一个模型来说每一次切分结果都会影响训练和推理时的参数更新路径。这点在做科普时一定要讲透。2.2 常见的 tokenizer 类型与适用场景实际项目中常见的 tokenizer 有三种思路类型代表算法切分粒度典型使用者Word-based按空格标点切分词级早期模型Subword-basedBPE、WordPiece、Unigram子词级BERT、GPT、LLaMA、QwenCharacter-based按字符切分字符级模型输入层容忍度高时当前大模型主要使用的是 Subword 类方法尤其是 Byte-level BPE。它本质上是在“把语料中出现的高频字符组合合并成 token”和“保留未知词可分解性”之间找平衡。它对英文更友好因为英文的常见词缀会被组合成语义较完整的 token对中文则会出现大量单字或双字 token但不是不能优化。2.3 科普内容里最值得做的 tokenizer 实验这里给一个可以反复使用的思路拿一小段语料训练一个自己的 BPE tokenizer然后观察不同词表大小vocab size下的切分效果。这个实验不依赖大规模 GPU在 CPU 上几分钟就能跑完。from tokenizers import Tokenizer from tokenizers.models import BPE from tokenizers.trainers import BpeTrainer from tokenizers.pre_tokenizers import Whitespace # 初始化一个 BPE 模型start/end token 可省略 tokenizer Tokenizer(BPE(unk_tokenunk)) tokenizer.pre_tokenizer Whitespace() trainer BpeTrainer( vocab_size500, special_tokens[pad, unk, cls, sep, mask] ) # 准备一个小语料文件每行一句 files [corpus_sample.txt] tokenizer.train(files, trainer) # 保存 tokenizer.save(sample_bpe_tokenizer.json)训练完成后可以做一个很有意思的对照用同一段中文文本在 vocab_size500 和 vocab_size3000 两种配置下分别看 token 数量和切分结果。通常词表越大单次编码后的 token 数越少但训练词表的成本与 embedding 参数规模会上升。这个对照能直观解释“为什么词表不能一味做大”。text 南京市长江大桥是连接南京市区与江北新区的重要通道。 encoded_low tokenizer_low.encode(text) encoded_high tokenizer_high.encode(text) print(vocab 500 token count:, len(encoded_low.ids)) print(vocab 3000 token count:, len(encoded_high.ids)) print(low tokens:, encoded_low.tokens) print(high tokens:, encoded_high.tokens)运行结果会展示出不同词表大小下 tokenizer 的行为差异。这个例子非常适合放进自己的科普内容里因为观众能直接看到可视化差异。3. tokenizer 内容制作的三个层次做 tokenizer 相关的科普不需要一次性把源码全啃下来但至少要在内容里体现三层递进概念层 - 代码层 - 问题层。3.1 概念层切分、词表和特殊 token第一层必须让读者明白 tokenizer 的作用和输出形式。很多没见过原生 tokenizer 输出的同学会误以为每个词天然对应一个 id。真正的过程是原始文本先经过归一化、预切分、对每个片段按算法进行子词切分最后查词表得到 id 列表。其中特殊 token如unk、pad、s也很容易被忽略它们在训练和推理时承担着很重要的角色。概念层的目标是让读者能解释如下问题一个 token 对应一段字符还是任意单位词表里没有的字符会怎样处理特殊 token 是不是越多越好3.2 代码层用开源库复现切分过程第二层需要展示真实代码。除了用tokenizers库训练自己的 tokenizer还可以通过transformers加载已有模型的 tokenizer观察现成大模型是怎么切中文的。这一步能让读者迅速理解“为什么同一句话在不同模型下 token 数差异很大”。from transformers import AutoTokenizer # 以常见开源中文模型为例实际使用注意模型是否公开可用 tokenizer AutoTokenizer.from_pretrained(your-model-path, trust_remote_codeTrue) text 首先我们先测试一下这段文本的 token 数量变化。 encoded tokenizer(text) print(token 数量, len(encoded[input_ids])) print(token 序列, tokenizer.convert_ids_to_tokens(encoded[input_ids]))输出中会看到有些字被拆得很碎有些常用词会保留为一个 token。这已经很接近大模型真实输入的样子了。把这个输出和训练数据构造放在一起讲前因后果会更清楚。3.3 问题层中文语料与 token 增长的坑第三层要讲到现实里更常见的问题。中文 tokenizer 的效果不只看词表里有多少个汉字还看语料统计方式。如果训练语料里大量出现的是通用新闻文本那么垂直领域词很可能被切成不稳定的组合。一个很典型的场景是“金融大模型”或“医疗大模型”用户输入一套平时不常见的专业缩写tokenizer 可能会把它切成多个碎 token后续模型很难稳定理解。另一个常见问题是 token 数膨胀。同一个句子在中文 tokenizer 下可能产生比英文多一倍的 token而很多模型又把上下文长度按 token 数计算这会造成有效信息密度下降。科普内容里应该把这个问题单独拿出来讲并给出观察方法准备同一内容的中英文版本分别 encode比较 token 数量比较相同 token 数下能承载的信息量。这些比较不是用来证明“中文模型不好”而是提醒做语料和词表优化的人模型能力的上限有一部分早在 tokenizer 阶段就被确定了。4. 从 tokenizer 到预训练和 post training 的过渡tokenizer 不是孤立组件。训练词表和 embedding 层是在模型初始化阶段完成的预训练过程不断更新 embedding 表示post training 阶段则是在预训练出来的基座之上进一步调整行为。这三者的关系是tokenizer 提供稳定的输入映射预训练获取通用语言能力post training 把模型导向特定任务或人类偏好。4.1 tokenizer 词表与模型 embedding 的关系如果要对已有模型做词表扩展例如往中文模型中加入一批领域词那么需要同步做几件工作在新词表中找出新增 token 位置并扩展 embedding 矩阵对新增 embedding 做合理初始化扩充后重新训练部分上层参数避免新旧 token 表示不一致校验扩展后的 tokenizer 是否会打乱原有文本的切分结果。这个工作并不难理解但工程上容易因为初始化和训练数据设置不当导致模型有效理解能力不升反降。相关内容在进行科普时可以列为“为什么不能随便往 tokenizer 里塞词”的引子。4.2 预训练基座是 post training 的起点从数据流来看整个大模型生命周期大致是原始语料 - tokenizer 切分 - 预训练通用能力 - 领域数据和指令 - post training能力调整与对齐其中 post training 并不是一个独立算法而是一类训练方式的总称。在科普内容里最好直接画出这个生命周期图并把每个阶段对应的数据规模和成本标出来。比起死记训练技巧先建立整体视角会更容易理解后续内容。5. post training 科普内容的骨干知识post training 涵盖从基座模型到可用对话模型之间的所有训练方式。现在最常见的是三条路线它们经常被混用但在接口层面有明确分工。5.1 持续预训练Continual Pretraining持续预训练是在基座模型上继续用大规模无标注领域语料进行训练目的在于给模型补充领域知识。它并不改变模型的问答形式和通用能力而是让模型更熟悉某个领域的表达和事实。在实现上它跟预训练的区别主要是数据来源收窄、学习率更低、训练步数更少。一个很常见的失败场景是只用极小规模领域数据去做持续预训练却期待模型从“不会该领域知识”直接变成“精通该领域知识”属于明显的期望错配。正确做法是把持续预训练当成知识补充入口后续仍需要指令数据配合。5.2 有监督微调SFTSFT 的目标是教会模型按指定格式输出。它输入的是指令和回答对本质上是在做行为塑造。例如要让模型学会输出 JSON与其在提示词里反复描述不如给几千条 JSON 格式样本直接微调。SFT 数据质量比数量重要。原因在于模型在预训练阶段已经学到大量语言表达SFT 的作用往往不是塞入新知识而是让模型学会“什么时候用什么格式回答问题”。如果 SFT 数据里出现错误事实模型可能快速记住并稳定输出错误答案这也是对齐问题里比较难处理的副作用。5.3 偏好对齐DPO 等偏好对齐做法是让模型学会比较两份回答哪个更符合人类偏好。经典实现通过强化学习或直接偏好优化在 SFT 之后进一步调整模型的输出偏好。DPODirect Preference Optimization由于训练流程更简单现在很受欢迎它的核心思路是直接在一个包含 chosen 和 rejected 答案的数据集上优化策略。{ prompt: 解释一下什么是过拟合, chosen: 过拟合是指模型在训练集上表现很好但在测试集上表现较差的现象。通常需要通过正则化、增大数据量或简化模型来缓解。, rejected: 过拟合就是训练不好模型不太行。 }上面这种三元组格式是很多开源偏好数据集的基础字段。需要说明的是chosen 和 rejected 的质量差异不能太小。两个回答其实都还不错时强行构造偏好对会让训练信号变得不稳定。下表可以加入科普内容里能帮助读者快速把握各阶段定位阶段数据形态数据量级主要目的常见风险Continual Pretraining无标注领域文本数十万到上亿条补领域知识灾难性遗忘SFT指令 期望回答数千到数十万条学习输出格式与任务行为数据质量被噪声主导DPOprompt chosen rejected数千到数十万条调整偏好方向偏好对差异过小6. post training 数据构造与实验验证方法科普内容不能只讲概念要讲验证方法。很多读者看过 post training 名词解释以后仍然不知道拿到一个开源基座模型后该怎么开始。6.1 先做小规模复现不要一开始就奔着完整调优建议最佳路径取一个 1B~7B 的开源基座准备一小批领域文本和 200~500 条 SFT 数据跑一个极短训练观察模型能否学会目标格式。这一步不是要训练出成品模型而是验证训练链路是否通畅。如果链路都不通后面所有超参讨论都没有意义。6.2 验证链路的三个手段检查 loss 下降是否正常但不要只看 loss用训练前和训练后的模型分别生成同一批问题做输出对比检查模型是不是把训练数据“背”下来了换一个类似但没见过的问题测试泛化能力。对比输出是效率最高的验证方式。在构造 SFT 数据时可以选择同一问题下的两种不同回答风格让模型通过微调学会目标风格。生成对比表格放在科普内容里直观程度很高。6.3 定义“训练前-训练后”对照实验博主或内容作者在做这一类科普时最好的内容形式不是念概念而是现场做一个对照。以下是一个通用流程适合作为实战演示脚本1. 选择一句领域性较强的用户问句 2. 记录基座模型的原始输出 3. 使用小型 SFT 数据集训练 1~2 个 epoch 4. 再次记录微调模型的输出 5. 对比两轮输出格式、信息完整度与事实正确率。如果内容目标是讲 tokenizer就换成对 tokenizer 做前后对比实验如果目标是讲 post training就以 SFT 或 DPO 为主。这个实验案例可以直接复制进自己的内容里作为系列内容的固定模式。7. 科普内容制作流程与脚本组织方案“东锡 NLP”的关键词里同时出现“从 tokenizer 开始”和“post training”说明这是一个系列内容而不是一篇零散文章。如果要做成 CSV 或图文视频内容建议按下面的流程推进。7.1 内容主线先行单集分为四段开头 30 秒给出本集要解决的问题用 3~5 分钟讲清关键概念用真实代码或数据做现场演示最后总结常见误区和下集预告。这个结构比单纯念论文或顺概念更合适国内技术社区读者。每一集都应该做到“看完能跑一个最小实验”。7.2 脚本写作时把口播文字与代码分离写科普脚本时第一稿往往是完整口播第二稿要再拆分把可执行的代码独立成块。这样拍摄、剪辑、博客排版都能有清晰素材。一个比较可复用的口播文案逻辑是先说“这一步在做什么”再说“为什么需要它”接着演示“代码怎么跑”最后解释“输出意味着什么”。这套四段式比平铺直叙更容易帮观众建立因果链。7.3 数据可视化和 Token 输出对照是核心素材做 tokenizer 科普最关键是给出可视化对照。例如输入中文句子左侧显示原始文本右侧显示切分后的 token 序列每个 token 用不同底色标出来。这段对照在界面里并不难做甚至可以用 Jupyter Notebook 直接展示。它比一张复杂理论图更有冲击力也更容易让观众理解“原来模型的输入长这样”。8. 常见问题与排查方法在做 tokenizer 和 post training 的相关实验和内容时下面这些坑是很常见的问题现象可能原因排查方式解决方案词表明明很大但领域词还是被切碎训练语料统计不覆盖领域术语打印该词的 token 序列统计词频加入领域语料重训或扩展词表同一句中文 token 数量远高于英文中文字符没被有效合并对比中英文版输入调整预分词规则考虑新增中文词 token微调后模型输出变得机械重复SFT 数据规模太小或格式单一检查训练集多样性扩充回答可能性避免单一模板SFT 之后模型在通用任务上退化训练数据偏向某一种任务增加通用指令数据比例混合通用与领域任务样本DPO 训练没有效果chosen 和 rejected 差异太小人工检查偏好对清洗数据集扩大偏好差异词表扩展后 embedding 维度不匹配只改了 tokenizer没同步扩展模型层打印模型参数量与旧权重尺寸扩展 embedding并做初始化处理笔记本或服务器上显存不足模型规模大于显存容量检查训练脚本的批次和序列长度降低 batch size、序列长度或改用小模型问题排查的核心思路是先复现再隔离变量。很多内容制作者为了“效果明显”会把实验条件设置得过于复杂最后很难定位问题。建议每次只改一个变量。9. 东锡 NLP 科普系列的实际应用建议从题目来看这个内容应该会发表在图文平台或视频平台。无论是哪种形态都建议把目标定位成“让读者完成一次最小闭环实验”而不是只看完概念就结束。所谓最小闭环实验就是读者能在本地跑起一套代码看到 tokenizer 或后训练对模型输出的真实影响。建议从以下三个方向设计成体系的内容面向快速验证型用户提供可直接运行的 notebook读者只改语料路径和模型名称就能看到效果面向理论型用户准备从词表构造到后训练流程的完整图示把每个阶段的数据规模、参数更新方式讲清楚面向实战开发用户强调代码排查和模型评估方法让读者能把这套流程迁移到自有业务数据上。内容系列化之后每一集都建议预留一个固定信息区例如统一模板当前讲解阶段tokenizer / post training 运行环境Python Transformers / tokenizers 验证方式可视化 token 切分 / 模型输出前后对比这样做的好处是读者能快速定位知识的上下文。视频开头那一两句话就可以直接交代这些信息不用每次都重新讲背景。10. 最容易忽视但在实际执行时极重要的点在结束前要再强调一个容易被科普内容跳过、但实际执行时很关键的点数据检查永远先于模型训练。很多同学在准备 post training 数据时只会检查字段是否完整不会检查文本中是否存在重复或噪音。tokenizer 阶段也有类似问题只关心词表大小却不检查最终语料被 tokenizer 切分后的结果是否合理。一个值得反复做的操练是先把待训练语料随机抽样几千条全部转换为 token 序列再对 token 长度、稀有 token 覆盖度、上下文重复率做统计。这个前置检查能在训练前就发现大量潜在问题。从这个角度来看内容科普如果只讲概念和公式读者仍然得不到真实提升。反而是把“数据检查 - tokenizer 观察 - 小规模后训练 - 输出对比”这个流程走通才能让读者在动手时少走弯路。做“东锡 NLP”这类内容时每一集哪怕只真正解决这流程中的一个小环节整体价值也会比罗列十几个术语强很多。
返回列表