news 2026/8/30 3:34:18

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从词向量到Transformer再到AI大模型:原理与PyTorch实战

词向量、Transformer、AI 大模型,这三个名词在深度学习面试和实际项目中出现得越来越频繁。很多人对每个名称都有印象,但问到底层逻辑时往往会发现知识是断的:为什么语言要先变成向量?为什么 RNN 最后会被 Transformer 取代?Transformer 内部的 Q、K、V 和注意力权重到底在算什么?大模型和 Transformer 又是什么关系?这篇文章把从词向量到大模型这条完整链路梳理一遍,并把每个抽象概念翻译成可运行的 PyTorch 代码。适合刚入门深度学习、准备做 NLP 项目、或者想系统理解大模型原理的读者。看完之后,你可以自己写一个极简 Transformer 编码器,也能说清楚每个模块为什么存在。

这类知识用动画理解效率最高:词向量可以想象成空间里移动的点,注意力可以想象成一张动态加粗的热度图,Transformer 的信息流动可以想象成每个 token 同时向其他 token 发消息。下面的文字版本保留这条可视化思路,但每一步都会落到可验证的代码和输出上。

1. 词向量:语言从符号变成数字的第一公里

1.1 One-Hot 编码直观,但它没有语义

计算机不认识中文或英文,只认识数字。最朴素的做法是 One-Hot 编码:先把所有词整理成一个词表,假设词表大小是 V,那么每个词用一个长度为 V 的向量表示,当前词对应位置是 1,其他位置是 0。

# 词表: ["我", "爱", "学习", "AI", "模型"] # One-Hot 表示 word_to_id = {"我": 0, "爱": 1, "学习": 2, "AI": 3, "模型": 4} import torch def one_hot(word_id, vocab_size): vec = torch.zeros(vocab_size) vec[word_id] = 1.0 return vec print(one_hot(word_to_id["学习"], 5)) # tensor([0., 0., 1., 0., 0.])

但 One-Hot 有两个致命问题。第一,词表越大向量越稀疏,存储和计算开销都很大;第二,任意两个词的向量内积都是 0,余弦相似度也是 0,模型完全看不出“猫”和“狗”比“猫”和“汽车”更相关。符号表示把语言变成了孤立的编号,语义被抹掉了。

1.2 Word2Vec 让词在空间里有方向和距离

Word2Vec 的核心思路是分布式表示(Distributed Representation):用一个低维稠密向量表示每个词,训练目标是让出现在相似上下文里的词,向量距离更近。它有两种训练方式:

  • CBOW(Continuous Bag-of-Words):用上下文词预测中心词。比如看到“我 __ AI”,预测中间是“学习”。
  • Skip-gram:用中心词预测上下文词。看到“学习”,预测周围会出现“我”“AI”。

一个最小 CBOW 模型非常短:

