残差连接的作用:为什么深度网络离不开它

副标题 / 摘要 残差连接通过“旁路”让梯度更容易传播,是深层网络可训练的关键。本文从原理到工程实践梳理残差的作用,并给出最小 PyTorch 示例。 预计阅读时长:12~16 分钟 标签:residual、skip-connection、transformer SEO 关键词:残差连接, ResNet, Transformer 元描述:系统解释残差连接为何能提升深度网络训练稳定性,并给出可运行示例。 目标读者 想理解残差连接价值的入门读者 在深层网络训练中遇到不稳定的工程实践者 关注 Transformer/ResNet 结构设计的开发者 背景 / 动机 深层网络容易梯度消失或爆炸,训练难以收敛。 残差连接通过“恒等映射”提供一条更短的梯度通道,使深层网络可训练。 它也是 ResNet 与 Transformer 的基础结构之一。 核心概念 残差连接(Skip/Residual):输出 = 输入 + 子层变换。 恒等映射:让网络学习“增量”而非全部映射。 梯度流动:减少梯度衰减,提高可训练性。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 残差连接的思路是: 如果一个深层网络难以直接学习映射 H(x),那就让它学习 F(x) = H(x) - x。 这样输出变成 x + F(x),训练更容易。 基础示例(1) 深层 MLP 加残差后 loss 更稳定、收敛更快。 基础示例(2) Transformer 每个子层都带残差,保证梯度可传播。 实践指南 / 步骤 在深层块中加入 x + f(x) 结构。 若维度不一致,用线性投影对齐。 配合 LayerNorm/RMSNorm 提升稳定性。 可运行示例(最小残差对比) import torch import torch.nn as nn torch.manual_seed(42) class PlainMLP(nn.Module): def __init__(self, dim=64, depth=6): super().__init__() layers = [] for _ in range(depth): layers += [nn.Linear(dim, dim), nn.ReLU()] self.net = nn.Sequential(*layers) def forward(self, x): return self.net(x) class ResMLP(nn.Module): def __init__(self, dim=64, depth=6): super().__init__() self.blocks = nn.ModuleList([ nn.Sequential(nn.Linear(dim, dim), nn.ReLU()) for _ in range(depth) ]) def forward(self, x): for block in self.blocks: x = x + block(x) return x x = torch.randn(8, 64) plain = PlainMLP() res = ResMLP() print(plain(x).shape, res(x).shape) 解释与原理 残差提供恒等路径,使梯度能绕过非线性层。 深层网络更容易学习“增量”,降低优化难度。 在 Transformer 中,残差 + 归一化是稳定训练核心。 C — Concepts(核心思想) 方法类型 残差连接属于架构层面的优化技巧,目的是改善训练稳定性与可扩展性。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

Attention 的复杂度与为什么需要位置编码

副标题 / 摘要 Self-attention 的 O(n^2) 复杂度是 Transformer 的主要瓶颈;位置编码则让模型区分顺序与相对位置。本文用 ACERS 框架解释复杂度来源与位置编码必要性,并提供最小示例。 预计阅读时长:14~18 分钟 标签:attention、positional-encoding、complexity SEO 关键词:Attention, 位置编码, 复杂度, Transformer 元描述:说明注意力复杂度与位置编码必要性,附可运行示例。 目标读者 想理解 Transformer 性能瓶颈的入门读者 需要处理长序列的工程实践者 关注注意力优化方案的开发者 背景 / 动机 Transformer 的性能瓶颈主要来自注意力矩阵的二次复杂度。 此外,注意力本身对顺序不敏感,必须引入位置编码。 理解这两点,才能合理设计模型与优化策略。 核心概念 注意力矩阵:n x n 的相似度矩阵。 时间/空间复杂度:自注意力随序列长度二次增长。 位置编码:赋予序列位置信息,避免“顺序不分”。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 注意力需要比较每个 token 与所有 token → 复杂度是 O(n^2)。 不加位置编码,模型无法区分“我爱你”和“你爱我”。 基础示例(1) 序列长度从 128 到 1024,注意力矩阵大小从 16K 到 1M。 基础示例(2) 句子顺序交换,位置编码缺失时模型输出相同。 实践指南 / 步骤 估算序列长度与注意力矩阵大小。 需要长序列时考虑稀疏/线性注意力。 选择位置编码方案(绝对/相对/旋转)。 可运行示例(复杂度与位置编码) import torch # 注意力矩阵规模示例 for n in [128, 256, 512, 1024]: mat = n * n print(n, "->", mat, "elements") # 位置编码示例(绝对位置) seq = torch.randn(1, 4, 8) pos = torch.arange(4).unsqueeze(0) pe = torch.sin(pos.float().unsqueeze(-1) / 10000) seq_with_pos = seq + pe print(seq_with_pos.shape) 解释与原理 QK^T 产生 n x n 矩阵,这是 O(n^2) 来源。 没有位置编码,注意力对序列顺序“置换不变”。 C — Concepts(核心思想) 方法类型 复杂度分析属于算法复杂度范畴,位置编码属于序列建模补偿机制。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

