尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Transformer 网络构建 的详尽指南

Transformer 网络构建 的详尽指南 第一部分背景与动机——为什么需要 Transformer1.1 序列建模的历史困境在 Transformer 出现之前自然语言处理NLP和时序数据处理主要依赖循环神经网络RNN及其变体LSTM、GRU。尽管 RNN 在理论上是图灵完备的能够处理任意长度的序列但其存在三个核心痛点串行计算的瓶颈RNN 必须按时间步依次计算$h_t f(h_{t-1}, x_t)$。这种递归结构使得 GPU/TPU 的并行计算能力无法被充分利用。长期遗忘问题虽然 LSTM 引入了门控机制缓解了梯度消失但在处理超过 100 个时间步的长序列时模型依然难以捕捉跨度极大的依赖关系。梯度不稳定反向传播经过时间轴展开Backpropagation Through Time, BPTT极易导致梯度爆炸或消失。1.2 卷积神经网络的局限卷积神经网络CNN虽然可以并行计算但感受野受限于卷积核大小。为了捕捉长距离依赖必须堆叠多层卷积或使用膨胀卷积Dilated Convolution这增加了模型的深度和参数量且感受野的扩大是隐式的不够直接。1.3 注意力机制的曙光注意力机制最初被引入 RNN 中用于机器翻译。其核心思想是在解码时让模型“关注”编码器中与当前输出最相关的输入部分。但当时的注意力依然是 RNN 的辅助模块。2017 年Google Brain 团队发表了论文《Attention Is All You Need》提出了一个大胆的架构完全抛弃循环与卷积仅靠自注意力Self-Attention和前馈网络构建模型。这就是 Transformer。它的革命性在于全局感受野自注意力机制允许序列中的任意两个位置直接交互计算它们之间的关联权重一步到位捕捉长距离依赖。高度并行化所有时间步的计算是同时进行的矩阵乘法训练速度远超 RNN。可扩展性随着参数量增大从 1 亿到 5000 亿模型性能呈现对数线性增长为大模型时代奠定了架构基础。第二部分核心架构拆解——Transformer 的每一块积木Transformer 遵循经典的编码器-解码器Encoder-Decoder架构。编码器负责理解输入序列将其转化为上下文表示解码器则基于编码器的输出和之前生成的输出逐步生成目标序列。原始的 Transformer 由 6 个编码器堆叠和 6 个解码器堆叠组成。2.1 输入嵌入层Input Embedding模型无法直接处理文本需要将 Token单词或子词映射为高维向量。公式假设词汇表大小为 $V$嵌入维度为 $d_{model}$原文为 512。每个 Token $t$ 被映射为 $x \in \mathbb{R}^{d_{model}}$。矩阵表示输入序列长度为 $n$则输入矩阵 $X \in \mathbb{R}^{n \times d_{model}}$。2.2 位置编码Positional Encoding由于 Transformer 没有循环也没有卷积它无法感知输入 Token 的顺序。为了让模型利用序列的顺序信息必须显式地注入位置编码。原始论文使用了正弦和余弦函数PE(pos,2i)sin⁡(pos100002i/dmodel)PE(pos,2i)​sin(100002i/dmodel​pos​)PE(pos,2i1)cos⁡(pos100002i/dmodel)PE(pos,2i1)​cos(100002i/dmodel​pos​)其中 $pos$ 是位置索引$i$ 是维度索引。这种设计的优点在于值域在 $[-1, 1]$ 之间保持稳定。对于任意偏移量 $k$$PE_{posk}$ 可以表示为 $PE_{pos}$ 的线性函数便于模型学习相对位置。最终输入$X_{final} X_{embed} PE$逐元素相加。2.3 自注意力机制Self-Attention这是 Transformer 的核心。它的目标是对于序列中的每一个词计算它与序列中所有词包括它自己的相关性然后加权聚合这些词的信息。2.3.1 缩放点积注意力假设输入矩阵为 $X \in \mathbb{R}^{n \times d_{model}}$。我们定义三个可训练的权重矩阵$W^Q \in \mathbb{R}^{d_{model} \times d_k}$$W^K \in \mathbb{R}^{d_{model} \times d_k}$$W^V \in \mathbb{R}^{d_{model} \times d_v}$通过线性变换得到Query$Q XW^Q$形状 $(n, d_k)$Key$K XW^K$形状 $(n, d_k)$Value$V XW^V$形状 $(n, d_v)$计算步骤相关性打分计算 $Q$ 与 $K$ 的点积。$Q \cdot K^T$ 得到形状为 $(n, n)$ 的矩阵其中第 $i$ 行第 $j$ 列表示第 $i$ 个词对第 $j$ 个词的未归一化注意力分数。缩放为了防止点积结果过大导致 softmax 进入梯度极小的区域除以 $\sqrt{d_k}$。掩码Mask在解码器中为了防止看到未来的信息会将未来位置的分数设置为 $-\infty$。Softmax对每一行进行 Softmax得到归一化的注意力权重 $\alpha$和为 1。加权求和将权重与 $V$ 相乘。公式Attention(Q,K,V)softmax(QKTdk)VAttention(Q,K,V)softmax(dk​​QKT​)V2.3.2 多头注意力Multi-Head Attention单头注意力虽然有效但可能只关注一种特征关系。多头注意力将 $Q, K, V$ 分别线性投影到 $h$ 个不同的子空间$h8$并行计算 $h$ 次注意力然后将结果拼接起来。公式MultiHead(Q,K,V)Concat(head1,...,headh)WOMultiHead(Q,K,V)Concat(head1​,...,headh​)WO其中 $\text{head}_i \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$。多头注意力的意义在于捕捉多义性不同的头可以关注不同的语法特征如指代关系、局部依赖、长距离依赖。增强表达能力通过不同的投影矩阵模型可以从不同角度理解语义。2.4 前馈网络Feed-Forward Network, FFN每个编码器和解码器层都包含一个全连接的前馈网络。它作用于每个位置独立且相同用于引入非线性变换。公式FFN(x)max⁡(0,xW1b1)W2b2FFN(x)max(0,xW1​b1​)W2​b2​通常采用两层线性变换中间使用 ReLU 激活现代实现常用 GELU 或 SwiGLU。在 Transformer 中$d_{ff}$ 通常远大于 $d_{model}$原文中 $d_{model}512, d_{ff}2048$。这个“扩张-收缩”的结构起到了类似记忆存储和信息过滤的作用。2.5 残差连接与层归一化Add Norm为了训练深层网络每个子层注意力层或前馈层都使用了残差连接随后进行层归一化LayerNorm。公式OutputLayerNorm(xSublayer(x))OutputLayerNorm(xSublayer(x))残差连接保证了梯度的直接流通防止深层网络退化。层归一化LayerNorm在特征维度上做归一化使模型训练更加稳定收敛更快。2.6 编码器Encoder结构编码器由 $N$ 个相同的层堆叠而成$N6$。每一层包含两个子层多头自注意力层允许每个位置关注输入序列中的所有位置。前馈网络层进行非线性映射。数据流输入 $X \to$ 自注意力 $\to$ Add Norm $\to$ FFN $\to$ Add Norm $\to$ 输出到下一层。2.7 解码器Decoder结构解码器也由 $N$ 个相同的层堆叠而成。但每一层包含三个子层掩码多头自注意力层与编码器类似但使用因果掩码Causal Mask。在生成第 $t$ 个词时不允许看到 $t$ 之后的词未来信息。这通过将 $QK^T$ 矩阵中 $ji$ 的位置设置为 $-\infty$ 实现。交叉注意力层Cross-Attention这是编码器与解码器的桥梁。$Q$ 来自解码器的上一输出$K$ 和 $V$ 来自编码器的最终输出。这使得解码器在生成每个词时能够“查阅”输入序列的所有信息。前馈网络层。数据流输出序列右移一位即 Start Token$\to$ 掩码自注意力 $\to$ Add Norm $\to$ 交叉注意力Query 来自解码器Key/Value 来自编码器$\to$ Add Norm $\to$ FFN $\to$ Add Norm $\to$ 输出。2.8 最后的线性层与 Softmax解码器的输出经过一个线性层全连接将维度从 $d_{model}$ 映射到词汇表大小 $V$再通过 Softmax 转换为概率分布选择概率最高的词作为下一个输出。第三部分代码实现——从零搭建 TransformerPyTorch理论说完我们来用 PyTorch 搭建一个可用的 Transformer 模型。我们将遵循原始论文的结构但为了清晰代码会尽量模块化。3.1 环境准备与超参数pythonimport torch import torch.nn as nn import torch.nn.functional as F import math # 超参数设置 class Config: d_model 512 # 嵌入维度 n_heads 8 # 多头数量必须能被 d_model 整除 d_ff 2048 # 前馈网络维度 n_layers 6 # 编码器/解码器层数 max_seq_len 5000 # 最大序列长度 dropout 0.1 # Dropout 比率 vocab_size 30000 # 词汇表大小示例 device torch.device(cuda if torch.cuda.is_available() else cpu)3.2 位置编码实现pythonclass PositionalEncoding(nn.Module): def __init__(self, d_model, max_seq_len, dropout0.1): super().__init__() self.dropout nn.Dropout(pdropout) # 创建一个固定编码矩阵 PE (max_seq_len, d_model) pe torch.zeros(max_seq_len, d_model) position torch.arange(0, max_seq_len, dtypetorch.float).unsqueeze(1) # (max_seq_len, 1) 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_seq_len, d_model) # 注册为 buffer不作为可训练参数但随模型保存到 state_dict self.register_buffer(pe, pe) def forward(self, x): # x: (batch_size, seq_len, d_model) x x self.pe[:, :x.size(1), :] return self.dropout(x)3.3 缩放点积注意力pythondef scaled_dot_product_attention(query, key, value, maskNone, dropoutNone): 参数: query: (batch, n_heads, seq_len, d_k) key: (batch, n_heads, seq_len, d_k) value: (batch, n_heads, seq_len, d_v) mask: (batch, 1, 1, seq_len) 或 (batch, 1, seq_len, seq_len) 返回: output: (batch, n_heads, seq_len, d_v) attn: (batch, n_heads, seq_len, seq_len) d_k query.size(-1) # 1. 计算 Q * K^T scores torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k) # 2. 应用掩码将 mask 位置设为 -inf if mask is not None: scores scores.masked_fill(mask 0, -1e9) # 3. Softmax attn F.softmax(scores, dim-1) # 4. Dropout if dropout is not None: attn dropout(attn) # 5. 加权求和 output torch.matmul(attn, value) return output, attn3.4 多头注意力模块pythonclass MultiHeadAttention(nn.Module): def __init__(self, d_model, n_heads, dropout0.1): super().__init__() assert d_model % n_heads 0, d_model must be divisible by n_heads self.d_model d_model self.n_heads n_heads self.d_k d_model // n_heads # 定义 Q, K, V 的线性变换层 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) self.dropout nn.Dropout(dropout) def forward(self, query, key, value, maskNone): batch_size query.size(0) # 1. 线性变换并分割成多头 # Q: (batch, seq_len, d_model) - (batch, seq_len, n_heads, d_k) - (batch, n_heads, seq_len, d_k) Q self.W_q(query).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2) K self.W_k(key).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2) V self.W_v(value).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2) # 2. 应用注意力 attn_output, attn_weights scaled_dot_product_attention( Q, K, V, mask, self.dropout ) # 3. 拼接多头 # attn_output: (batch, n_heads, seq_len, d_k) - (batch, seq_len, d_model) attn_output attn_output.transpose(1, 2).contiguous().view( batch_size, -1, self.d_model ) # 4. 最终线性变换 output self.W_o(attn_output) return output3.5 前馈网络模块pythonclass PositionwiseFeedForward(nn.Module): def __init__(self, d_model, d_ff, dropout0.1): super().__init__() self.linear1 nn.Linear(d_model, d_ff) self.linear2 nn.Linear(d_ff, d_model) self.dropout nn.Dropout(dropout) def forward(self, x): # 使用 ReLU 激活现代实现可换为 GELU return self.linear2(self.dropout(F.relu(self.linear1(x))))3.6 编码器层与编码器pythonclass EncoderLayer(nn.Module): def __init__(self, d_model, n_heads, d_ff, dropout0.1): super().__init__() self.self_attn MultiHeadAttention(d_model, n_heads, dropout) self.feed_forward PositionwiseFeedForward(d_model, d_ff, dropout) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.dropout1 nn.Dropout(dropout) self.dropout2 nn.Dropout(dropout) def forward(self, x, maskNone): # 子层1: 多头自注意力 残差 LayerNorm attn_output self.self_attn(x, x, x, mask) x self.norm1(x self.dropout1(attn_output)) # 子层2: 前馈网络 残差 LayerNorm ff_output self.feed_forward(x) x self.norm2(x self.dropout2(ff_output)) return x class Encoder(nn.Module): def __init__(self, config): super().__init__() self.layers nn.ModuleList([ EncoderLayer(config.d_model, config.n_heads, config.d_ff, config.dropout) for _ in range(config.n_layers) ]) def forward(self, x, maskNone): for layer in self.layers: x layer(x, mask) return x3.7 解码器层与解码器pythonclass DecoderLayer(nn.Module): def __init__(self, d_model, n_heads, d_ff, dropout0.1): super().__init__() self.self_attn MultiHeadAttention(d_model, n_heads, dropout) self.cross_attn MultiHeadAttention(d_model, n_heads, dropout) self.feed_forward PositionwiseFeedForward(d_model, d_ff, dropout) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.norm3 nn.LayerNorm(d_model) self.dropout1 nn.Dropout(dropout) self.dropout2 nn.Dropout(dropout) self.dropout3 nn.Dropout(dropout) def forward(self, x, encoder_output, src_maskNone, tgt_maskNone): # 子层1: 掩码自注意力只看左边 attn_output self.self_attn(x, x, x, tgt_mask) x self.norm1(x self.dropout1(attn_output)) # 子层2: 交叉注意力Q来自解码器K/V来自编码器 attn_output self.cross_attn(x, encoder_output, encoder_output, src_mask) x self.norm2(x self.dropout2(attn_output)) # 子层3: 前馈网络 ff_output self.feed_forward(x) x self.norm3(x self.dropout3(ff_output)) return x class Decoder(nn.Module): def __init__(self, config): super().__init__() self.layers nn.ModuleList([ DecoderLayer(config.d_model, config.n_heads, config.d_ff, config.dropout) for _ in range(config.n_layers) ]) def forward(self, x, encoder_output, src_maskNone, tgt_maskNone): for layer in self.layers: x layer(x, encoder_output, src_mask, tgt_mask) return x3.8 完整的 Transformer 模型pythonclass Transformer(nn.Module): def __init__(self, config): super().__init__() self.config config # 嵌入层 self.encoder_embedding nn.Embedding(config.vocab_size, config.d_model) self.decoder_embedding nn.Embedding(config.vocab_size, config.d_model) # 位置编码 self.positional_encoding PositionalEncoding( config.d_model, config.max_seq_len, config.dropout ) # 编码器与解码器 self.encoder Encoder(config) self.decoder Decoder(config) # 输出层 self.output_linear nn.Linear(config.d_model, config.vocab_size) # 初始化参数 self._init_parameters() def _init_parameters(self): for p in self.parameters(): if p.dim() 1: nn.init.xavier_uniform_(p) def generate_src_mask(self, src): 生成编码器的填充掩码将 padding 位置设为 0 # src: (batch, seq_len) src_mask (src ! 0).unsqueeze(1).unsqueeze(2) # (batch, 1, 1, seq_len) return src_mask def generate_tgt_mask(self, tgt): 生成解码器的因果掩码防止看到未来 batch_size, seq_len tgt.size() # 1. 填充掩码 tgt_pad_mask (tgt ! 0).unsqueeze(1).unsqueeze(2) # (batch, 1, 1, seq_len) # 2. 后续掩码上三角矩阵 subsequent_mask torch.triu(torch.ones((seq_len, seq_len), devicetgt.device), diagonal1).bool() subsequent_mask subsequent_mask.unsqueeze(0).unsqueeze(0) # (1, 1, seq_len, seq_len) # 合并两者都为 True 的位置才允许关注 tgt_mask tgt_pad_mask ~subsequent_mask return tgt_mask def forward(self, src, tgt): 参数: src: 源序列 (batch, src_len) tgt: 目标序列 (batch, tgt_len) 返回: logits: (batch, tgt_len, vocab_size) src_mask self.generate_src_mask(src) tgt_mask self.generate_tgt_mask(tgt) # 编码器 src_emb self.encoder_embedding(src) src_emb self.positional_encoding(src_emb) encoder_output self.encoder(src_emb, src_mask) # 解码器 tgt_emb self.decoder_embedding(tgt) tgt_emb self.positional_encoding(tgt_emb) decoder_output self.decoder(tgt_emb, encoder_output, src_mask, tgt_mask) # 输出投影 logits self.output_linear(decoder_output) return logits第四部分训练与优化——让 Transformer 真正工作有了模型架构如何训练它并使其收敛这一部分涵盖损失函数、优化器、正则化、以及训练中的常见陷阱。4.1 损失函数与标签平滑在原始 Transformer 中使用了交叉熵损失配合标签平滑Label Smoothing。标签平滑将硬标签one-hot转换为软标签例如将正确的概率从 1 降低到 $1-\epsilon$将 $\epsilon$ 均匀分配给其他类别。作用防止过拟合防止模型对训练数据过于自信。提高泛化能力鼓励模型学习更柔和的概率分布。代码实现pythonclass LabelSmoothingCrossEntropy(nn.Module): def __init__(self, smoothing0.1): super().__init__() self.smoothing smoothing def forward(self, pred, target): # pred: (batch * seq_len, vocab_size) # target: (batch * seq_len) n_classes pred.size(-1) log_probs F.log_softmax(pred, dim-1) # 真实标签的损失 with torch.no_grad(): true_dist torch.zeros_like(pred) true_dist.fill_(self.smoothing / (n_classes - 1)) true_dist.scatter_(1, target.unsqueeze(1), 1.0 - self.smoothing) loss (-true_dist * log_probs).sum(dim-1).mean() return loss4.2 Adam 优化器与 Noam 学习率调度Transformer 训练对学习率极其敏感。原论文使用Adam优化器并配合一种特定的预热Warmup调度策略。公式lrdmodel−0.5⋅min⁡(step−0.5,step⋅warmup_steps−1.5)lrdmodel−0.5​⋅min(step−0.5,step⋅warmup_steps−1.5)原理预热阶段学习率线性增长。这是因为模型在训练初期参数随机梯度方差较大。较小的学习率可以让模型稳定起步防止早期发散。衰减阶段学习率按步数的倒数平方根衰减帮助模型在后期精细微调。代码实现pythonclass NoamOpt: def __init__(self, model_size, factor, warmup, optimizer): self.optimizer optimizer self._step 0 self.warmup warmup self.factor factor self.model_size model_size self._rate 0 def step(self): self._step 1 rate self.rate() for p in self.optimizer.param_groups: p[lr] rate self._rate rate self.optimizer.step() def rate(self, stepNone): if step is None: step self._step return self.factor * (self.model_size ** (-0.5) * min(step ** (-0.5), step * self.warmup ** (-1.5))) def get_std_opt(model, d_model, factor1, warmup4000): optimizer torch.optim.Adam(model.parameters(), lr0, betas(0.9, 0.98), eps1e-9) return NoamOpt(d_model, factor, warmup, optimizer)4.3 正则化技巧Dropout在子层输出注意力权重和前馈网络后应用。原论文设置 $p0.1$。权重衰减Weight Decay即 L2 正则化在 Adam 中可通过weight_decay参数设置。梯度裁剪Gradient Clipping虽然原始 Transformer 未强调但在大规模训练中如 BERT、GPT为了防止梯度爆炸通常设置最大范数 $max_norm1.0$。pythontorch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)4.4 训练循环示例pythondef train_epoch(model, dataloader, optimizer, criterion, device): model.train() total_loss 0 for batch in dataloader: src, tgt batch.src.to(device), batch.tgt.to(device) # 将目标序列右移一位作为解码器输入Teacher Forcing tgt_input tgt[:, :-1] tgt_output tgt[:, 1:] optimizer.optimizer.zero_grad() # 前向传播 logits model(src, tgt_input) # (batch, tgt_len-1, vocab) # 计算损失需要展平 loss criterion(logits.reshape(-1, logits.size(-1)), tgt_output.reshape(-1)) # 反向传播 loss.backward() # 梯度裁剪 torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0) # 更新参数包含学习率调度 optimizer.step() total_loss loss.item() return total_loss / len(dataloader)4.5 推理自回归生成训练时使用 Teacher Forcing直接给正确答案推理时模型需要逐步生成即自回归Autoregressive解码。pythondef greedy_decode(model, src, max_len, start_token, end_token, device): model.eval() src src.to(device) src_mask model.generate_src_mask(src) # 编码器前向 src_emb model.encoder_embedding(src) src_emb model.positional_encoding(src_emb) encoder_output model.encoder(src_emb, src_mask) # 初始化目标序列为 [start_token] tgt torch.LongTensor([[start_token]]).to(device) for _ in range(max_len - 1): tgt_mask model.generate_tgt_mask(tgt) tgt_emb model.decoder_embedding(tgt) tgt_emb model.positional_encoding(tgt_emb) decoder_output model.decoder(tgt_emb, encoder_output, src_mask, tgt_mask) logits model.output_linear(decoder_output) next_token logits[:, -1, :].argmax(dim-1).unsqueeze(1) tgt torch.cat([tgt, next_token], dim1) if next_token.item() end_token: break return tgt第五部分深入变体与应用——Transformer 的进化之路原始 Transformer 开创了时代但随后的改进和变体层出不穷。这里介绍几个关键的发展方向。5.1 BERT双向编码器表示BERTBidirectional Encoder Representations from Transformers只使用了 Transformer 的编码器部分并引入了掩码语言模型MLM和下一句预测NSP的预训练任务。双向性与解码器不同BERT 的编码器可以同时看到左右两侧的上下文使其适合理解类任务如分类、问答、命名实体识别。创新引入了[CLS]标记作为句子级别的表示[SEP]标记分隔句子。5.2 GPT 系列自回归生成模型GPTGenerative Pre-trained Transformer只使用了 Transformer 的解码器部分保留了因果掩码专注于自回归生成。演进GPT-1 使用无监督预训练有监督微调GPT-2 证明零样本学习能力GPT-3 引入上下文学习In-Context LearningGPT-4 扩展到多模态。关键技术因果自注意力Causal Self-Attention确保生成时只依赖左侧上下文。5.3 高效 Transformer原始 Transformer 的复杂度是 $O(n^2)$处理超长序列如整本书、高分辨率图像时内存和计算成本极高。因此出现了一系列高效变体稀疏注意力Sparse AttentionLongformer使用滑动窗口 全局注意力将复杂度降至 $O(n)$。BigBird结合滑动窗口、随机和全局注意力近似全注意力的效果。低秩近似Linformer通过投影矩阵将 $n \times n$ 的注意力矩阵降维到 $n \times k$复杂度 $O(n)$。Performer使用核方法FAVOR近似 Softmax线性复杂度。循环记忆Transformer-XL引入片段级递归机制允许模型在长文本中复用隐藏状态解决上下文碎片问题。5.4 视觉 TransformerViTTransformer 不仅限于文本。Vision TransformerViT将图像分割为固定大小的 Patch如 16x16 像素将每个 Patch 视为一个 Token输入标准 Transformer 编码器。挑战ViT 缺乏卷积的归纳偏置平移不变性需要大规模数据预训练如 JFT-300M才能超越 CNN。混合架构后续的 Swin Transformer 引入层次化结构和滑动窗口成为计算机视觉的新 backbone。5.5 多模态与大模型现代大型语言模型LLM如 LLaMA、ChatGLM 等几乎全部基于 Transformer 架构。它们通常具备以下特征仅解码器简化结构统一训练和推理模式。旋转位置编码RoPE取代绝对位置编码能更好地外推长文本。RMSNormLayerNorm 的简化版减少计算量。SwiGLU 激活替换 ReLU提升性能。分组查询注意力GQA在推理时减少 KV 缓存的内存占用。总结与展望至此我们完整地探讨了 Transformer 网络从理论到实现的全过程。从原理上看Transformer 通过自注意力机制彻底解决了序列建模的并行化和长距离依赖问题。从实现上看它由嵌入层、位置编码、多头注意力、前馈网络、残差连接和层归一化等模块精妙组合而成。从训练上看它依赖 Adam 优化器、Noam 学习率调度、标签平滑和强大的正则化才能稳定收敛。从发展上看它衍生出 BERT、GPT、ViT 等众多变体统治了 NLP 并扩展到了 CV、语音、生物信息学等领域。
返回列表