import torch import torch.nn as nn class CBOW(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.output = nn.Linear(embedding_dim, vocab_size) def forward(self, context_words): # context_words: [batch, context_size] embeds = self.embeddings(context_words).mean(dim=1) return self.output(embeds) # [batch, vocab_size]

训练结束后,词表里的每个词都对应一个稠密向量。此时可以用余弦相似度计算两个词的语义距离,也可以做向量运算,例如经典的“king - man + woman ≈ queen”效果。把高维向量用 TSNE 降到二维画出来,会看到语义相近的词聚在一起,这个过程非常适合用动画展示:训练开始时点随机分布,随着训练推进,语义相近的词点逐渐靠近。

1.3 GloVe 用全局共现信息补足 Word2Vec 的盲区

Word2Vec 只看局部窗口内的共现关系。GloVe 换了一个角度:统计整个语料库中任意两个词共同出现的次数,构建一个共现矩阵,然后训练向量,使得两个词向量的点积近似等于它们共现次数的对数。

从工程角度看,Word2Vec 适合在超大语料上增量训练,GloVe 适合先统计共现矩阵再一次性训练。两者都属于静态词向量:一个词只有一个固定向量。词向量发展到这里,已经能把“语义相似”变成“距离相近”,但还没有能力处理“一词多义”。

1.4 静态词向量的天花板:一个词只能有一个向量

“bank”既可以指银行,也可以指河岸。在 Word2Vec 和 GloVe 里,“bank”只有一个向量,等于把两种含义平均在一起,结果既不精确也不稳定。这个问题直到 Transformer 出现后才真正解决:同一个词,在不同句子里应该生成不同的向量,也就是上下文相关的动态表示。理解了这个缺口,就能理解为什么后面需要 Transformer 这样的深层网络。

四种表示方式的对比:

表示方式核心思想维度能否表达语义能否处理一词多义
One-Hot每个词一个独立维度词表大小不能不能
静态分布式词向量低维稠密向量100 到 300能表达相似性不能
上下文相关向量根据上下文动态生成隐藏层维度
Transformer 输出向量深层注意力融合上下文512 到 8192

2. 为什么序列建模最终选择了 Transformer

2.1 RNN 的顺序读取是性能瓶颈,也是信息瓶颈

RNN 处理句子时从左到右一个一个读,每读一个词就更新一次隐藏状态h_t = f(h_{t-1}, x_t)。这个设计有两个问题:

  • 串行计算导致训练速度慢,尤其在长文本上。
  • 信息要经过很多步才能从句子开头传到结尾,梯度在反向传播时容易消失或爆炸,模型很难记住长距离依赖。

LSTM 和 GRU 通过门控机制缓解了梯度消失,但并没有改变串行计算和长距离信息衰减的本质。句子越长,前面的信息被“压缩”得越厉害。

2.2 CNN 只能看到局部窗口

CNN 通过卷积核扫描文本,每个卷积核只能看到固定大小的窗口。要覆盖很长的依赖关系,必须堆叠很多层,感受野才会逐步扩大。而且卷积核是位置无关的,它不能根据当前词动态决定应该关注哪些词。

对于文本这种长度不固定、依赖关系不规律的数据,CNN 天然不是最优选择。

2.3 Attention 让任意两个位置直接对话

Attention 机制的核心是:在计算某个词的表征时,不再固定读相邻的词,而是让这个词和自己相关的所有词建立连接,连接强度由注意力权重决定。

以经典句子为例:“The animal didn't cross the street because it was too tired.” 模型在处理 “it” 时,应该重点关注 “animal”,而不是机械地看相邻的 “street”。注意力权重可以画成一张热度图:行是当前词,列是所有词,颜色越深表示权重越大。看这张图,人能直观理解模型在关注什么,这也是动画学习 Transformer 最有价值的部分。

自注意力(Self-Attention)让任意两个位置的信息路径长度变成 O(1),并且所有位置的计算可以并行执行。这两点直接解决了 RNN 和 CNN 的核心痛点。

2.4 CNN、RNN、Transformer 的对比

结构处理方式长距离依赖并行性任意两位置路径长度
RNN从左到右循环弱,易遗忘O(n)
CNN滑动窗口扫描弱,需堆叠层数随层数增长
Transformer(自注意力)任意两位置直接计算O(1)

这里的路径长度是指信息从位置 i 传到位置 j 需要经过多少步。RNN 需要 |i-j| 步,CNN 需要取决于卷积层数,而 Transformer 只需要一步。这就是为什么论文标题直接叫 Attention Is All You Need:注意力机制足够强,甚至可以完全替换掉循环结构。

3. 拆开 Transformer:注意力、多头、位置编码

3.1 整体架构

Transformer 原作是 Encoder-Decoder 结构。Encoder 由 N 个相同的编码器块堆叠而成,每个块包含多头自注意力、残差连接、层归一化和前馈网络;Decoder 在每个块里多了一个带掩码的自注意力和一个 Cross-Attention,用于关注 Encoder 的输出。

后来 NLP 实践分化出两种用法:

  • Encoder-only:BERT 为代表,擅长理解任务,如分类、抽取。
  • Decoder-only:GPT 为代表,擅长生成任务,如对话、写作。

当前主流大模型基本都采用 Decoder-only,因为“预测下一个词”这个自监督任务足够统一,也容易扩展到任意文本生成。

3.2 Self-Attention 的 Q、K、V 计算

Self-Attention 的输入是一组 token 向量。计算时先通过三个可学习的线性变换把它们映射成 Q(Query,查询)、K(Key,键)、V(Value,值),然后按如下公式计算:

Attention(Q, K, V) = softmax(Q * K^T / sqrt(d_k)) * V

理解这三个角色的通俗方式:

  • Q 表示“我在找什么信息”。
  • K 表示“我能提供什么信息”。
  • V 表示“我实际携带的内容”。

计算过程分四步:

  1. 每个 token 的 Q 和所有 token 的 K 做点积,得到一个分数,表示它与各个 token 的相关性。
  2. 除以sqrt(d_k),防止点积随维度增大而变得过大,导致 softmax 进入饱和区、梯度消失。
  3. 对每一行做 softmax,让分数变成总和为 1 的注意力权重。
  4. 用权重对 V 做加权求和,得到该 token 融合上下文后的新向量。
import math import torch def scaled_dot_product_attention(Q, K, V, mask=None): d_k = Q.size(-1) scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k) if mask is not None: scores = scores.masked_fill(mask == 0, float("-inf")) weights = torch.softmax(scores, dim=-1) return torch.matmul(weights, V), weights