为什么使用多头注意力机制:能力、稳定性与工程取舍

副标题 / 摘要 多头注意力并不是“多次重复”,而是让模型在不同子空间中同时关注不同关系。本文从原理、复杂度与工程场景出发解释其必要性,并给出最小 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:multi-head-attention、attention、transformer SEO 关键词:多头注意力, Multi-Head Attention, Transformer 元描述:系统解释多头注意力机制的优势与工程取舍,含最小示例。 目标读者 想理解 Transformer 关键设计的入门读者 需要做模型结构选型的工程实践者 关注注意力可解释性与效率的开发者 背景 / 动机 单头注意力只能在一个投影空间里“看关系”。 而自然语言/多模态里存在多种关系(语法、语义、位置、对齐)。 多头注意力让模型并行捕捉多种关系,提高表达能力与泛化。 核心概念 Head(注意力头):一个独立的注意力子空间。 子空间投影:每个头有独立的 Q/K/V 线性投影。 拼接与映射:多个头输出拼接后再线性映射回模型维度。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 单头注意力像“单一视角”。 多头注意力像“多视角协作”,同时关注不同关系。 基础示例(1) 机器翻译中,一个头关注语法对齐,另一个头关注实体对齐。 基础示例(2) 同一序列中,一个头关注局部邻近词,另一个头关注长距离依赖。 实践指南 / 步骤 选择头数 h,保持 d_model % h == 0。 每个头在子空间 d_head = d_model / h 中计算注意力。 拼接各头输出,线性投影回 d_model。 观察注意力分布是否更丰富。 可运行示例(最小多头注意力) import torch import torch.nn as nn torch.manual_seed(42) mha = nn.MultiheadAttention(embed_dim=32, num_heads=4, batch_first=True) x = torch.randn(2, 5, 32) attn_out, attn_weights = mha(x, x, x) print(attn_out.shape) print(attn_weights.shape) 解释与原理 每个头在不同线性子空间建模关系。 多头输出拼接后,模型获得更丰富的特征组合。 这使得同一层能同时学习多种依赖模式。 C — Concepts(核心思想) 方法类型 多头注意力属于并行子空间注意力建模范式。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

Transformer 结构描述:从编码器到解码器

副标题 / 摘要 Transformer 由编码器与解码器堆叠而成,核心是自注意力与前馈网络。本文从结构出发解释各模块职责,并提供最小可运行示例与工程场景。 预计阅读时长:16~20 分钟 标签:transformer、attention、encoder-decoder SEO 关键词:Transformer, 编码器, 解码器, 注意力机制 元描述:系统描述 Transformer 结构与工程应用,含最小示例。 目标读者 想理解 Transformer 结构的入门读者 需要搭建 NLP/多模态模型的工程实践者 关注模型架构取舍的开发者 背景 / 动机 在 Transformer 出现之前,序列建模主要依赖 RNN。 Transformer 用注意力替代循环,大幅提升并行性与可扩展性。 理解其结构,是学习大模型的起点。 核心概念 Encoder/Decoder:编码器负责理解输入,解码器负责生成输出。 Self-Attention:同一序列内部建模依赖。 Cross-Attention:解码器对编码器输出做对齐。 FFN:逐位置前馈网络。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 Transformer 的流程可以理解为: 编码器把输入序列变成上下文表示。 解码器在生成时,通过 cross-attention 读取编码器信息。 多层堆叠形成深层表达。 基础示例(1) 机器翻译:编码器读英文,解码器生成中文。 基础示例(2) 文本生成:只保留解码器,逐词预测下一个 token。 实践指南 / 步骤 选择结构:encoder-decoder(翻译)或 decoder-only(生成)。 设置模型参数:层数、隐藏维度、注意力头数。 训练:使用适当的损失(MLM/CLM)。 推理:启用因果 mask 或 cross-attention。 可运行示例(最小 Transformer 模块) import torch import torch.nn as nn torch.manual_seed(42) model = nn.Transformer( d_model=32, nhead=4, num_encoder_layers=2, num_decoder_layers=2, dim_feedforward=64, batch_first=True, ) src = torch.randn(2, 5, 32) tgt = torch.randn(2, 4, 32) out = model(src, tgt) print(out.shape) 解释与原理 编码器输出为“上下文记忆”。 解码器 self-attn 保证自回归顺序。 cross-attn 让解码器读取编码器信息。 C — Concepts(核心思想) 方法类型 Transformer 属于注意力驱动的序列建模架构。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

