从Transformer到BERT与GPT:大模型构建全流程图解指南
2026/9/20 16:16:36 网站建设 项目流程

简介:一份以GPT为主线、图解大语言模型构建全流程的系统性学习资料包,主要面向刚接触NLP与大模型的开发者、科研初学者以及对Transformer架构感兴趣的工程师。包内从数据处理、模型设计到训练优化均有涉及,可帮助读者跨越理论到代码实现的鸿沟。压缩包共37个文件,其中22个Jupyter Notebook构成主线,覆盖Word2Vec、NPLM、Seq2Seq、Self-Attention、Transformer、GPT、ChatGPT等逐模块拆解,另有3个Python脚本、3个txt说明、2个Markdown、1个Word文档及若干示意图,体积仅1.54MB。目前已有179人学习下载。资源内含勘误表、附赠资源及原始笔记,适合系统自学者按章节推进,亦适合教学培训作为案例库。从词向量训练到预训练、微调、RLHF,再到OpenAI API部署,展示了完整的大模型生命周期,可帮助读者快速搭建自己的实验框架并深入理解BERT、GPT等经典模型的原生实现。 以前我学大模型,走的是典型的"收藏夹吃灰"路线:关注了一堆公众号,看到Transformer就点收藏,遇到自注意力机制就转发,结果半年过去,脑子里只剩"注意力"三个字,具体怎么算、为什么这么算,完全说不清。后来偶然拿到一套图解大模型构建全流程的资料,从零开始手把手把大语言模型的构建过程画出来,我才真正把GPT、BERT、Transformer这些概念串成了一条线。这篇文章就想把这条线重新走一遍——从自注意力机制的原理,到BERT和GPT的设计差异,再到预训练、微调、部署的全生命周期,把我踩过的坑和悟出来的道理一起说清楚。如果你也处于"看过无数文章但始终没真正理解"的阶段,这篇应该能帮你把拼图拼上。

1. 为什么我决定"从零手写"而不是直接调现成框架

1.1 这份图解资料解决的最大痛点

现在的开源生态太丰富了,HuggingFace上随便一拉就有现成的BERT、GPT权重,几行代码就能跑起来做推理。但问题恰恰出在这里:当你习惯了"调用即所得",对模型内部发生的计算就没有任何感知。就像一个人天天开车,但对发动机工作原理一无所知,车子一旦出问题就只能拖去修理厂。

我见过太多这样的同行:简历上写着"熟练使用BERT、GPT",但问你自注意力机制里Q、K、V各自的维度关系,他答不上来;问你为什么要除以根号d_k,他也一脸茫然。这不怪个人能力,怪的是学习路径——整个行业都太强调"用",太轻视"造"。

那套图解资料给我的第一个启发是:真正有效的学习路径应该是"先造一遍,再用起来"。不用真的训练出一个几百B的大模型(那也不现实),而是把最小版本的Transformer写明白、画清楚,理解每一个张量在每个步骤的形态变化。这个过程走完,后面所有框架都只是实现细节的差异,核心思想你已经掌握了。

1.2 一个反直觉的结论:手写比调参更能建立全局观

我最初也以为,从零手写意味着更多的数学、更复杂的代码,对日常工作帮助不大。实际做完之后才发现完全相反。

手写一遍的意义不在于让你成为模型科学家,而在于给你一张"全局地图"。当你看着每一层的张量shape变化,你会理解为什么embedding维度通常是512或768,为什么前馈网络要先把维度放大四倍再压缩回来,为什么层归一化放在残差连接之后(Pre-LN而不是Post-LN)会让训练更稳定。这些知识在调参时很难体会,但在手写过程中会自然地浮现出来。

另一个反直觉的点是:手写过程中最难的不是实现,而是"画图"。把注意力机制画成流程图时,你必须精确到每一步的张量形状;把位置编码可视化时,你会看到不同频率的正弦波如何在数值上区分token顺序。这种"用图画逼迫自己精确"的方式,比读十遍论文都管用。

2. Transformer架构拆解:自注意力机制到底在算什么

2.1 从一句"你不认识我"理解Q、K、V