这里每一步的维度都要确认。Q、K、V 的形状通常是[batch, num_heads, seq_len, d_k]K.transpose(-2, -1)把 seq_len 和 d_k 交换,得到[batch, num_heads, seq_len, seq_len]的分数矩阵,第 i 行第 j 列表示第 i 个 token 对第 j 个 token 的相关性。

3.3 Multi-Head Attention 为什么有效

单个注意力头只能学到一种“关系模式”。多头的思想是并行运行多个注意力头,每个头用不同的投影矩阵,相当于让模型从多个子空间观察输入:一个头可能关注句法关系,另一个头可能关注指代关系,还有一个头可能关注位置距离。

最后把所有头的输出拼接起来,再过一层线性变换合并:

class MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads): 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, mask=None): batch_size, seq_len, _ = x.size() 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) attn_out, attn_weights = scaled_dot_product_attention(Q, K, V, mask) attn_out = attn_out.transpose(1, 2).contiguous().view(batch_size, seq_len, self.d_model) return self.W_o(attn_out), attn_weights

关键点在于viewtranspose的组合:先把线性变换后的[batch, seq_len, d_model]拆成[batch, seq_len, num_heads, d_k],再交换维度和顺序,变成[batch, num_heads, seq_len, d_k],这样每个头独立参与注意力计算,互不干扰。计算完后要contiguous().view恢复形状,否则拼接时维度顺序会错。

3.4 位置编码:没有顺序信息的注意力是“词袋”

自注意力本身对 token 位置完全无感。把句子倒过来,注意力分数矩阵不变,因为 Q 和 K 的点积只关心内容相关性,不关心谁先谁后。为了让模型感知顺序,必须把位置信息加进输入。

原作使用正弦位置编码:

  • 偶数维用sin(pos / 10000^(2i/d_model))
  • 奇数维用cos(pos / 10000^(2i/d_model))

这样设计的好处是不同位置生成不同的编码,而且相邻位置编码接近,距离远的位置编码差异大。实现如下:

class PositionalEncoding(nn.Module): def __init__(self, d_model, max_len=512): super().__init__() pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) self.register_buffer("pe", pe.unsqueeze(0)) def forward(self, x): return x + self.pe[:, :x.size(1)]

register_buffer让位置编码矩阵跟随模型移动到 GPU,但不会参与训练更新。forwardx.size(1)是实际序列长度,因为输入可能比max_len短。

现代大模型更多使用可学习位置编码或旋转位置编码(RoPE)。RoPE 通过旋转矩阵把相对位置信息编码进 Q 和 K,这样模型对相对距离更敏感,对长文本的泛化也更好。理解正弦编码的原理后,再去看 RoPE 会容易很多。