为什么 GPT 是 Decoder-Only:自回归生成的最佳形态

副标题 / 摘要 GPT 采用 decoder-only 结构是为了极致匹配自回归生成任务:因果注意力保证顺序一致性,结构简化降低训练与推理成本。本文对比 encoder-only 与 encoder-decoder,并给出最小 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:gpt、decoder-only、autoregressive SEO 关键词:GPT, Decoder-Only, 自回归, Causal Attention 元描述:从任务目标到工程成本,解释 GPT 为什么选择 decoder-only 结构。 目标读者 想理解 GPT 架构选择的入门读者 需要做生成模型选型的工程实践者 想对比不同 Transformer 结构的开发者 背景 / 动机 在文本生成任务中,模型必须严格遵循“从左到右”的因果顺序。 GPT 的 decoder-only 结构天然满足这一目标,同时简化了模型设计。 但它与 encoder-only、encoder-decoder 的差异常被混淆,需要系统梳理。 核心概念 Decoder-only:仅使用解码器堆叠 + 因果自注意力。 Encoder-only:双向自注意力,擅长理解任务。 Encoder-decoder:编码输入再解码输出,擅长序列到序列任务。 Causal Mask:确保 token 只能看见左侧历史。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 GPT 的任务是“预测下一个词”,所以只需要解码器并遵守因果顺序。 Encoder-only(如 BERT)不适合生成,因为它能看到未来词。 Encoder-decoder(如 T5)适合翻译/摘要,但结构更复杂。 基础示例(1) 输入:“今天是” → 模型预测“周五”。 这要求模型只能看到“今天是”,不能看到未来词。 基础示例(2) 机器翻译需要“源序列 → 目标序列”,更适合 encoder-decoder。 实践指南 / 步骤 任务为生成/续写 → 优先 decoder-only。 任务为理解/分类 → 优先 encoder-only。 任务为序列到序列 → 优先 encoder-decoder。 可运行示例(最小因果注意力) import torch import torch.nn.functional as F def causal_attention(x): # x: (batch, seq, dim) scores = x @ x.transpose(-2, -1) seq = x.size(1) mask = torch.tril(torch.ones(seq, seq)).bool() scores = scores.masked_fill(~mask, float("-inf")) weights = F.softmax(scores, dim=-1) return weights @ x x = torch.randn(1, 4, 8) out = causal_attention(x) print(out.shape) 解释与原理 因果 mask 保证 token 只依赖左侧历史。 这与自回归目标完全一致,避免信息泄露。 Decoder-only 结构也更容易并行化与扩展模型规模。 C — Concepts(核心思想) 方法类型 GPT 属于自回归生成模型,采用 decoder-only 结构 + 因果自注意力。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

BERT vs GPT:预训练任务与应用差异

