ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

GPT技术路线全解析:从生成式预训练到工程落地

GPT技术路线全解析:从生成式预训练到工程落地

GPT 这个缩写放到今天,已经很难说清楚它到底是“模型名”还是“技术路线”了。把它完整展开成 Generative Pre-Training,其实是一整套训练范式的浓缩:先用海量文本把模型喂成一个“懂很多常识的说话者”,再在具体任务上做轻量调整。前阵子我重读相关资料,也在自己的几个文本生成、分类小项目里重新试了一遍预训练加微调的流程,越实践越觉得,只要把“生成式”和“预训练”这两件事的顺序想清楚,模型结构、训练技巧、参数设置这些后续问题多半都不会乱。

这篇文章我想把 GPT 这条技术路线从头到尾拆一遍:两段式训练在做什么,解码器架构为什么非这样不可,各代版本迭代时真正解决的问题是什么,以及普通人自己训练或使用时最容易忽视的坑。文章尽量不讲复杂数学公式,只用直觉和实际经验把它们串起来,适合想把语言模型原理彻底搞明白的人,也适合正在考虑把大模型接入自己项目的工程师。

1. 拆开“Generative Pre-Training”:它到底想解决什么问题

1.1 “生成式”不是在写作文,而是在学“预判能力”

Generative 这个词,字面意思是“能生成内容”,但做训练目标时,它指的是一个非常具体的操作:给定一段文字的前面部分,让模型预测下一个 token。 token 可以粗略理解成一个词、半个词,或者一个中文汉字。

举个例子,句子是“河水很深”,模型拿到“河水真”三个字,要尝试输出“深”的概率。整个过程不要求模型背诵标准答案,它只是不断从真实文本里学一件反常识的事:用前面的上下文去猜被遮住的未来内容,本质上是把语序、语法、语义、甚至部分事实知识都压缩进了模型参数里。

很多人会低估“预测下一个词”的难度。一个词后面可以接什么,受语法约束、受上下文约束、还受真实世界常识约束。比如“鲸鱼生活在_____里”,正确答案是“海洋”,能不能猜对,取决于模型是否真的理解“鲸鱼”和“海洋”的关系。所以生成式预训练用一种极朴素的方式,把无监督文本变成了一个超大训练场:不需要人工打标签,互联网上的新闻、书籍、代码、问答都是训练样本。

1.2 “预训练”解决的是知识迁移的起点问题

Pre-Training 的中文直译是“预训练”,但这个词真正的分量在“预”上。传统机器学习流程是:拿到一个任务,收集这个任务专用的标注数据,从头训练一个模型。问题是,大多数业务任务的标注数据只有几百到几万条,根本不够让大模型从零学会语言规律。

预训练的思路完全不同:先在通用大语料上训练,让模型学到语言的通用规律,然后再到某个具体任务上做二次训练。这个过程很像培养一名员工:先系统学习基础知识,再接受某个岗位的专业训练,而不是把一个完全没受过教育的人直接扔到工作岗位上摸索十年。

GPT 路线里的预训练,用的是单向语言模型目标:只根据前文预测后文。这意味着模型天然适合续写、生成、对话这类任务。后面文章会提到,这个结构选择看似简单,影响却极其深远。

1.3 五个词的标题,其实是一条完整公式

把 Generative 和 Pre-Training 连起来看,GPT 的完整工作流就是一条两段式流水线:

  • 第一阶段:在海量文本上做“预测下一个 token”的预训练,得到一个通用底座模型;
  • 第二阶段:在具体任务数据上微调,或者干脆不微调,靠提示和示例激发底座模型完成任务。

这两件事的分工非常清晰:预训练负责积累“世界知识”,微调或提示负责把知识“引出来”变成某类任务需要的输出格式。理解了这两个阶段,就已经抓住了 GPT 整个技术路线的核心骨架。

2. 两段式训练流程:先读万卷书,再练一门手艺

2.1 第一段的自回归预训练到底在算什么