3.5 残差连接、LayerNorm 和 FFN 各有分工

注意力层之后还有一个前馈网络(FFN)和两个重要的结构组件。

残差连接的用意是让梯度有一条“高速公路”直接回传,避免深层网络退化。Transformer 块里典型写法是x = x + sublayer(x),这样即使子层学不到有用的映射,模型至少保留原来的表示。

层归一化(LayerNorm)对每个 token 的所有维度做归一化,稳定数值分布。Transformer 早期常用 Post-LN,也就是x = x + sublayer(x); x = LayerNorm(x);现在更多大模型用 Pre-LN,即x = x + sublayer(LayerNorm(x)),训练更稳定,对 warmup 的依赖更小。

FFN 是两层线性变换加激活函数,中间维度d_ff通常比d_model大很多:

self.ffn = nn.Sequential( nn.Linear(d_model, d_ff), nn.ReLU(), nn.Linear(d_ff, d_model), )

它的作用是给每个 token 独立做非线性变换,增强模型表达能力。注意力负责“融合信息”,FFN 负责“加工信息”,两者分工明确。

完整编码器块:

class TransformerBlock(nn.Module): def __init__(self, d_model, num_heads, d_ff, dropout=0.1): super().__init__() self.attn = MultiHeadAttention(d_model, num_heads) self.norm1 = nn.LayerNorm(d_model) self.ffn = nn.Sequential( nn.Linear(d_model, d_ff), nn.ReLU(), nn.Linear(d_ff, d_model), ) self.norm2 = nn.LayerNorm(d_model) self.dropout = nn.Dropout(dropout) def forward(self, x, mask=None): # Pre-LN 风格:先归一化,再过子层,再加残差 x = x + self.dropout(self.attn(self.norm1(x), mask)[0]) x = x + self.dropout(self.ffn(self.norm2(x))) return x

核心参数速查:

参数含义常见值调大的影响调小的影响
d_model向量维度 / 隐藏层宽度512 / 768容量大,训练慢容量小,训练快
num_heads注意力头数8 / 12关系模式更丰富表达模式受限
d_ffFFN 中间维度2048 / 3072非线性能力更强更轻量
dropout随机失活比例0.1正则化更强正则化更弱

4. 从 Transformer 到大模型:词向量变成了上下文向量

4.1 预训练与微调

Transformer 本身只是网络结构,真正让它演变成大模型的是预训练范式。先在海量无标注文本上做自监督学习:BERT 遮住一部分词让模型预测,GPT 让模型预测下一个词。训练完成后得到一个基础模型,再根据下游任务做微调、接入指令数据,或者直接用提示词调用。

预训练的价值在于让模型在没有人工标注的情况下学会大量语言规律,包括语法、事实知识、逻辑关联和风格模式。这比传统的“人工标注 + 单任务训练”高效得多,也是大模型能力的主要来源。

4.2 大模型的“动态词向量”

如果你把大模型最后一层输出的向量取出来,会发现它已经超越了静态词向量:同一个词在不同上下文里输出不同向量。“bank”在“river bank”和“bank account”两个句子里,会得到明显不同的表示。

从词向量的角度看大模型,可以这样理解:静态词向量是查表得到的固定结果,Transformer 的每一层都在对词向量做上下文融合和语义细化,最后一层的输出才是“这个词在当前句子里的完整语义”。这也是前面说 Transformer 解决一词多义问题的原因。

4.3 规模扩张带来能力变化

大模型的“大”体现在三个维度:参数量、训练数据量、计算量。当模型规模达到一定量级后,会出现小模型没有的能力,比如上下文学习、思维链推理、指令跟随等。GPT、LLaMA、Qwen、DeepSeek 等模型都是 Transformer Decoder 在规模和数据上的延伸,架构本身没有跳出自注意力、多头、位置编码、残差和 LayerNorm 这套框架。

所以学习路径非常明确:把词向量和 Transformer 理解透,再看大模型就是“更大的 Transformer + 更多的训练数据 + 更精细的训练策略”,不会再觉得它是一个黑盒。