副标题 / 摘要 BERT 通过 MLM/NSP 学习双向语义,GPT 通过 CLM 学习自回归生成。本文用 ACERS 框架对比两者预训练任务与应用场景,并提供最小 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:bert、gpt、pretraining SEO 关键词:BERT, GPT, MLM, CLM 元描述:对比 BERT 与 GPT 的预训练目标与工程应用差异。 目标读者 想入门理解 BERT 与 GPT 核心差异的读者 需要做模型选型的工程实践者 关注 NLP 任务适配策略的开发者 背景 / 动机 BERT 和 GPT 经常被混用,但它们的预训练目标决定了“擅长什么”。 理解 MLM 与 CLM 的差异,能更快做出任务匹配与架构选型。 核心概念 MLM(Masked Language Modeling):随机遮蔽词,预测被遮蔽词。 NSP(Next Sentence Prediction):判断两句是否相邻(BERT 原版)。 CLM(Causal Language Modeling):预测下一个词(自回归)。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 BERT 是“看全句补空词”的双向理解模型。 GPT 是“从左到右续写”的生成模型。 基础示例(1) 输入:“北京是[MASK]国首都” → BERT 预测“中”。 基础示例(2) 输入:“北京是中国” → GPT 预测下一个词“首都”。 实践指南 / 步骤 任务是理解/分类 → 首选 BERT 类模型。 任务是生成/续写 → 首选 GPT 类模型。 推理时注意:BERT 需要 [MASK],GPT 需要 prompt。 可运行示例(最小 PyTorch 逻辑) import torch import torch.nn.functional as F # MLM: 预测被遮蔽位置 vocab = 100 seq = torch.tensor([[1, 2, 3, 4]]) mask_pos = 2 logits = torch.randn(1, 4, vocab) mlm_loss = F.cross_entropy(logits[:, mask_pos], torch.tensor([3])) print("MLM loss:", mlm_loss.item()) # CLM: 预测下一个 token logits = torch.randn(1, 4, vocab) labels = torch.tensor([[2, 3, 4, 5]]) clm_loss = F.cross_entropy(logits[:, :-1].reshape(-1, vocab), labels[:, 1:].reshape(-1)) print("CLM loss:", clm_loss.item()) 解释与原理 MLM 学到双向上下文,因此更适合理解类任务。 CLM 强调顺序生成,因此更适合生成类任务。 GPT 不需要特殊 [MASK],推理更自然。 C — Concepts(核心思想) 方法类型 BERT 属于双向编码器预训练,GPT 属于自回归生成预训练。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

SGD vs Adam:优化器原理与工程取舍

副标题 / 摘要 SGD 简洁稳定,Adam 自适应学习率收敛更快。本文用 ACERS 框架对比两者原理与工程取舍,并给出最小 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:sgd、adam、optimizer SEO 关键词:SGD, Adam, 优化器, 动量 元描述:对比 SGD 与 Adam 的训练特性与使用场景。 目标读者 想理解优化器差异的入门读者 需要做训练稳定性与收敛速度取舍的工程实践者 想掌握常见调参策略的开发者 背景 / 动机 优化器决定训练速度与最终性能。 SGD 以稳定著称,Adam 以快速收敛著称。 理解两者差异有助于在不同任务中做更合理的选择。 核心概念 SGD:基于当前梯度更新参数。 Momentum:引入历史梯度方向,加速收敛。 Adam:结合动量与 RMSProp,自适应学习率。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 SGD:每步朝“当前梯度方向”走。 Adam:用历史梯度估计方向,同时对每个参数自适应调节步长。 基础示例(1) SGD 在噪声大时会“抖动”,收敛慢但稳定。 基础示例(2) Adam 在稀疏梯度场景(NLP)通常收敛更快。 实践指南 / 步骤 快速验证效果 → Adam。 追求最终泛化 → SGD + 动量。 对比验证集曲线,而非只看训练 loss。 可运行示例(最小 PyTorch 对比) import torch import torch.nn as nn torch.manual_seed(42) x = torch.randn(128, 10) y = torch.randn(128, 1) model = nn.Linear(10, 1) loss_fn = nn.MSELoss() sgd = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9) for _ in range(5): pred = model(x) loss = loss_fn(pred, y) sgd.zero_grad() loss.backward() sgd.step() adam = torch.optim.Adam(model.parameters(), lr=1e-2) for _ in range(5): pred = model(x) loss = loss_fn(pred, y) adam.zero_grad() loss.backward() adam.step() print("done") 解释与原理 SGD 只依赖当前梯度,步长固定。 Adam 用一阶/二阶动量估计,使得学习率对每个参数自适应。 C — Concepts(核心思想) 方法类型 SGD 是一阶优化基线,Adam 是自适应学习率优化。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

LoRA 初始化的常见方法与工程取舍