自注意力机制是Transformer的心脏,也是很多人第一道坎。网上的教程都喜欢甩公式:Attention(Q,K,V) = softmax(QK^T/√d_k)V。公式本身不难,难的是理解Q、K、V这些向量到底在做什么。

我自己琢磨出一个比较好懂的生活化类比:想象你在一个派对上,想找到最值得聊天的人。你会先看每个人的"名片"(Key,代表这个人是谁),再跟自己心里的"需求清单"(Query,代表我想找什么样的人)做匹配。匹配分数最高的几个人,你才会认真听他们说话,并结合他们的"内容"(Value)来更新自己的认知。

放到文本场景里,每个token都会生成三个向量:Query是"我在找什么信息",Key是"我能提供什么信息",Value是"我实际携带的信息内容"。自注意力机制做的事情就是:让序列里的每一个token,都能根据Query和所有token的Key计算相似度,然后用这些相似度作为权重,对所有的Value做加权求和。这一步做完,每个token的表示就不再孤立,而是融合了整个序列的信息。

2.2 注意力权重的计算流程:图解里那张表的读法

图解资料里有一张经典的注意力权重矩阵图——一张方方正正的格子图,横轴纵轴都是序列里的token,格子颜色深浅代表注意力权重的大小。很多人匆匆扫一眼就翻过去了,其实这张图包含了大量信息。

以"苹果"这个词为例。在"我爱吃苹果"和"苹果公司发布了新手机"这两个句子里,模型对"苹果"这个词需要关注的内容截然不同:前一句应该更多关注"吃"这个动作,后一句则应该关注"公司""发布"这些商业语境词汇。注意力矩阵就是把这些关注关系显式地画出来了。

计算流程可以拆解成四步:

  1. 每个token通过三个权重矩阵W_Q、W_K、W_V,把自己的输入向量分别映射成Q、K、V三个向量。
  2. 计算所有token两两之间的注意力分数,也就是Q和K的点积。点积越大,说明这两个token在向量空间里越"相关"。
  3. 对所有注意力分数进行缩放,然后过softmax归一化。缩放是因为点积的数值会随着维度增大而增大,如果不处理,softmax会进入饱和区,梯度变得极小。
  4. 用归一化后的注意力权重对V进行加权求和,得到每个token的新表示。

这四步走完,就完成了一次"全局信息交互"。而且注意,这个交互是一次性、直接连接的——任意两个位置的token不管距离多远,计算路径长度都是1。这就是Transformer相比RNN最大的优势:RNN要把信息一步步传过去,距离一长就容易丢失,而Transformer天然就解决了长距离依赖问题。

2.3 为什么需要缩放点积:数值稳定性问题

关于"为什么除以√d_k",这是面试高频题,也是图解里特意标注的一个细节。我在初学时觉得这只是工程技巧,深入了解后才发现这是一个典型的数值稳定性和梯度问题。

Query和Key的维度是d_k,假设向量里每个元素都是均值为0、方差为1的独立随机变量,那么Q和K的点积(也就是对d_k个乘积求和)的均值是0,方差是d_k。这意味着什么?当d_k比较小(比如64),点积的方差也在可接受范围内;但当d_k增大到几百甚至上千,点积的方差会变得非常大。

方差大有什么问题?softmax对输入非常敏感,输入里的最大值和最小值差距过大,softmax的输出会迅速逼近one-hot分布——最大的那个值接近1,其他值接近0。这样的注意力分布太"尖锐",意味着每个token只关注极少数几个位置,梯度也会变得极其稀疏。把它恢复到与维度无关的尺度,方差重新变回1,softmax的输出就不会过早饱和。

这个细节很有代表性:很多看似"多此一举"的设计,背后是训练稳定性的深坑。如果你想去掉这个缩放项试试,在模型深度较浅时可能没感觉,一旦层数堆到12层、24层,loss曲线会给你上一课。

3. 多头注意力与位置编码:图解里最容易跳过的两个细节

3.1 多头不是"多个注意力"那么简单

第一次看图解时,我把多头注意力理解成"把多个独立的注意力机制并行跑一遍,然后拼接结果"。这个理解不算错,但如果只理解到这个层面,就会错过关键点。