自回归预训练的目标函数,说穿了就是极大似然估计。给定一段长度为 T 的文本,模型依次计算每个位置后面一个 token 的概率,然后让真实 token 的对数概率尽量高。用更直觉的话说:让模型在看完前面所有词之后,对真实下一个词的预测结果尽量自信。

实际训练时,模型不会一个字一个字地“读”,而是把一个固定长度窗口内的内容同时输入,一次性算出每个位置的概率。比如窗口长度是 512,那一次输入就能产出 511 个预测样本。这种并行计算设计极其重要,没有它,预训练的效率会低到根本无法实际落地。

我在实际项目中试过,哪怕只是带小规模语料的领域文本,自回归目标也能很快学会句法和常见搭配。但这里有个前提:语料质量必须高。如果文本里有大量重复、乱码、格式错乱,模型的 loss 会降得很顺利,但生成出来的东西会很空洞,因为它的“世界知识”大部分是噪音。

2.2 第二段微调:从“语言通才”变成“业务专员”

预训练结束后,模型已经能根据前文产生流畅文本,但它不知道“该按什么格式回答用户问题”。微调解决的是这个问题:拿一批“输入-期望输出”的示例,继续用同样的 next token 预测目标训练模型,让它在看到某类输入时,输出符合预期的文本。

以情感分类为例,预训练模型只会续写,你问“这部电影好看吗”,它可能接一句“我还没看过,不过听说评分很高”。这时在专门数据上微调,给它输入“这部电影好看吗?情感类别:”,然后期望输出“正面”,模型很快就学会把输入映射到固定类别的输出格式上。

微调和预训练用的是同一个目标函数,这点经常被人忽略。它不像传统分类任务那样输出一个类别 logits,而是把类别也当作文字来生成。好处是“生成”和“分类”被统一成一个接口,所有任务都能统一成“输入一段文字,输出一段文字”,极大降低了多任务适配的成本。

2.3 为什么不建议从零开始训练任务模型

很多刚接触深度学习的人会问:我任务就一个,数据也就几万条,为什么要多绕一步预训练?直接针对任务训练一个 Transformer 不好吗?

原因很简单:几万条数据不够学出泛化可用的语言表示。语言中的同义表达、反讽、指代、忽略不相关背景信息,这些能力都需要极大滋养。预训练底座保存的是从海量通用文本中泛化出来的编码,它的作用相当于一个“高起点”。

我在一个小数据集上试过从零训练,loss 确实能降到不错,但一遇到训练集范围外的措辞,效果立刻崩盘。后来换成在通用预训练模型上继续微调,只用十分之一的数据量就稳定超过了前者。这就是两段式训练的价值:通用底座解决“语义理解”的成本,专有数据只负责学习“任务格式和知识点”。

3. 只有解码器还不够:掩码注意力和位置编码才是 GPT 运转的骨架

3.1 为什么选解码器结构,而不是编码器

Transformer 最初是机器翻译模型,分为编码器和解码器两部分。编码器负责读完整句话后输出整体表示,解码器逐词生成翻译结果。到了 GPT 这里,作者砍掉了编码器,只用解码器堆叠。这个选择让很多人困惑:直接去掉一半结构,为什么效果反而更好?

关键在于 GPT 追求的是生成能力。解码器天然是“逐 token 产出”的架构,每一步生成都和条件语言建模一致。如果保留编码器,输入要被完整编码后喂给解码器,结构变得复杂,训练目标也不好统一。GPT 要证明的恰恰是:哪怕不依赖输入部分的双向编码,一个纯粹的自回归解码器已经能从规模中涌现出强大能力。

实际体验上,解码器模型处理任意输入时,都可以把它当成“前文”,然后继续自己写后续。这让预训练、微调、推理三个阶段共用同一个接口,工程成本大幅下降。

3.2 掩码自注意力:看不见未来,才能学会预测未来

自注意力机制的本来面目是让每个 token 都能看到全序列所有 token 的信息,包括它自己后面的内容。但对于自回归语言模型,预测当前 token 时如果看到了未来的正确答案,训练就没有意义了——那等于模型提前抄了答案。

