资讯动态

从词向量到Transformer:AI大模型原理与PyTorch实现

发布时间:2026/8/30 17:40:06 来源:尧图企业网站定制
如果你刚开始接触 AI 大模型打开一篇论文或者一份源码时大概率会同时遇到这几个词词向量、自注意力、Transformer、预训练、微调。它们之间到底是什么关系为什么大家都在强调 Transformer而不是更早的 RNN 或者 CNN要从零建立一条清晰的技术脉络最好的方式不是直接读论文而是沿着 AI 大模型背后的原理线走一遍词向量解决什么问题注意力机制解决什么问题Transformer 又是如何把两者融合成可扩展的大模型底座。这篇文章会以“动画急速入门”的思路用尽量直观的方式拆解这条主线并给出一个基于 PyTorch 的简化版 Transformer 实现帮助你从代码层面验证对原理的理解。文章内容偏入门适合刚接触大模型、准备转向 NLP 方向或者想弄懂 GPT 和 BERT 底层逻辑的开发者阅读。1. 背景与核心概念1.1 为什么大模型要从词向量讲起计算机本身不理解自然语言。我们需要把文字转换成一种计算机可以计算的表示这个转换过程就是“词向量”要做的事情。所谓词向量简单理解就是把一个词映射成一个固定长度的数值向量例如“苹果”可能被表示成[0.1, 0.5, -0.2, ...]。早期做法是 One-Hot 编码也就是给词典里的每个词分配一个独立位置这个词所在位置为 1其余位置为 0。但这种表示有两个严重问题维度灾难词典越大向量维度越大存储和计算开销非常高。语义鸿沟任意两个词的 One-Hot 向量都是正交的无法表达“苹果”和“水果”在语义上的相近关系。如果能用连续的低维向量表示词并且让语义相近的词在向量空间里距离更近那计算机就能更好地理解语言。这就是词向量Word Embedding的核心思想。1.2 从静态词向量到上下文词向量在 AI 大模型时代我们经常听到“上下文理解”这个词。传统词向量是静态的也就是一个词无论出现在什么句子里它的向量都是同一个。比如“我在银行办业务”和“河岸边种了很多银行”中的“银行”传统词向量无法区分。后来预训练语言模型引入上下文相关的词向量同一个词在不同句子中会得到不同的向量表示。这种“动态词向量”正是 Transformer 类大模型的核心能力之一。理解了这个递进关系再看大模型原理就会清晰很多。2. 词向量让机器理解语言的第一步2.1 One-Hot 编码的局限性先看一个最朴素的思路假设词典里有四个词“猫”“狗”“鱼”“鸟”。用 One-Hot 表示词向量猫[1, 0, 0, 0]狗[0, 1, 0, 0]鱼[0, 0, 1, 0]鸟[0, 0, 0, 1]这种编码方式虽然简单但“猫”和“狗”都是宠物向量距离却和“猫”与“鱼”一样远。计算机完全看不出词与词之间的语义关系。2.2 Word2Vec 的核心思想Word2Vec 是 2013 年前后提出的经典词向量方法它提出了一个很关键的假设一个词的含义可以由它周围的词来决定。也就是“You shall know a word by the company it keeps”词的语义由它的上下文决定。Word2Vec 有两种训练方式CBOWContinuous Bag of Words用上下文词预测中心词。Skip-gram用中心词预测上下文词。训练完成后模型隐层得到的权重矩阵就可以作为词向量表。一个经典例子是vector(国王) - vector(男人) vector(女人) ≈ vector(王后)这说明词向量在一定程度上捕捉到了词之间的类比关系。除了 Word2VecGloVe 也是常用的静态词向量方法它利用全局词共现统计信息来训练词向量在处理某些任务时比 Word2Vec 更稳定。2.3 静态词向量的问题静态词向量最大的问题是没有上下文。由于一个词只有一个固定向量无法处理一词多义。此外静态词向量无法感知词序比如“猫追狗”和“狗追猫”如果用词向量简单相加得到的句子表示会非常接近但语义完全相反。这促使研究者开始思考能不能设计一种结构让模型在读取句子时根据上下文动态调整每个词的表示。这就引出了循环神经网络 RNN以及后来的注意力机制和 Transformer。3. 从 RNN 到注意力机制3.1 RNN 如何处理序列RNNRecurrent Neural Network循环神经网络是一种适合处理序列数据的结构。它的核心思想是按时间步逐个读取输入并维护一个隐藏状态h_t每一步的隐藏状态都会传递给下一步。RNN 在机器翻译、文本生成等任务上取得了不错的效果但它存在明显的短板当序列很长时早期信息经过多步传递后会被逐步稀释出现长距离依赖问题。你让模型翻译一个 50 个词的句子句首的主语信息可能传到句尾时已经很弱了。另一个问题是梯度消失。在反向传播过程中梯度需要沿着时间步反向传递经过多次连乘后梯度会指数级缩小导致模型难以学习到远距离依赖关系。3.2 LSTM 与 GRU 的改进LSTMLong Short-Term Memory长短期记忆网络通过引入“门控机制”来缓解长距离依赖问题。它用遗忘门、输入门和输出门控制信息的保留与更新让模型可以选择性记住重要信息。GRU 是 LSTM 的一种简化版本参数更少训练更快。但即使是 LSTM本质上仍然是逐步传递信息无法解决“并行计算”和“全局依赖”这两个核心问题。RNN 系模型必须按时间步串行计算训练效率低同时信息传递链条太长远距离依赖仍然受限。3.3 注意力机制的出现2014 年前后研究者开始把注意力机制引入 seq2seq 模型。注意力机制的核心思想是在生成输出时不把全部信息压缩在一个固定向量里而是动态地关注输入序列中更相关的部分。具体来说注意力机制会计算三组向量Query查询向量当前需要关注什么。Key键向量被用来匹配查询。Value值向量真正被提取的信息。先计算 Query 和每个 Key 的相似度得分再用 softmax 转成权重最后对 Value 加权求和。这样模型在每一步生成时都能“重点关注”输入中的某些位置而不是机械地按顺序记忆。当这种注意力机制被应用在“序列自身”上也就是一个句子里的每个词都去关注句子里的其他词就形成了自注意力Self-Attention。自注意力正是 Transformer 的核心组件。4. Transformer 架构拆解4.1 为什么最终是 Transformer一句话总结Transformer 用自注意力机制替代了 RNN 的循环结构既解决了长距离依赖问题又实现了并行计算。输入序列中的所有 token 可以同时进入自注意力层彼此之间直接计算关联不需要逐步传递。这让 Transformer 在训练效率上远超 RNN也让它能捕获更远距离的依赖关系。GPT、BERT 以及各种大模型本质上都是基于 Transformer 的不同形式构建的。4.2 自注意力机制详解自注意力计算过程可以分为四步对输入序列中的每个 token分别通过三个线性变换得到 Query、Key、Value 向量。计算 Query 和所有 Key 的点积得到注意力得分。将得分除以sqrt(d_k)做缩放然后通过 softmax 归一化为权重。用权重对 Value 加权求和得到当前 token 的输出表示。缩放的原因是为了防止点积结果过大导致 softmax 进入饱和区梯度变得很小。下面是一个最简化的自注意力计算示意帮助你理解矩阵形状变化import torch import torch.nn.functional as F # 模拟 1 个 batch、3 个词、每个词 8 维 x torch.randn(1, 3, 8) # 随机初始化 Q、K、V 线性层没有偏置 W_q torch.randn(8, 8) W_k torch.randn(8, 8) W_v torch.randn(8, 8) Q x W_q # (1, 3, 8) K x W_k # (1, 3, 8) V x W_v # (1, 3, 8) scores torch.matmul(Q, K.transpose(-2, -1)) # (1, 3, 3) d_k K.size(-1) scores scores / (d_k ** 0.5) attn_weights F.softmax(scores, dim-1) output torch.matmul(attn_weights, V) # (1, 3, 8)从输出可以看到每个 token 的输出都是由整个序列加权融合而来的这就是自注意力实现全局依赖的方式。4.3 多头注意力机制为了让模型能够从不同子空间捕获信息Transformer 使用了多头注意力Multi-Head Attention。它将 Q、K、V 分割成多份分别做注意力计算再把结果拼接起来。举个例子假设模型维度d_model 512注意力头数num_heads 8那么每个头的维度就是512 / 8 64。不同的头可能分别关注语法关系、指代关系、语义相似度等信息这比单个注意力头表达能力更强。多头注意力的计算逻辑在 6.3 节的完整代码中会有体现。4.4 位置编码自注意力本身不感知顺序因为它的计算只是加权求和和词的先后位置无关。为了让模型知道词的顺序信息Transformer 在输入向量上叠加了位置编码Positional Encoding。原始论文使用正弦和余弦函数生成位置编码PE(pos, 2i) sin(pos / 10000^(2i/d_model)) PE(pos, 2i 1) cos(pos / 10000^(2i/d_model))其中pos是词在句子中的位置i是向量维度下标。这种编码方式有几个好处值域在 [-1, 1] 之间适合与词向量相加。对不同长度的序列都有一定的外推能力。正弦、余弦的周期性让模型可能学习到相对位置关系。在后来的大模型实践中很多模型改用了可学习的位置编码或旋转位置编码RoPE但核心目的是一致的给模型补充位置信息。4.5 残差连接与层归一化Transformer 的每个子层外面都会接一个残差连接然后再做层归一化。残差连接的作用是让梯度可以跨层直接回传缓解深层网络训练难的问题。层归一化则是为了避免训练过程中数据分布不稳定。整个 Transformer Block 的处理顺序可以概括为输入 x → 多头自注意力 → 残差连接x x attention_output → 层归一化 → 前馈网络 → 残差连接x x ffn_output → 层归一化 → 输出这种“注意力 前馈网络 残差 归一化”的组合就是 Transformer 的基本构建单元。大模型通过不断堆叠这样的层数来提升表达能力。5. 从 Transformer 到 AI 大模型5.1 Encoder、Decoder 与预训练范式原始的 Transformer 论文提出的是 Encoder-Decoder 结构Encoder 负责理解输入Decoder 负责生成输出。这个结构后来发展出了两条不同的技术路线BERT 路线只使用 Encoder适合理解类任务比如文本分类、命名实体识别、语义相似度。GPT 路线只使用 Decoder适合生成类任务比如对话、文章续写、代码生成。现在的 GPT 系列大模型本质上都是基于 Transformer Decoder 的堆叠。Decoder 通过掩码自注意力Masked Self-Attention保证在生成第t个词时看不到后面未来的词。5.2 为什么“大”就有智能大模型的“大”主要体现在三个维度参数规模大从早期的亿级参数到现在的千亿甚至万亿级参数。训练数据大使用海量互联网文本进行预训练。计算资源大需要大量 GPU/TPU 集群这也是本地部署 AI 大模型成本较高的原因。参数规模提升后模型能记住更多语言模式也能在遇到从未见过的新任务时表现出一定的“涌现能力”。但从原理层面看它依然是“用海量数据训练 Transformer在给定上文时预测下一个词”这一核心逻辑。5.3 大模型应用开发与学习路线如果你想进入 AI 大模型方向推荐的学习路线可以按这个顺序走掌握 Python 和 PyTorch 基础。理解词向量与 RNN、注意力机制的原理。亲手实现一个简化版 Transformer也就是本文第 6 部分的内容。阅读 BERT 或 GPT 的源码与论文。学习 Hugging Face Transformers 库跑通预训练和微调流程。尝试大模型应用开发例如提示词工程、RAG 知识库、模型微调、大模型 API 调用等。这条路线不追求一次吃透所有细节重点是边学边动手验证。6. 动手实践用 PyTorch 实现一个简化版 Transformer为了验证前面的原理这里给出一个可运行的简化版 Transformer 实现包含位置编码、自注意力、多头注意力和 TransformerBlock并用一个小例子演示前向计算过程。6.1 环境准备本文示例代码基于以下环境编写实际使用时需要根据你的环境微调版本依赖说明Python 3.9推荐使用 3.10 或以上版本PyTorch 2.xCPU 版本即可运行示例numpy一般随 PyTorch 自动安装安装 PyTorch 可以参考官方命令这里不再贴安装步骤直接进入代码编写。6.2 实现位置编码位置编码的作用是给输入序列加入顺序信息。我们用正弦和余弦函数生成固定位置编码并在前向计算时叠加到输入向量上。# 文件路径positional_encoding.py import torch import math class PositionalEncoding(torch.nn.Module): def __init__(self, d_model: int, max_len: int 5000): super().__init__() # 生成 shape 为 [max_len, d_model] 的位置编码矩阵 pe torch.zeros(max_len, d_model) position torch.arange(0, max_len, dtypetorch.float).unsqueeze(1) # 计算 10000^(2i/d_model) 的对数形式避免数值溢出 div_term torch.exp( torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model) ) # 偶数维度用 sin奇数维度用 cos pe[:, 0::2] torch.sin(position * div_term) pe[:, 1::2] torch.cos(position * div_term) pe pe.unsqueeze(0) # [1, max_len, d_model] self.register_buffer(pe, pe) def forward(self, x): # x: [batch_size, seq_len, d_model] return x self.pe[:, : x.size(1)]这里使用register_buffer注册位置编码它会被自动移动到模型所在的设备上且不会参与梯度更新。6.3 实现多头自注意力多头自注意力是整个 Transformer 的核心。下面代码把 Q、K、V 拆分成多个头分别计算注意力后再拼接并通过输出线性层。# 文件路径multi_head_attention.py import torch import torch.nn as nn import math class MultiHeadAttention(nn.Module): def __init__(self, d_model: int, num_heads: int): super().__init__() assert d_model % num_heads 0, d_model 必须能被 num_heads 整除 self.d_model d_model self.num_heads num_heads self.d_k d_model // num_heads self.W_q nn.Linear(d_model, d_model) self.W_k nn.Linear(d_model, d_model) self.W_v nn.Linear(d_model, d_model) self.W_o nn.Linear(d_model, d_model) def forward(self, x, maskNone): batch_size, seq_len, _ x.size() # 1. 线性变换后拆分为多头 Q self.W_q(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2) K self.W_k(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2) V self.W_v(x).view(batch_size, seq_len, self.num_heads, self.d_k).transpose(1, 2) # 2. 计算缩放点积注意力得分 scores torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k) # 3. 如果提供 mask则掩盖指定位置 if mask is not None: scores scores.masked_fill(mask 0, -1e9) attn_weights torch.softmax(scores, dim-1) # 4. 对 V 加权求和并还原形状 context torch.matmul(attn_weights, V) context context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model) # 5. 输出线性变换 output self.W_o(context) return output这段代码需要重点理解的是 Q、K、V 的形状变化输入x为[batch_size, seq_len, d_model]。线性变换后通过view拆成[batch_size, seq_len, num_heads, d_k]。transpose(1, 2)后变成[batch_size, num_heads, seq_len, d_k]方便并行计算每个头。6.4 实现前馈网络与 TransformerBlock前馈网络是一个简单的两层全连接中间使用 ReLU 激活。TransformerBlock 则把多头注意力、前馈网络、残差连接和层归一化组合起来。# 文件路径transformer_block.py import torch.nn as nn from multi_head_attention import MultiHeadAttention class FeedForward(nn.Module): def __init__(self, d_model: int, d_ff: int): super().__init__() self.fc1 nn.Linear(d_model, d_ff) self.fc2 nn.Linear(d_ff, d_model) self.relu nn.ReLU() def forward(self, x): return self.fc2(self.relu(self.fc1(x))) class TransformerBlock(nn.Module): def __init__(self, d_model: int, num_heads: int, d_ff: int, dropout: float 0.1): super().__init__() self.attention MultiHeadAttention(d_model, num_heads) self.ffn FeedForward(d_model, d_ff) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.dropout nn.Dropout(dropout) def forward(self, x, maskNone): # 第一路子层多头注意力 残差连接 LayerNorm attn_output self.attention(x, mask) x self.norm1(x self.dropout(attn_output)) # 第二路子层前馈网络 残差连接 LayerNorm ffn_output self.ffn(x) x self.norm2(x self.dropout(ffn_output)) return x可以看到每个子层都遵循“先计算再加残差再归一化”的顺序。这是 Transformer 能够训练得很深的关键之一。6.5 组合成简单的 Transformer Encoder接下来把这些模块组合成一个简化版 Transformer Encoder并用随机输入验证前向传播。# 文件路径simple_transformer.py import torch import torch.nn as nn from positional_encoding import PositionalEncoding from transformer_block import TransformerBlock class SimpleTransformerEncoder(nn.Module): def __init__(self, vocab_size: int, d_model: int, num_heads: int, d_ff: int, num_layers: int, max_len: int 512): super().__init__() self.embedding nn.Embedding(vocab_size, d_model) self.positional_encoding PositionalEncoding(d_model, max_len) self.layers nn.ModuleList([ TransformerBlock(d_model, num_heads, d_ff) for _ in range(num_layers) ]) def forward(self, token_ids): x self.embedding(token_ids) x self.positional_encoding(x) for layer in self.layers: x layer(x) return x # 模拟运行 if __name__ __main__: model SimpleTransformerEncoder( vocab_size100, d_model64, num_heads8, d_ff128, num_layers2, max_len20, ) # 输入batch_size1, seq_len10 token_ids torch.randint(0, 100, (1, 10)) output model(token_ids) print(输入形状:, token_ids.shape) print(输出形状:, output.shape)运行这段代码后预期看到类似下面的输出输入形状: torch.Size([1, 10]) 输出形状: torch.Size([1, 10, 64])输出维度是[batch_size, seq_len, d_model]每个 token 都被转换成了一个 64 维的上下文向量。如果继续在后面接一个分类头或者语言模型头就可以完成具体任务了。6.6 运行与验证步骤把第 6 小节的 5 个 Python 文件放在同一目录下。安装 PyTorch。执行python simple_transformer.py。观察输出形状是否符合预期。如果想进一步验证模型能学习可以构造一个简单的分类任务比如“判断句子中是否包含某个关键词”用交叉熵损失训练几个 epoch再查看损失是否下降。这种方式能帮助你确认自己写的 Transformer 计算流程是通的。7. 常见问题与排查思路在学习和上手过程中有几个问题出现频率很高这里整理成表格供你对照排查。问题现象常见原因解决思路训练 loss 不下降学习率设置不合理、数据未归一化、模型结构错误先尝试小数据集过拟合再逐步提升难度检查学习率和梯度值注意力输出结果异常Q、K、V 维度拆分错误、mask 位置设置错误打印每一层的 tensor shape对照 6.3 节步骤检查位置编码对结果没有影响忘记把位置编码叠加到词向量上检查 forward 中是否执行了x self.positional_encoding(x)Transformer 训练很慢序列长度太长、层数太多缩短 max_len、减小 batch、使用混合精度训练模型在长序列上效果差位置编码外推能力受限考虑使用旋转位置编码 RoPE 或 ALiBi 等新方法本地部署大模型显存不足参数规模超过硬件承载能力使用量化、模型并行或调用云端 API7.1 学习中的几个认知误区误区一词向量和上下文向量是一回事。实际上传统静态词向量是“查表得到固定向量”而 Transformer 的输出是“结合上下文动态计算得到向量”两者原理不同。误区二Transformer 只有一种结构。实际上Transformer 有 Encoder 结构、Decoder 结构和 Encoder-Decoder 结构GPT 和 BERT 使用方式并不同。误区三看懂了注意力公式就能理解大模型。注意力只是核心模块之一大模型还涉及预训练目标、数据 pipeline、分布式训练、推理优化、对齐策略等多方面内容。误区四本地部署 AI 大模型很容易。虽然很多大模型开源了权重但本地部署需要显存、内存、推理框架等条件模型量化、上下文长度管理都是工程化难题。8. 最佳实践与工程建议8.1 原理学习建议如果你正在学习 Transformer 和大模型下面这组实践路径值得参考不要只看不写。把本文的完整代码自己敲一遍改成不同 d_model、num_heads、num_layers 观察输出变化。用可视化工具观察注意力权重。PyTorch 的 hook 机制可以提取每一层的 attention 矩阵把注意力权重可视化后你会直观看到模型关注了哪些词。先跑通小模型再去看大模型源码。Hugging Face 的bert-base-uncased只有 1.1 亿参数比 GPT-4 这种千亿级模型容易理解得多。把公式和实现做映射。比如“缩放点积注意力”对应代码中的torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)这一行理解了英文术语对应的代码再去读论文就轻松很多。8.2 实际项目中的工程建议当你从学习进入大模型应用开发阶段有几个工程层面的建议值得注意控制上下文长度。Transformer 的复杂度会随序列长度平方增长过长的输入会显著增加推理耗时和显存占用。在实际应用中尽量把 prompt 控制在合理长度或使用 RAG 做知识库检索后再拼接上下文。重视数据质量。大模型效果的上限很大程度上由训练数据决定。即便是在做微调也要注意数据的多样性、去重、格式统一和敏感信息过滤。评估成本与效果。本地部署 AI 大模型需要对显存和推理性能做详细评估不要为了“本地化”而盲目部署过大的模型可以先用量化版本或云端 API 验证效果。做好版本与实验管理。模型训练涉及数据、代码、超参数、权重等多类产物使用实验记录工具跟踪每一次实验避免反复试错找不到最优配置。关注安全边界。在涉及用户数据、企业数据的大模型应用中要注意权限管控和数据脱敏涉及生产环境变更时先在测试环境验证并做好备份遵循最小权限原则。8.3 代码层面的建议保持模块化设计。把位置编码、注意力、前馈网络、TransformerBlock 拆成独立类方便复用和调试。多用 shape 检查。在写张量运算时在关键步骤后打印 shape能快速定位维度不匹配问题。mask 处理要统一。Transformer 中的 padding mask 和 causal mask 作用不同一个是屏蔽无效 token一个是防止看到未来信息实现时要分开维护。关注数值稳定性。softmax 前的大数值容易导致梯度消失或溢出使用-1e9填充 masked 位置是一种常见做法更规范的方式是使用torch.where配合极小值。9. 总结与下一阶段建议从词向量到 Transformer再到今天的 AI 大模型这条技术演进路线其实非常清晰先让机器拥有可计算的词表示再通过注意力机制解决长距离依赖和并行计算问题最后用海量数据把 Transformer 的规模推到千亿级参数从而涌现出复杂的语言理解和生成能力。如果你想继续深入建议按以下顺序学习手写 Transformer 的完整训练流程而不是只看 forward。阅读 BERT 论文BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding和 GPT 论文对比两种结构设计差异。学习 Hugging Face Transformers 库跑通预训练模型的加载、微调和推理。动手做一个大模型应用例如基于 RAG 的文档问答系统在真实业务中体会上下文工程和调用大模型 API 的流程。如果本文对你理解词向量、Transformer 和 AI 大模型背后的原理有帮助建议收藏备用也可以自己动手运行一遍代码遇到问题欢迎在评论区一起讨论。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价