多头注意力的核心价值在于:不同的头可以关注不同类型的关系。实验和可视化结果几乎都能看到这样鲜明的分工——有的头专门关注句法依赖关系(比如名词和修饰它的形容词),有的头关注指代关系(比如代词"它"指向的先行词),有的头关注位置邻近关系,而在翻译任务里甚至会有头往"对齐方向"倾斜。这种分工不是我们显式指定的,而是模型在训练中自己涌现出来的。

具体实现上,输入向量会被投影到h个不同的低维子空间(每个头的维度通常是d_k = d_model / h),每个头独立计算注意力,最后把所有头的输出拼接起来,再经过一个线性变换。整个过程引入的参数量几乎没增加,但模型的表达能力成倍增强——因为它允许同一个token在不同关系维度上同时"分心"。

我建议动手画一画多头的图解:把输入矩阵和每个头的W_Q、W_K、W_V列出来,走一遍8个头各自的注意力计算,再看拼接后的形状如何恢复成与输入一致。这一步画完,"多头"就不再是一个神秘词语。

3.2 位置编码:让Transformer知道词序的巧妙设计

自注意力机制本身是位置无关的——如果把一句话的token顺序打乱,注意力计算的结果完全一样(只是输出的顺序跟着变)。但对于语言来说,词序是核心语义的一部分,"我打你"和"你打我"完全不是一回事。所以Transformer必须额外引入位置信息。

图解里通常会画一张非常漂亮的正弦波位置编码图:横轴是token位置,纵轴是编码维度,每个维度上是不同频率的正弦或余弦波。这种设计的精妙之处在于:

  • 不同位置会得到不同的编码向量,模型能区分顺序;
  • 正弦函数的线性变换性质让模型容易学会"相对位置"关系:位置p+k的编码可以表示为位置p编码的某种线性函数,这让模型天然具备外推到更长序列的能力(虽然实际外推效果还需要打折扣来看);
  • 编码值被限制在[-1,1]区间,不会给embedding叠加过大的数值干扰。

后来更常用的做法是RoPE(旋转位置编码)等相对位置编码方案,它们在长文本场景下表现更好。但理解经典的正弦位置编码,仍然是理解一切位置编码变体的基础。图解资料里那张正弦波图,真的值得你停下来仔细看五分钟。

4. BERT与GPT:同一套架构下的两种进化路线

4.1 BERT的"完形填空"与双向上下文

有了Transformer这个地基,模型就开始分叉了。我学BERT时最大的误区是把它当作一个全新的架构,其实它只是Transformer的Encoder部分,核心创新在预训练任务上——Masked Language Model。

简单说,就是在训练时随机把输入中15%的token用[MASK]遮挡掉,让模型根据上下文预测被挡住的词。这就像在做完形填空:为了填出空格,模型必须同时利用左边的词和右边的词,也就是"双向上下文"。正是因为这种双向特性,BERT非常适合做理解类任务:文本分类、命名实体识别、句对匹配、阅读理解、语义相似度计算等等。

以经典的句子对任务为例,BERT的输入除了token embedding和位置编码,还有一个segment embedding用来区分前后两个句子,句子之间用[SEP]分隔,开头加[CLS]。预训练时除了MLM还有一个Next Sentence Prediction任务,虽然这个任务在后来的改进中被证明帮助不大甚至有害(比如RoBERTa就去掉了它),但了解这个设计能帮助你理解BERT在句对任务上的输入结构。

BERT把模型的"理解能力"做到了那个时代的极致。使用场景也很明确:你手里有一堆标注好的任务数据,想要一个强语义理解底座来抽取特征、做分类,BERT类模型就是首选。下游任务微调的成本相对低,因为Encoder不需要生成文本,只需要输出表示。

4.2 GPT的自回归与生成能力

GPT走的是另一条路——只用Transformer的Decoder部分,预训练任务是标准的语言模型:给定前文,预测下一个词。这就是自回归范式。预测只能看到左侧的上下文,不能看到右侧,因此在自注意力计算时会有mask,把未来的位置全部遮蔽掉。

这种"单向"限制看似是缺陷,却意外带来了强大的生成能力。因为语言本身天然是序列生成的过程,GPT的做法和"写文章"这件事高度一致:一个字一个字往出蹦,每一步都基于已经写过的全部内容来推断下一个词。