解决办法是掩码:注意力矩阵上三角全置为零,每个 token 只能与其他位置注意力,权重只允许指向自己以及前面位置。这样一来,预测第 t 个词时,模型的信息来源只包括前 t-1 个词,和推理时的条件完全一致。

这个“训练和推理条件一致”的点特别重要。一旦不一致,模型在推理阶段会表现异常。例如训练时能看到未来,推理时看不到,模型会对未来信息形成隐式依赖,生成质量会大幅下滑。掩码自注意力就是通过强制“只看过去”,把这种不一致性从源头消除。

3.3 位置编码:让模型不至于把句子当词袋

多头注意力本身不感知顺序,把一句话里所有词打乱顺序,注意力计算出的结果完全一样。为了让模型知道“谁先谁后”,必须把位置信息加到输入里。

早期 GPT 用的是可学习位置编码,把每个位置训练一个向量,再加到 token 的 embedding 上。这种方案直观,但有局限:训练时见过的最大位置决定了推理时能支持的最大长度,超出位置范围模型可能发疯。之后的实现陆续转向相对位置编码、旋转位置编码等,核心都是让模型更擅长推断长度变化。

我在测试一个长度扩展过的模型时发现,位置编码对长文本的影响远大于短文本。短文本里,语义信息足够强,顺序乱一点影响不大;但长文本里,第 100 句和第 1000 句的位置如果没法区分,模型很快就会失去全局连贯性。所以别小看这一层,它决定了模型到底能不能从“会造句”变成“会写长文”。

4. 从第一代到多模态:GPT 系列每一次升级都在补什么短板

4.1 第一个版本完成了“从零到一”的证明

初代 GPT 参数量是 1.17 亿,放到今天连“小型模型”都算不上,但在当时最重要的贡献是证明了:先做生成式预训练,再做微调,能在多数自然语言任务上显著超过专门训练的模型。

当时很多任务模型还在为每个任务单独设计网络结构,GPT 相当于泼了一盆冷水:与其为任务设计复杂模型,不如先让模型读够足够多的书,再用通用结构微调。这种“任务无关”的通用模型思路,后来成了大模型领域的基本共识。

第一版的成功还带火了一个观念:数据规模和模型规模,比网络结构创新更能稳定提升效果。这个观念在今天看来几乎理所当然,但在当时属于很反直觉的结论。

4.2 规模变大之后:零样本和上下文学习出现了

第二代 GPT 把参数做到 15 亿,同时把预训练目标从追求分数改成追求“在无微调情况下完成任务”。当时的论文里已经出现零样本学习:不喂任何示例,直接描述任务要求,模型就能输出可接受答案。这种能力现在大家已经很熟悉,但那一代模型是最早大规模展示它的一批。

到了第三代参数达到 1750 亿,最亮眼的不是零样本,而是上下文学习:你不需要微调,只在输入里给出几个问答示例,模型就能照着样例继续做同类问题。这背后是预训练数据里天然包含大量“问答-回答”规律,模型在训练时把任务演示格式内化成了知识。

这里给个表格,方便看每代核心变化:

代际代表性参数量上下文长度最关键的变化给我的启示
第一代1.17 亿512证明预训练加微调范式有效结构和技巧不如数据和训练方式重要
第二代15 亿1024更大数据量带来零样本能力规模是能力的一部分,不只靠模型设计
第三代1750 亿2048上下文学习、少样本能力涌现足够大的模型可以直接靠提示完成任务
指令对齐版约 1750 亿2048人在回环增强对齐,模型更“听话”能力再强也要配合人类偏好校准
多模态版未完整披露明显更长图文输入、复杂推理更强质量仍然来自数据、算力和对齐的综合

4.3 从“会说话”到“会听话”:对齐的重要性

早期一代两代模型虽然也能生成流畅文本,却经常不按用户要求来,容易答非所问、堆砌废话。后来的关键改进是加入指令微调和基于人类反馈的强化学习:先让人对模型的多个回答排序,再用这些偏好信号训练一个奖励模型,最后用强化学习去更新生成模型。