副标题 / 摘要 LoRA 的初始化方式会直接影响训练稳定性与收敛速度。本文按 ACERS 结构对比标准正态、He、Xavier 与归一化初始化,并提供最小 PyTorch 示例。 预计阅读时长:14~18 分钟 标签:lora、initialization、finetuning SEO 关键词:LoRA, 初始化, He, Xavier 元描述:对比 LoRA 的常见初始化策略与工程取舍,给出可运行代码。 目标读者 正在做 LoRA 微调的入门读者 需要提升训练稳定性与收敛速度的工程实践者 想系统理解初始化策略的开发者 背景 / 动机 LoRA 把低秩矩阵插入到线性层中,新增参数很少。 但“初始化方式”决定了模型初始扰动幅度,进而影响收敛与稳定性。 在实际工程中,初始化常常比优化器参数更敏感。 核心概念 低秩分解:LoRA 用 W + ΔW 表达更新,其中 ΔW = B A。 缩放系数:常用 α / r 控制 LoRA 更新幅度。 初始化策略:决定 A 与 B 的初始分布。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 LoRA 的核心是“在不改动原权重的情况下,增加一个低秩增量”。 初始化方式决定了这个增量是否“从 0 开始”以及“起步有多快”。 基础示例(1) 若 B 初始化为全 0:模型初始行为与原模型一致,训练更稳定。 基础示例(2) 若 A 与 B 都较大:初始扰动过强,可能导致 loss 波动。 实践指南 / 步骤 选择 LoRA rank r 与缩放系数 α。 选初始化策略:保守(B=0)或激进(He/Xavier)。 小批量跑 100~200 steps 观察 loss 变化。 若发散,优先减小初始化尺度或 α。 可运行示例(最小 PyTorch LoRA 初始化) import torch import torch.nn as nn torch.manual_seed(42) class LoRALinear(nn.Module): def __init__(self, in_dim, out_dim, r=4, alpha=8, init="normal"): super().__init__() self.weight = nn.Parameter(torch.randn(out_dim, in_dim) * 0.02) self.r = r self.alpha = alpha self.scale = alpha / r self.A = nn.Parameter(torch.zeros(r, in_dim)) self.B = nn.Parameter(torch.zeros(out_dim, r)) self.reset_parameters(init) def reset_parameters(self, init): if init == "normal": nn.init.normal_(self.A, mean=0.0, std=0.02) nn.init.zeros_(self.B) elif init == "he": nn.init.kaiming_normal_(self.A, nonlinearity="linear") nn.init.zeros_(self.B) elif init == "xavier": nn.init.xavier_normal_(self.A) nn.init.zeros_(self.B) elif init == "normalized": nn.init.normal_(self.A, mean=0.0, std=1.0 / (self.r ** 0.5)) nn.init.zeros_(self.B) else: raise ValueError("unknown init") def forward(self, x): delta = (self.B @ self.A) * self.scale w = self.weight + delta return x @ w.t() x = torch.randn(2, 8) layer = LoRALinear(8, 4, r=4, alpha=8, init="xavier") print(layer(x).shape) 解释与原理 经典 LoRA 做法是让 B 初始化为 0:初始增量为 0,稳定。 A 的初始化控制低秩子空间的方向分布。 He/Xavier 更适合在“非线性后接层”使用,但 LoRA 通常在 linear 上。 C — Concepts(核心思想) 方法类型 LoRA 初始化属于权重初始化范式,核心目标是控制梯度尺度与稳定性。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

LLaMA 中 RMSNorm 相比 LayerNorm 的优势