这也是为什么GPT适合做生成类任务:文本续写、对话、代码生成、摘要生成。ChatGPT的强大,本质上是"自回归语言模型 + 大规模数据 + 人类反馈对齐"三者的乘积。很多人问为什么BERT不能做chat,原因就在训练目标的根本差异上——BERT的完形填空训练出来的表示能力更均衡,但要让模型自己一个字一个字地写完整文章,它并不擅长。

值得强调的是,GPT的"单向"不是说它在理解上就弱。模型层数、参数量、训练数据量堆到一定规模之后,Decoder在"预测下一个词"这个看似简单的任务上被迫学会了海量的语言知识和世界常识。这也解释了为什么GPT系列的参数量和预训练数据规模一直在疯狂增长——它就是在用最简单的目标逼模型学到最复杂的能力。

4.3 选择路线的核心判断标准

如果你要为实际项目选基座模型,我的建议是记住这个原则:理解任务选Encoder类模型,生成任务选Decoder类模型。虽然现在的大模型时代GPT风格的Decoder-only架构几乎一统天下(甚至很多做理解任务的方案也都直接用LLM),但在中小规模、限定场景、对响应速度和资源消耗敏感的生产环境中,BERT/RoBERTa/DeBERTa这类模型仍然有不可替代的位置。

我见过太多人一上来就要用LLM做文本分类,结果发现:一次推理要跑0.5秒,而用BERT只需要20毫秒;一轮微调要8张A100,而用BERT一张消费级显卡就行。技术选型不是越新越好,而是在效果、成本、延迟之间找平衡点。

5. 从训到用:预训练、微调、部署全流程踩坑记录

5.1 预训练:数据和算力是最大的现实问题

预训练这一步,首先要清醒:除非你有实验室级别的算力,否则不要试图从头训练一个大模型。图解的课程之所以手把手带你走一遍预训练,是为了让你理解数据怎么采样、loss怎么算、梯度怎么回传,而不是让你真的去复现GPT-3。

我在预训练这个小规模模型时踩过的坑主要有三个:

  1. 数据清洗不到位。语料里重复句子太多,模型容易产生"复读机"倾向,生成内容变成循环。解决方式是加去重逻辑,并且在采样时屏蔽掉重复度高的连续片段。
  2. 学习率预热没做。刚开始训练时模型参数是随机的,梯度更新幅度过大会导致早期loss震荡。用warmup把学习率从0线性升到目标值,前几千步会稳很多。
  3. loss曲线看不出"过拟合"还是"欠拟合"。小规模语料训练时,val loss比train loss低很正常(因为dropout),但如果gap持续扩大,说明开始过拟合,需要加权重衰减或者增大dropout。

从零预训练在本地做小规模实验还有一个好处:你会对"模型到底在学什么"有直观感受。比如loss掉到某个阈值时,模型开始能拼对单词;再往下,才开始出现语法结构;最后才是语义层面的连贯。这个"从记忆到语言"的演化过程,只看别人训练的曲线是体会不到的。

5.2 微调:显存不够时的实用策略

大多数人的实际工作是微调,而不是预训练。微调阶段最大的敌人是显存。我在16GB的显卡上调7B模型,默认做法必然OOM,后来是这么组合解决的:

  • LoRA:冻结原模型参数,只训练低秩分解的两个小矩阵。参数量直接降到原来的0.1%到1%,显存占用大幅下降。
  • 梯度累积:显存不够不代表不能模拟大batch。多次前向反向累积梯度,到指定步数再更新一次参数,效果等价于增大batch size。
  • 混合精度训练:用fp16或bf16做前向反向计算,显存占用几近减半,同时因为精度降低,训练显存还能挤一挤。注意bf16在部分显卡上效果比fp16更稳。

LoRA有个实践经验值得分享:秩r的选择对效果的影响没有想象中大。r=8和r=64在多数任务上的差距远小于数据质量和任务适配度的影响。与其盲目调r,不如把精力花在构造高质量微调数据上——这句我强调多少遍都不为过。微调不是炼丹,数据才是真正的配方。

5.3 部署:从ollama到企业级的几个选择