严格说,这已经不是“语言模型预训练”本身的内容,而是训练流程的延伸。但它解决了 GPT 从“能生成”到“能作为产品被使用”的关键一步:模型不仅要知道答案,还要知道什么时候该答、什么时候该拒绝、语气该怎样。

在我自己的小项目里,同样一个底座模型,用了几百条高质量指令样本微调之后,用户对输出质量的满意度提升是肉眼可见的。技术味道很浓的模型不一定等于好用的模型,对齐和格式控制的权重往往被低估。

5. 预算有限时训练自己的迷你 GPT:四个容易忽略的变量

5.1 数据质量:先清洗,再去重,最后才配模型结构

很多人一上来就调模型层数、注意力头数,却忽略了数据。我在实验中发现,语料里如果存在大量重复片段,模型特别容易陷入几句话的死循环,训练 loss 看着挺漂亮,验证集上却一塌糊涂。

基本做法是字符级或 token 级 n-gram 去重。以一个很小的例子来说,如果 n-gram 长度取 8,连续出现次数超过设定阈值,说明这段文本是模板重复,可以直接过滤或降权。中文场景还要额外处理内容里的标点混乱,中文和英文空格混排等。

清洗完的数据量级会比原始数据掉百分之二十到五十,这是完全正常的。宁可少而精,不要为了凑数量把一堆低质量文本塞进去,后者会让模型学到大量错误关联。

5.2 tokenizer 和序列长度影响训练代价

token 分词方式直接决定一句中文会被切多碎。同样的意思,不同分词器可能会差出百分之二三十的 token 数,这直接影响训练成本和模型记忆长度。

我对迷你 GPT 的建议是:在选模型结构之前,先打印一批语料的 token 长度分布,确认大概需要多长的上下文窗口才能覆盖大多数样本。不要无脑把序列长度拉到 2048,很大一部分非长文本任务根本用不上。更合理的做法是先用 512 或 1024 把流程跑通,再根据实际效果决定是否扩展。

5.3 学习率、batch size 与 warmup 的经验区间

很多人自训练失败,不是结构问题,而是超参不合适。我记录下来的有效经验区间大概是这样:

超参数建议起点说明
学习率峰值3e-4 到 1e-3模型越小可以稍微偏大,越大越要调低
batch size等效 32 到 128 条样本显存不够就用梯度累积
warmup 步数500 到 2000 步防止刚开始损失爆炸
权重衰减0.01 到 0.1控过拟合,但不要贪大

如果 loss 突然跳到很大,大概率是学习率峰值过高;如果训练 loss 一直降但生成还是重复,检查数据重复和 dropout 设置。这些谈不上精巧,但非常实用。

5.4 先跑小规模闭环,再往上堆算力

很多人会把全量数据直接扔进大模型,跑了一天发现 loss 不降,才回来找原因。更稳妥的路线是先把数据截出一个小批量,用一个很小的模型快速跑几十步,确认数据管道、分词、mask 逻辑都正常,然后逐步扩大模型和数据。

这一步看起来浪费时间,实际能省几天折腾。我甚至见过有人因为 vocab 文件路径写错,白跑了一个晚上。先小规模闭环验证,就是给训练流程买保险。

6. 上生产之前,最容易翻车的三个环节

6.1 长上下文不等于长记忆

很多业务场景会把一大段客户资料或者某份长文档直接塞进提示词窗口,以为模型会自动记住关键细节。实际效果经常让人失望:模型对开头细节的引用会模糊,对中间信息的把握也时好时坏,尤其在答案需要依赖一个长文档中并不显眼的一两句话时。

原因在于注意力机制并不天然偏向“对任务最重要的内容”,它更容易被位置靠前或表述响亮的片段吸引。解决方案不是无限加长窗口,而是先做检索:把相关片段抽出来,拼成一个几千字以内的精简上下文,再交给模型。