副标题 / 摘要 LLaMA 使用 RMSNorm 替代 LayerNorm,主要是为了简化计算、提升训练稳定性与推理效率。本文用公式、示例与工程场景讲清差异,并提供最小 PyTorch 代码。 预计阅读时长:12~16 分钟 标签:rmsnorm、layernorm、llama、pytorch SEO 关键词:RMSNorm, LayerNorm, LLaMA, 归一化 元描述:解释 RMSNorm 与 LayerNorm 的差异与优势,并给出可运行的 PyTorch 示例。 目标读者 想理解 LLaMA 架构细节的入门读者 关注训练/推理效率的工程实践者 需要在模型中选择归一化方案的开发者 背景 / 动机 归一化是稳定训练的关键步骤。 LayerNorm 是 Transformer 的默认选择,但在大模型中成本可观。 RMSNorm 用更少的计算达到相似效果,是 LLaMA 等模型的常见替代。 核心概念 LayerNorm(LN):对每个 token 的特征维度做均值和方差归一化。 RMSNorm:只做均方根归一化,不减均值。 缩放参数:两者都保留可学习的缩放向量 g。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 LayerNorm:把每个 token 的特征变成“均值 0、方差 1”。 RMSNorm:只把特征的“幅度”缩放到稳定范围,不强制均值为 0。 基础示例(1) 输入向量 [1, 2, 3],LN 会中心化;RMSNorm 只缩放长度。 基础示例(2) 在大 batch 推理时,RMSNorm 少了一次均值计算,吞吐更高。 实践指南 / 步骤 若追求推理效率与训练稳定性,优先尝试 RMSNorm。 如果模型对偏移敏感,可保留 LN 或搭配残差调参。 对比训练曲线与损失波动,确认稳定性。 可运行示例(最小 PyTorch 对比) import torch import torch.nn as nn torch.manual_seed(42) class RMSNorm(nn.Module): def __init__(self, dim, eps=1e-6): super().__init__() self.eps = eps self.weight = nn.Parameter(torch.ones(dim)) def forward(self, x): # x: (..., dim) rms = x.pow(2).mean(dim=-1, keepdim=True).add(self.eps).sqrt() x = x / rms return x * self.weight x = torch.randn(2, 4, 8) ln = nn.LayerNorm(8) rms = RMSNorm(8) out_ln = ln(x) out_rms = rms(x) print(out_ln.mean(dim=-1)) print(out_rms.mean(dim=-1)) print(out_ln.std(dim=-1)) print(out_rms.std(dim=-1)) 解释与原理 LN 同时消除均值与缩放;RMSNorm 只控制尺度。 RMSNorm 计算少、数值更稳定,适合大模型训练。 由于不做中心化,RMSNorm 可能保留有用的偏移信息。 C — Concepts(核心思想) 方法类型 两者都属于特征归一化,用于稳定训练并加速收敛。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]

Self-Attention vs Cross-Attention:机制、差异与工程应用

副标题 / 摘要 Self-attention 在同一序列内建模元素关系,Cross-attention 在两个序列之间做对齐。本文用公式、示例与最小可运行代码解释两者差异,并给出工程场景建议。 预计阅读时长:14~18 分钟 标签:attention、self-attention、cross-attention SEO 关键词:Self-Attention, Cross-Attention, 注意力机制, Transformer 元描述:系统对比 self-attention 与 cross-attention 的机制差异与应用场景。 目标读者 想理解 Transformer 关键机制的入门读者 需要区分编码器/解码器注意力的工程实践者 从事多模态应用、关注对齐策略的开发者 背景 / 动机 注意力机制是 Transformer 的核心。 但很多工程误用来自于“分不清 self 和 cross”。 理解两者的计算图和适用场景,能直接减少模型设计与性能调优的试错成本。 核心概念 Query / Key / Value(Q/K/V):注意力的三元组。 Self-attention:Q、K、V 来自同一序列。 Cross-attention:Q 来自目标序列,K、V 来自源序列。 对齐(Alignment):跨序列的语义匹配。 A — Algorithm(题目与算法) 用通俗语言说明主题内容 Self-attention:自己“看自己”,适合建模序列内部依赖。 Cross-attention:一个序列“看另一个序列”,适合对齐或条件生成。 基础示例(1) 机器翻译的解码器在生成当前词时,需要关注源语言句子 → cross-attention。 基础示例(2) 语言模型内部每个 token 关注上下文 → self-attention。 实践指南 / 步骤 明确是否需要跨序列对齐:是 → cross-attention。 仅建模单序列依赖:用 self-attention。 组合使用:编码器 self-attn + 解码器 self-attn + 交叉注意力。 可运行示例(最小注意力计算) import torch import torch.nn.functional as F def attention(q, k, v): scores = q @ k.transpose(-2, -1) / (q.size(-1) ** 0.5) weights = F.softmax(scores, dim=-1) return weights @ v # Self-attention: Q/K/V 同源 x = torch.randn(2, 4, 8) # batch, seq, dim self_out = attention(x, x, x) print(self_out.shape) # Cross-attention: Q 来自目标序列, K/V 来自源序列 q = torch.randn(2, 3, 8) kv = torch.randn(2, 5, 8) cross_out = attention(q, kv, kv) print(cross_out.shape) 解释与原理 Self-attention 输出与输入序列长度一致。 Cross-attention 输出长度与 Query 序列一致。 在编码器-解码器结构中,cross-attn 是桥梁。 C — Concepts(核心思想) 方法类型 Self-attention 属于序列内部建模,cross-attention 属于跨序列对齐。 ...

2026年1月24日 · 2 分钟 · map[name:Jeanphilo]