4.4 Transformer 不只是 NLP:视觉和时间序列

Transformer 的应用早已超出文本。Vision Transformer(ViT)把图像切成固定大小的 patch,每个 patch 当成一个 token,然后直接套用标准 Transformer 编码器;Swin Transformer 引入分层结构和移位窗口,兼顾了全局建模和计算效率。时间序列预测领域也有 Informer、Autoformer 等基于 Transformer 的模型,把注意力用在多变量时序数据上。

这些应用的共同点是:把任意离散单元变成 token,把 token 映射成向量,再用自注意力建模单元之间的关系。理解原理后,从 NLP 迁移到这些领域只需要理解 token 化的方式不同。

5. 手写一个极简 Transformer:环境、代码、验证

5.1 环境准备

本文所有代码只需要 CPU 就能跑,关键是验证各模块的形状和计算过程。环境如下:

组件推荐版本说明
Python3.8 以上基础运行环境
PyTorch2.0 以上自动微分和神经网络模块
NumPy1.24 以上数据处理辅助
python -c "import torch; print(torch.__version__)" # 输出示例: 2.1.2

如果没有安装 PyTorch,执行:

pip install torch --index-url https://download.pytorch.org/whl/cpu

学习阶段 CPU 版本完全够用,手写代码验证形状不需要 GPU。后面真正训练词向量或微调模型时,再根据显卡配置安装 CUDA 版本。

5.2 最小词向量模型

class CBOW(nn.Module): def __init__(self, vocab_size, embedding_dim): super().__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.output = nn.Linear(embedding_dim, vocab_size) def forward(self, context_words): embeds = self.embeddings(context_words).mean(dim=1) return self.output(embeds)

训练循环框架:

model = CBOW(vocab_size=5000, embedding_dim=128) criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3) # context: [batch, 4],target: [batch] # logits = model(context) # loss = criterion(logits, target) # loss.backward() # optimizer.step()

训练结束后,model.embeddings.weight的第 i 行就是词表第 i 个词的静态词向量。这是后面所有大模型表示学习的起点。

5.3 缩放点积注意力

把前文的核心函数再单独强调一次:

def scaled_dot_product_attention(Q, K, V, mask=None): d_k = Q.size(-1) scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k) if mask is not None: scores = scores.masked_fill(mask == 0, float("-inf")) weights = torch.softmax(scores, dim=-1) return torch.matmul(weights, V), weights

用一个小例子验证形状:

torch.manual_seed(0) Q = torch.randn(2, 8, 10, 16) # batch=2, heads=8, seq_len=10, d_k=16 K = torch.randn(2, 8, 10, 16) V = torch.randn(2, 8, 10, 16) out, weights = scaled_dot_product_attention(Q, K, V) print("输出形状:", out.shape) # torch.Size([2, 8, 10, 16]) print("注意力权重形状:", weights.shape) # torch.Size([2, 8, 10, 10])

注意力权重矩阵的最后两维是[10, 10],第 i 行就是第 i 个 token 对所有 token 的注意力分布;每一行经过 softmax,总和为 1。

5.4 多头注意力

将 MultiHeadAttention 类和 TransformerBlock 类放在一个transformer_mini.py文件里,然后运行验证脚本:

torch.manual_seed(42) # 模拟一个 batch: 2 个句子,每句 6 个 token,向量维度 64 x = torch.randn(2, 6, 64) mha = MultiHeadAttention(d_model=64, num_heads=8) out, attn_weights = mha(x) print("多头注意力输出:", out.shape) # torch.Size([2, 6, 64]) print("注意力权重:", attn_weights.shape) # torch.Size([2, 8, 6, 6]) block = TransformerBlock(d_model=64, num_heads=8, d_ff=256) out = block(x) print("编码器块输出:", out.shape) # torch.Size([2, 6, 64])

5.5 位置编码验证

pe = PositionalEncoding(d_model=64, max_len=100) x = torch.randn(2, 6, 64) y = pe(x) print("加位置编码后:", y.shape) # torch.Size([2, 6, 64]) # 验证不同位置的编码差异 pos_diff = (pe.pe[0, 5] - pe.pe[0, 1]).norm() print("位置5与位置1编码差异:", pos_diff.item())