我在这类任务上的体会是,上下文内容宁缺毋滥。掺入越多无关信息,模型越容易被带偏,输出质量下降的速度往往快过上下文量的增加速度。

6.2 微调数据的格式一致性,比数据量更关键

微调一个大模型,并不只是把问答对扔进去。我踩过比较典型的坑是:训练数据里几十种表达风格混杂,今天用“解析:”,明天用“Explanation:”,后天什么前缀都不加。结果模型学到的任务边界很模糊,上线后用户措辞稍一变化,输出就开始漂。

解决方法是先定义一套统一的输入和输出模板,把全部训练样本都转换成同一种格式。比如统一用“问题:… 答案:…”两段式,问题里保留必要的分隔标记,答案里限制开头用词。格式越一致,模型越容易学到稳定的条件映射。

数据处理阶段多做一步格式规范化,比多增加几千条杂乱样本更能提升模型最终表现。这个经验我反复验证过很多次。

6.3 幻觉要分“事实错误”和“格式错误”来治理

业界讨论最多的是事实性幻觉:模型一本正经地编造不存在的内容。解决办法不是靠微调骂一顿就能彻底解决,而是要把任务边界设置清楚。在事实回答类场景中,可以在提示里明确要求“只根据资料回答,资料中没有就说不知道”,同时在内部增加检索引用。

另一种容易被忽视的是格式性幻觉:模型像模像样地给出一个表格或 JSON,但字段名是瞎编的。这种问题更适合用“约束解码”或“结果校验”来解决,不要指望通用模型天然遵守格式契约。

我在生产项目里一般会把生成结果再做一道后置校验,凡是结构不符就直接返回错误提示并要求重新生成。这个兜底步骤虽然简单,但能把失控概率压到很低。

7. 选型判断:什么时候非 GPT 不可,什么时候反而该用简单方案

7.1 先回答三个问题,再决定要不要上大模型

第一个问题:任务是否真的需要跨领域的语义理解?比如开放式问答、文本润色、代码生成,这类任务没有固定规则,确实更适合大模型。

第二个问题:错误容忍度是多少?如果错一次可能带来严重损失,比如医疗建议、法律文书,那再强的模型也得搭配人工审核或规则校验,否则风险不可控。

第三个问题:有没有稳定的提示词和输出解析团队?大模型不是即插即用,需要有人持续调优 prompt、校准输出格式、处理失败样本。如果团队没有这个人力,模型再好也会在真实数据里翻车。

7.2 完全可以分期升级,没必要一步上最重的模型

我建议的替代顺序是:先用规则表达式和词典处理常见情况,能把准确率做到百分之八九十,就别急着上大模型;剩下的少数困难样本,再用中等规模模型做分类或抽取;只有确认问题需要开放生成,才考虑直接调用或部署大模型。

这个顺序的成本曲线很直观:规则方案几乎零推理成本,小模型可以用普通服务器跑,大模型的推理成本和服务复杂度则高一个量级。先拿简单方案兜底,把大模型用在刀刃上,是性价比最高的做法。

7.3 我的最终选型清单

  • 任务输入输出是否能被清晰枚举:能,优先走规则或小模型。
  • 是否必须生成自然语言:否,优先用分类标签或结构化输出。
  • 是否对事实精度有极高要求:是,必须配检索和人工复核。
  • 是否有足够高质量的历史问答数据:有,适合微调;没有,先用提示工程验证。
  • 每一次请求的延迟和成本预算:是否扛得住大模型推理开销。
  • 是否需要可解释的决策依据:需要,别让黑箱模型直接做最终决定。

把这些条件都过一遍,大多数业务其实只需要“轻量模型加规则”的混合方案。真正必须上大模型的场景反而没有想象中那么多。

我个人抛开理论文章再补一条经验:把 GPT 类模型当成一个知识面很广、但偶尔嘴上跑偏的同事,比把它当成无所不知的数据库更安全。明确这件事之后,很多项目设计思路都会变得更务实。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进