部署是整个流程里"看起来最简单、做起来最头大"的环节。我自己先在本机用ollama跑通了7B模型的推理,整个过程非常顺畅:下载量化后的GGUF格式模型,一条命令就起了一个本地服务,API兼容OpenAI格式,直接就能用curl调用。这种方式做原型验证、个人应用、内部工具完全够用。

但要上生产,问题就来了:

  • 单卡推理太慢:7B模型fp16在消费级显卡上生成速度可能只有10-20 token/s,如果要做流式输出,体验勉强能接受,但并发一上来就全卡死。
  • 量化格式的选择:GPTQ适合GPU推理,AWQ在部分场景下表现更好,GGUF则兼顾CPU和GPU混合部署。没有绝对的最优,只有针对你的推理硬件的适配。
  • 高并发服务:需要上vLLM、TensorRT-LLM这类推理加速框架,用PagedAttention做KV Cache管理,配合continuous batching提升吞吐。这一步没有银弹,只能根据你的模型规模、硬件配置和延迟要求逐个压测调参。

部署阶段我最大的心得是:先想好你要多少并发,再决定方案。个人工具用ollama就行,几十并发就要考虑vLLM,几百并发则要上多卡推理和负载均衡。很多团队一上来就上K8s,最后发现瓶颈根本不在编排层,而是显卡数量不够——架构过度设计比简单方案堆砌问题更隐蔽。

6. 学习路线复盘:先画图,再写码,最后才谈炼丹

6.1 我推荐的构建顺序

被那套图解资料"带进门"之后,我重新整理了自己的学习体系,现在如果有人问我大模型该怎么学,我会给出下面这个顺序:

  1. 手画Transformer架构图。不要看别人画好的,自己拿一张A4纸,从embedding开始,把多头注意力、残差连接、层归一化、前馈网络、最后的softmax输出一层层画出来。画的时候务必标出每个张量的shape变化,卡住了就回去翻论文。
  2. 用PyTorch写一个最小Transformer。代码不要抄,真的一行行写。写完后用玩具语料训练,观察loss下降,然后用它做生成。模型不用大,两层、四头、128维embedding足够了,目标是理解而不是效果。
  3. 跑通BERT和GPT的微调流程。用HuggingFace加载预训练权重,分别做一次文本分类微调和一次文本生成微调。对比两种模型在输入输出结构上的差异,体会为什么说"架构源于同一个底子,走向却完全不同"。
  4. 理解全生命周期的资源边界。预训练需要什么量级的数据和算力,微调在显存上的瓶颈在哪,部署在不同并发下应该选什么方案。这些不需要全部亲手做一遍,但要知道边界在哪里。
  5. 回到论文,带着问题精读。这时候再读"Attention Is All You Need",读到每个细节你都会有"原来如此"的感觉,因为那些抽象符号你已经用自己的手和脑走过了一遍。

6.2 最后分享几个实际体会

如果说这几年在大模型这条路上踩坑总结出了什么,能放在最前面说的有三条。

第一,不要被术语吓住。自注意力机制、多头注意力、位置编码、预训练、微调……这些名词拆开看都不可怕,它们背后都是非常朴素的直觉:让模型有选择地关注信息、记住顺序、先学通用知识再学具体任务。术语是经验的压缩包,解压之后内容并不多。

第二,动手画图和动手写代码,比读多少文章都管用。图解资料的价值就在于它强迫你把抽象概念空间化、视觉化。很多你觉得"懂了"的概念,一旦让你画出来或者写出来,马上就会发现漏洞。补上这些漏洞的过程,才是真正的学习。

第三,从零构建的意义在于获得"可控感"。今天的大模型生态已经足够成熟,成熟到你可以完全不懂原理就把产品做出来。但这种"不懂也能用"的便利也在悄悄剥夺你对系统的掌控力——当模型表现不佳时,你不知道该调数据、调架构还是调训练策略,只能盲目试错。拥有"从零构建"这层功力,你就能给自己的问题做出有根据的假设,而不是瞎猜。

现在再回头看,那套图解的标题里"全流程"三个字是最重要的。它没有只讲Transformer原理,也没有只讲部署,而是把从架构设计到训练调优到部署上线的完整链路串了起来。这种全局视角,恰恰是行业里最稀缺的东西。希望你也找个周末,拿张白纸,从attention开始画起。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询