如果一切正常,输出形状与输入一致,说明残差结构保证了维度不变。注意力权重矩阵的形状能直接看出“多少个头、多少 token”,这是排查维度问题最直观的依据。

5.6 动画视角看整个前向过程

把上面代码组合起来,想象一张动画:6 个 token 的向量从左到右排列,进入多头注意力后,每个 token 伸出 8 组连接线与其他 5 个 token 相连,连接线的粗细就是注意力权重;随后经过残差合并,再过 FFN 做非线性变换,最后输出一组更新后的向量。每个编码器块就是一轮“信息交换 + 信息加工”。理解了这个动画,Transformer 就不再是黑盒。

6. 常见错误与排查链路

6.1 Mask 设置错误,模型看到未来信息

现象:Decoder 训练时 loss 异常低,但生成文本混乱重复。

原因:没有使用因果掩码(Causal Mask),训练时当前 token 看到了后面的 token,相当于“开卷考试”。真正生成时没有未来信息,模型立刻露馅。

检查与解决:打印注意力分数矩阵,确认掩码把上三角位置置为-inf。生成掩码的标准写法:

seq_len = 6 causal_mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1) == 0 # 第 i 行第 j 列,j > i 时为 False,会被 masked_fill 成 -inf

6.2 维度不匹配

现象:mat1 and mat2 shapes cannot be multiplied之类的报错。

原因:d_model不能被num_heads整除;viewtranspose顺序写反;多头输出没有contiguous().view直接拼接。

检查:在每个关键节点打印形状。

print("Q:", Q.shape) # [batch, num_heads, seq_len, d_k] print("K:", K.shape) # [batch, num_heads, seq_len, d_k] print("V:", V.shape) # [batch, num_heads, seq_len, d_k] print("scores:", scores.shape) # [batch, num_heads, seq_len, seq_len]

最常见的是遗忘contiguous(),因为transpose返回的是视图而非连续内存,直接view会报错。

6.3 训练不收敛、NaN、梯度爆炸

现象:loss 居高不下,或者出现 NaN;静态词向量训练后相似词距离不明显。

原因分析顺序:

  1. 学习率过大,梯度更新幅度太大。
  2. 没有梯度裁剪,长序列上梯度爆炸。
  3. 数值不稳定,softmax 输入过大或出现-inf未正确处理。
  4. 语料太小或没有去除低频词,词向量学不到稳定语义。

处理方式:

torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

同时建议训练初期设置学习率 warmup,并且小幅降低学习率观察 loss 变化。

6.4 排错顺序清单

无论遇到什么问题,按这个顺序排查最有效:

顺序检查项工具或方法
1输入形状打印每个张量的 shape
2掩码打印 mask,确认-inf位置
3数值稳定性检查 logits 是否有 NaN、Inf
4梯度计算grad_norm,确认没有爆炸或消失
5超参数检查 lr、batch_size、d_model、dropout
6数据检查语料质量、词表构建、低频词过滤

7. 最佳实践与下一步学习路线

7.1 复现和自检清单

学习 Transformer 时,建议每次写完代码都过一遍清单:

  • 固定随机种子,保证结果可复现。
  • 先用随机输入跑通前向,确认所有输出形状正确。
  • 用一个小 batch 数据训练几个 step,确认 loss 在下降。
  • 单独可视化解码器的因果掩码,确认没有信息泄漏。
  • 单独可视化一组注意力权重,确认不是均匀分布。
  • 保存 checkpoint,训练中断后能恢复。
  • 对比 Post-LN 和 Pre-LN 的训练稳定性。

这份清单同样适用于后面的 BERT、GPT 复现实验。

7.2 学习环境与生产环境的差异

本文的代码用于理解原理,直接跑在 CPU 上即可。如果要在真实场景使用 Transformer 或大模型,还需要额外考虑:

  • 训练环境:GPU 显存、混合精度、分布式训练、数据并行。
  • 推理环境:模型量化(INT8、INT4)、KV Cache、推理框架(vLLM、TensorRT-LLM 等)。
  • 工程保障:日志监控、异常告警、版本回滚、数据备份。
  • 安全和合规:本地部署大模型要考虑数据隐私、内容安全过滤、权限控制。

尤其是本地部署大模型,单靠 Transformer 理论不够,还需要理解显存占用如何估算、量化后精度损失多大、并发请求如何调度。这些属于另一条工程链路,但底层原理仍然是注意力计算和 token 表示。

7.3 扩展方向

理解基础 Transformer 后,按兴趣选择扩展方向:

  • 视觉方向:读 Vision Transformer(ViT)、Swin Transformer 论文,用 PyTorch 实现图像 patch 化。
  • 预训练方向:复现一个微型 BERT,在中文语料上做掩码语言模型预训练,观察词向量如何变为上下文向量。
  • 时间序列方向:研究 Informer、Autoformer,尝试用注意力机制做股票或气象数据预测。
  • 工程方向:实践模型量化、服务化部署,用一个小模型搭建本地知识库问答。
  • 理论方向:阅读 RoPE、FlashAttention、Grouped Query Attention 等改进机制,理解大模型在工程上的优化思路。

7.4 给新手的最后建议

词向量解决的是“语言如何变成数字”,Transformer 解决的是“数字之间如何交换信息”,大模型解决的是“如何用海量数据和计算让这个过程涌现智能”。三个问题层层递进,理解顺序不能跳。

新手最常见的问题是直接去看大模型代码,被复杂的张量维度和分布式逻辑吓退。更好的做法是先把本文这段最小代码跑熟,再逐步加入批量训练、掩码、解码器,最后再去接触真实大模型框架。每一步都能运行、能验证、能画出可视化结果,知识才是自己的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 3:30:01

Cloudflare Kitesurf:AI Agent浏览器的工作原理与实战指南

最近一年里,AI Agent 的讨论热度一直居高不下。从“能聊天的模型”到“能动手干活的智能体”,行业对浏览器的期待正在悄悄发生变化。过去我们打开浏览器是为了阅读新闻、刷视频、写文档,现在越来越多的开发者希望让 Agent 帮我们自动填表、比…

作者头像 李华
网站建设 2026/8/30 3:29:56

游戏公会招募解析:50级门槛与“等级接近我带你”的真实含义

先把这个标题翻译成游戏玩家都懂的话:这是一条叫 Salt 的公会招募信息,核心条件是等级达到 50 级就能申请,不需要你装备多好、副本经验多丰富、在线时长多稳定;如果你的等级和公会主力成员比较接近,招募人还愿意亲手带…

作者头像 李华
网站建设 2026/8/30 3:29:54

Python实现人生模拟器:属性建模与事件驱动机制详解

周末整理代码仓库时,发现之前拿 Python 折腾过一个小项目:人生模拟器。当时想法很简单——网上很多“人生重开模拟器”要么是网页小游戏,要么逻辑写得太复杂,不太适合拿来学编程。于是决定自己手搓一个纯 Python 控制台版本&#…

作者头像 李华
网站建设 2026/8/30 3:27:53

机器学习入门避坑指南:从速成陷阱到系统学习路径

简介:本资源是一套面向零基础学习者的机器学习入门速成资料包,聚焦Python生态下的核心概念与实践路径,适用于高校学生、转行新人及希望快速建立ML知识框架的开发者。压缩包共2000个文件,体量达165.14MB,以1909个JavaSc…

作者头像 李华
网站建设 2026/8/30 3:26:28

STM32 IWDG重装载值写不进?RVU置位原因与初始化正确顺序

上周在调试一块 STM32F411CEU6 的小板子时,遇到了一个特别典型的 IWDG 问题:往 IWDG_RLR 寄存器里写入新的重装载值,读回来永远是 0xFFF,而 IWDG_SR 里的 RVU 位却死死保持为 1。这个组合非常反直觉——RVU 全称是 Reload Value U…

作者头像 李华