第 1 章:语言基础与预处理
15. 什么是 Multi-query Attention (MQA)?它如何节省显存? [校: ★★★ | 社: ★★★★★]
子问题拆解(引导思考)
15.1 在 LLM 推理时,最大的显存开销来自哪里?
并非模型参数本身,而是KV Cache (Key-Value 缓存)。在自回归生成中,为避免重复计算历史 Token 的 KKK 和 VVV,系统会将其缓存。对于 MHA,每个头都需独立存储一份 KV,导致缓存体积随头数线性增长。
15.2 MQA 的核心思想是什么?
解耦 Query 与 KV 的头数 :保留多头 Query 以维持模型的表达能力,但将 Key 和 Value 压缩为单头。这样,所有 Query 头"共用"同一组上下文表示。
15.3 为何 KV 共享能大幅节省显存?
假设模型有 32 个头,序列长度为 4096,每个头维度为 128:
- MHA 的 KV Cache :2×32×4096×128≈33.5 M2 \times 32 \times 4096 \times 128 \approx 33.5\,\text{M}2×32×4096×128≈33.5M 元素
- MQA 的 KV Cache :2×1×4096×128≈1.05 M2 \times 1 \times 4096 \times 128 \approx 1.05\,\text{M}2×1×4096×128≈1.05M 元素
显存占用减少 32 倍,这对长上下文推理至关重要。
15.4 MQA 是否影响训练效率?
几乎不影响。训练时可并行处理整个序列,KV 计算开销占比小。MQA 的优势主要体现在推理阶段------此时生成是逐 Token 进行的,频繁读取 KV Cache 成为瓶颈。
15.5 为什么主流模型不直接用 MQA?
虽然 MQA 极省显存,但精度损失不可忽视。单头 KV 限制了模型对不同语义关系的建模能力(如无法同时关注局部语法和全局指代)。因此,工业界更倾向采用折中方案------GQA。
现在,让我们看看标准答案是如何精准刻画 MQA 的设计动机与工程价值的:
【基本原理】
Multi-query Attention (MQA) 是由 Google 在 2019 年提出的一种注意力机制变体。在标准的 Multi-head Attention (MHA) 中,每个 Query (Q) 头都有自己对应的 Key (K) 和 Value (V) 头。而 MQA 则采取了一种极端的共享策略:所有的 Query 头都共享同一组 Key 和 Value 头。
这种设计的初衷并不是为了减少训练时的计算量,而是为了解决大模型在**推理(Inference)**阶段的内存带宽瓶颈和显存占用问题。
示意图:
Multi-query Attention
Q1
Shared K & V
Q2
Q3
所有 Q 共享同一组 KV
Multi-head Attention
Q1
K1
V1
Q2
K2
V2
Q3
K3
V3
每个 Q 拥有独立的 KV
【回答模板】
- 什么是 MQA :
MQA 是注意力机制的一种简化形式。它保持 Query 依然是多头的(如 32 个头),但将 Key 和 Value 的头数缩减为 1。这意味着无论你有多少个 Query 头,生成的 KKK 和 VVV 张量在"头"这一维度上的大小始终为 1。 - 如何节省显存 :
- KV Cache 压缩 :在 LLM 自回归生成(推理)时,为了避免重复计算,我们会缓存之前所有 Token 的 KKK 和 VVV 向量(即 KV Cache)。在 MHA 中,KV Cache 的大小随头数线性增加;而在 MQA 中,由于 KV 只有一份,KV Cache 的显存占用直接降低到了原来的 1/h1/h1/h (hhh 为原有的头数)。
- 带宽效率提升:推理时,显卡的计算速度远快于从显存读取数据的速度(访存受限)。MQA 大幅减少了需要从显存中加载的 KV 数据量,使得 GPU 可以在相同时间内处理更多的 Token,显著提升了推理的吞吐量。
【深入理解】
- KV Cache 瓶颈问题 :
对于一个 7B 参数的模型,如果使用 MHA,在长文本场景下 KV Cache 可能会占用数十 GB 显存,甚至超过模型参数本身的体积。MQA 通过减少 KV 头的数量,将这部分开销降到了极致。例如,原先需要 32GB 存储 KV,现在仅需 1GB。 - 性能与效率的博弈 :
虽然 MQA 极大地提升了速度,但它也带来了一定的精度损失。因为所有的 QQQ 都去同一个 KKK 和 VVV 中找信息,这限制了模型捕捉多种不同语义关系的能力。 - 现状 :
由于 MQA 的精度下降有时比较明显,现在主流的大模型(如 Llama 3)更多采用 Grouped-query Attention (GQA),它在 MHA(不共享)和 MQA(全共享)之间取了折中,既保留了性能又兼顾了显存优化。
16. 什么是 Grouped-query Attention (GQA)? [校: ★★★ | 社: ★★★★]
子问题拆解(引导思考)
16.1 MHA 和 MQA 各有什么优缺点?
- MHA:表达能力强,但 KV Cache 巨大,推理慢;
- MQA:推理极快、显存省,但表达能力弱,精度下降。
16.2 GQA 如何平衡二者?
引入分组机制 :将 NNN 个 Query 头分为 GGG 组,每组分配独立的 KV 头。例如,32 个 Q 头分为 8 组,则只需 8 个 KV 头------比 MHA 少 4 倍,比 MQA 多 8 倍。
16.3 为什么"分组"能接近 MHA 的性能?
因为每组内的多个 Query 仍可共享一个"局部多样"的上下文表示。8 组 KV 已足以覆盖主要的语义模式(如句法、指代、主题等),避免了 MQA 的"信息瓶颈"。
16.4 GQA 对推理吞吐量有何影响?
KV Cache 体积降至 MHA 的 1/G1/G1/G,显存带宽需求同步下降。在 A100/H100 等设备上,GQA 可使长上下文生成速度提升 2--4 倍,同时几乎不损失任务性能。
16.5 为何 Llama 3 等模型选择 GQA?
在 70B+ 级别模型中,推理成本决定落地可行性 。GQA 在精度损失 <1% 的前提下,将推理吞吐提升数倍,是当前性价比最高的注意力变体。
现在,让我们看看标准答案是如何系统阐述 GQA 的架构优势与工业价值的:
【基本原理】
Grouped-query Attention (GQA) 是注意力机制演进中的一个重要里程碑。它是 Multi-head Attention (MHA) 和 Multi-query Attention (MQA) 的折中方案。
在 LLM 推理时,显存带宽往往是瓶颈。MHA 虽然效果好但 KV Cache 巨大;MQA 极大地压缩了 KV Cache 但模型表达能力受损。GQA 通过将 Query 头分为若干组,每一组内的 Query 共享同一个 Key 和 Value 头,从而在性能(精度)与效率(速度)之间找到了"黄金分割点"。
示意图:
Multi-query Attention
Q1, Q2, Q3, Q4
Shared KV
所有 Q 共享唯一的一对 KV
Grouped-query Attention
Q1, Q2
KV Group 1
Q3, Q4
KV Group 2
分组共享: 多个 Q 共享一对 KV
Multi-head Attention
Q1
K1
Q2
K2
Q3
K3
Q4
K4
V1
V2
V3
V4
每个 Q 对应唯一的 K 和 V
【回答模板】
- 核心逻辑 :GQA 将 NNN 个 Query 头均匀地分为 GGG 个组。在每一组内,所有的 Query 共用同一个 Key 矩阵和 Value 矩阵。
- 关键参数 :
- 如果组数 G=NG = NG=N(头数),则退化为 MHA。
- 如果组数 G=1G = 1G=1,则退化为 MQA。
- 目前 Llama 3 等模型通常采用 G=8G = 8G=8 等设置。
- 主要优势 :
- 降低显存带宽压力:在生成每个 Token 时,需要从显存加载 KV Cache。GQA 显著减少了加载量,使推理速度(吞吐量)大幅提升。
- 维持高精度:相比 MQA 这种极端的压缩,GQA 依然保留了多组 Key/Value 的多样性,模型在长文本和复杂推理上的表现非常接近全量 MHA。
【深入理解】
-
内存带宽瓶颈(Memory Bound) :
在大模型推理过程中,计算开销往往不是最耗时的,从显存读取 KV Cache 数据才是。由于 MHA 每一层都要为每个头存储独立的 KV,随着序列变长,数据读取量呈几何倍数增长。GQA 通过减少 KV 头的数量,直接砍掉了大部分数据传输开销。
-
KV Cache 的瘦身方案 :
以一个拥有 32 个 Query 头的模型为例。如果采用 MHA,推理时每个 Token 要存 32 组 KV;如果采用 GQA(分 8 组),则只需存 8 组 KV。显存占用瞬间降低到原来的 1/4,这意味着我们可以在同样的设备上支持更长的上下文长度(Context Length)和更大的 Batch Size。
-
为什么是大模型标配?
在 Llama 2 (70B) 和 Llama 3 时代,由于参数量巨大,推理性能成为了工业化落地的关键。实验证明,GQA 能够提供接近 MHA 的质量,同时在推理速度上达到 MQA 的水平。这种"几乎不亏性能,大幅提升效率"的特性,使其成为了现代高性能大模型的事实标准。
17. 解释注意力机制中的 Causal Mask 原理。 [校: ★★★★★ | 社: ★★★]
子问题拆解(引导思考)
17.1 为什么语言模型不能"看到未来"?
自回归生成的本质是:P(x1,x2,...,xT)=∏t=1TP(xt∣x<t)P(x_1, x_2, ..., x_T) = \prod_{t=1}^T P(x_t | x_{<t})P(x1,x2,...,xT)=∏t=1TP(xt∣x<t)。若模型在预测 xtx_txt 时能看到 xt+1x_{t+1}xt+1,就违反了概率链式法则,导致训练目标失真。
17.2 Causal Mask 如何实现"禁止看未来"?
通过构造一个上三角掩码矩阵 (不含对角线),将注意力得分矩阵中代表"未来"的位置置为 −∞-\infty−∞。Softmax 后,这些位置的权重变为 0,相当于完全屏蔽。
17.3 为何要用 −∞-\infty−∞ 而不是 0?
若直接设为 0,Softmax 会将其与其他有效位置一起归一化,仍可能分配非零权重。而 −∞-\infty−∞ 经 Softmax 后严格等于 0,确保绝对因果性。
17.4 Causal Mask 与 Padding Mask 能否共存?
可以。实际实现中,两者通常叠加使用:先应用 Padding Mask 屏蔽无效 token,再叠加 Causal Mask 屏蔽未来 token,最终掩码为两者的逻辑或(OR)。
17.5 Causal Mask 对训练效率有何影响?
它使得整句并行训练成为可能。虽然推理是逐词进行的,但训练时可通过 Causal Mask 一次性处理整个序列,极大提升 GPU 利用率------这是 GPT 类模型可扩展的关键。
现在,让我们看看标准答案是如何清晰揭示 Causal Mask 的数学本质与工程意义的:
【基本原理】
Causal Mask(因果掩码)是 Transformer Decoder 架构中的核心设计。其目的是在计算自注意力时,强制模型只能看到当前及之前的 Token,而不能"偷看"未来的 Token。
在自回归生成任务中(如 GPT 生成文本),模型是根据已有的词逐个预测下一个词。在预训练阶段,为了提高效率,我们会将整个句子一次性输入模型。如果不加 Causal Mask,模型在预测第 iii 个词时,就能直接通过注意力机制看到第 i+1i+1i+1 个词及后面的内容,这会导致信息泄漏(Information Leakage),使训练失去意义。
示意图:
Causal Mask 通常表现为一个下三角矩阵。在 Softmax 之前的注意力得分矩阵(Score Matrix)上覆盖此掩码。
text
输入序列: [A, B, C, D]
掩码矩阵 (1代表可见, 0代表不可见):
A B C D
A [ 1, 0, 0, 0 ] <-- A 只能看到自己
B [ 1, 1, 0, 0 ] <-- B 可以看到 A, B
C [ 1, 1, 1, 0 ] <-- C 可以看到 A, B, C
D [ 1, 1, 1, 1 ] <-- D 可以看到 A, B, C, D
实现方式: 将 0 的位置替换为 -inf (-1e9),Softmax 后权重变为 0。
【回答模板】
- 核心目的 :保证序列处理的"因果性"。确保在训练过程中,第 ttt 时刻的预测仅依赖于 111 到 ttt 时刻的输入,模拟推理时的真实场景。
- 实现手段 :
- 构造掩码:生成一个上三角(不含对角线)全为 1 的矩阵。
- 数值替换 :将该矩阵中为 1 的位置在注意力得分矩阵 QKTQK^TQKT 中替换为 −∞-\infty−∞(通常取 -1e9)。
- 归一化 :经过 Softmax 计算后,这些 −∞-\infty−∞ 的位置对应的注意力权重将变为 0。
- 应用场景:所有 Decoder-only 架构(如 GPT 系列)以及 Encoder-Decoder 架构中的 Decoder 部分。
【深入理解】
-
并行训练的关键 :
Causal Mask 的巧妙之处在于它允许并行训练 。虽然模型在推理时是逐字生成的(Sequential),但在训练时,我们可以利用 Causal Mask 屏蔽掉未来信息,从而一次性处理整个序列。这种"伪并行"通过矩阵运算极大地提升了训练效率,这种技术也被称为 Teacher Forcing 的并行版本。
-
物理意义的转变 :
加入 Causal Mask 后,原本对称的自注意力机制变成了**单向(Unidirectional)**的信息流。这使得每个 Token 的特征向量只包含其左侧的上下文信息,从而让模型具备了预测下一个词的条件概率建模能力:P(xt∣x<t)P(x_t | x_{<t})P(xt∣x<t)。
-
与 Padding Mask 的区别:
- Padding Mask 是为了遮盖补齐用的无效字符(),防止模型关注无意义区域。
- Causal Mask 是为了遮盖未来真实的标签信息,防止模型"作弊"。
在实际的 LLM 开发中,这两者通常会合并为一个组合掩码。
18. 什么是 Transformer 中的 FFN?它的参数量占比如何? [校: ★★★ | 社: ★★]
子问题拆解(引导思考)
18.1 Attention 和 FFN 在 Transformer 中分别扮演什么角色?
- Attention :负责 Token 之间的跨位置交互,建立上下文依赖("谁和谁相关?")。
- FFN :负责对每个位置的表示进行独立的非线性变换,提取和增强语义特征("这个词到底是什么意思?")。
18.2 为什么 FFN 要先升维再降维?
升维(如 d→4dd \to 4dd→4d)为模型提供了更大的表达空间,使非线性激活函数(如 GELU)能在高维流形中解耦复杂的语义组合。降维则将提炼后的核心信息压缩回原始维度,避免维度爆炸。
18.3 FFN 的参数量为何远超 Attention?
- MHA 参数 :WQ,WK,WV,WOW_Q, W_K, W_V, W_OWQ,WK,WV,WO 各为 d×dd \times dd×d,共约 4d24d^24d2。
- FFN 参数 :W1∈Rd×4dW_1 \in \mathbb{R}^{d \times 4d}W1∈Rd×4d,W2∈R4d×dW_2 \in \mathbb{R}^{4d \times d}W2∈R4d×d,共 8d28d^28d2。
因此,FFN 占单个 Transformer Block 参数量的约 2/3。
18.4 现代 LLM 如何改进 FFN?
Llama 系列采用 SwiGLU 激活:
FFN(x)=Swish(xW1)⊙(xW2)W3 \text{FFN}(x) = \text{Swish}(xW_1) \odot (xW_2) W_3 FFN(x)=Swish(xW1)⊙(xW2)W3
虽引入第三个权重矩阵 W3W_3W3,但实验证明其在相同参数量下性能优于 ReLU/GELU。
18.5 为何量化对 FFN 尤为有效?
FFN 参数量大且计算密集,在推理时频繁从显存加载权重。通过 INT4/INT8 量化可大幅减少内存带宽需求,而对其精度影响相对较小------因为 FFN 的冗余性较高。
现在,让我们看看标准答案是如何系统阐述 FFN 的结构、作用与工程意义的:
【基本原理】
FFN (Feed-Forward Network,前馈神经网络) 是 Transformer 每个层中的第二个子层。如果说 Attention 层 负责 Token 之间的"相互通讯"(跨时间步交换信息),那么 FFN 层则负责在每个位置上进行"信息加工"(对当前词的特征进行非线性变换)。
FFN 通常由两个线性变换层(全连接层)组成,中间夹着一个非线性激活函数(如 ReLU、GELU 或 SwiGLU)。其标准结构是一个"升维-激活-降维"的过程。
示意图:
功能视角
Attention: 负责跨 Token 通讯
FFN: 负责 Token 内部特征提取
输入向量 X: d_model
线性层 1: 升维至 4 * d_model
激活函数: ReLU/GELU/SwiGLU
线性层 2: 降维至 d_model
输出向量: d_model
【回答模板】
- 什么是 FFN :
在 Transformer 中,FFN 采用的是 Position-wise(逐位置) 的结构。公式表达为:
FFN(x)=Activation(xW1+b1)W2+b2\text{FFN}(x) = \text{Activation}(xW_1 + b_1)W_2 + b_2FFN(x)=Activation(xW1+b1)W2+b2
第一层线性变换将维度从 dmodeld_{model}dmodel 扩展到一个更大的中间维度 dffd_{ff}dff(通常 dff=4×dmodeld_{ff} = 4 \times d_{model}dff=4×dmodel),经过激活后,第二层再将其映射回 dmodeld_{model}dmodel。 - 参数量占比 :
在一个标准的 Transformer 块(Block)中,FFN 的参数量通常占总参数量的 2/3 左右(不计 Embedding 层)。- Attention 块参数 :WQ,WK,WV,WOW_Q, W_K, W_V, W_OWQ,WK,WV,WO 四个矩阵均为 d×dd \times dd×d,总参数约为 4d24d^24d2。
- FFN 块参数 :W1W_1W1 为 d×4dd \times 4dd×4d,W2W_2W2 为 4d×d4d \times d4d×d,总参数约为 8d28d^28d2。
- 比例:FFN 的参数量大约是 Attention 部分的两倍。
【深入理解】
- FFN 的本质是"知识库" :
有研究(如 Transformer Feed-Forward Layers Are Key-Value Memories)表明,Attention 负责从上下文中检索信息,而 FFN 的神经元则更像是在存储预训练过程中学到的"事实性知识"。当某个模式出现时,FFN 内部的特定神经元会被激活,从而将相关的语义特征提取出来。 - 升维的必要性 :
为什么要先升至 4d4d4d 再降回来?这就像是将压缩的特征在更高维的空间中"展开",利用非线性激活函数在更大的空间里进行流形变换。升维能提供足够的自由度来解耦复杂的语义特征,然后再通过降维保留最核心的信息。 - LLM 架构的变体 :
在现代 LLM(如 Llama 3)中,FFN 演进为了 SwiGLU 结构。它包含三个线性矩阵 W1,W2,W3W_1, W_2, W_3W1,W2,W3,虽然计算过程略复杂,但依然维持了大约 3×d×dff3 \times d \times d_{ff}3×d×dff 的参数规模,进一步提升了模型的知识容量。 - 计算与显存 :
由于 FFN 不涉及复杂的矩阵转置和因果掩码,它的计算密集度很高,非常适合 GPU 利用。但在模型推理阶段,由于 FFN 参数量巨大,模型权重的读取(Memory Bound)往往成为性能瓶颈,这也是为什么量化(Quantization)技术对 FFN 尤其有效的原因。
19. 解释 Residual Connection 如何解决深层网络的梯度消失。 [校: ★★★ | 社: ★★★]
子问题拆解(引导思考)
19.1 什么是梯度消失?
在深层网络中,反向传播的梯度需经过多层链式求导。若每层导数范数小于 1(如 sigmoid 导数最大为 0.25),则梯度随层数指数衰减,底层参数几乎无法更新。
19.2 残差连接如何改变梯度路径?
传统网络:xl+1=f(xl)x_{l+1} = f(x_l)xl+1=f(xl) → ∂L∂xl=∂L∂xl+1⋅f′(xl)\frac{\partial \mathcal{L}}{\partial x_l} = \frac{\partial \mathcal{L}}{\partial x_{l+1}} \cdot f'(x_l)∂xl∂L=∂xl+1∂L⋅f′(xl)
残差网络:xl+1=f(xl)+xlx_{l+1} = f(x_l) + x_lxl+1=f(xl)+xl → ∂L∂xl=∂L∂xl+1⋅(f′(xl)+1)\frac{\partial \mathcal{L}}{\partial x_l} = \frac{\partial \mathcal{L}}{\partial x_{l+1}} \cdot (f'(x_l) + 1)∂xl∂L=∂xl+1∂L⋅(f′(xl)+1)
关键:多了一个恒为 1 的项 ,即使 f′(xl)→0f'(x_l) \to 0f′(xl)→0,梯度仍能无损回传。
19.3 为什么"+x"能防止退化?
若某层无用,最优解是 f(x)=0f(x) = 0f(x)=0,此时输出 = 输入,即恒等映射。网络可自动"跳过"冗余层,确保深层性能不低于浅层。
19.4 残差连接对 Transformer 有多重要?
Transformer 通常有 32--96 层。若无残差连接,底层 Attention/FFN 的梯度在反向传播中会迅速衰减至 0,导致模型无法训练。残差连接是 LLM 可扩展性的基石。
19.5 残差连接是否影响前向信号?
是的。它也稳定了前向传播:输入信号可通过"捷径"直接传递到深层,避免因多层非线性变换导致的特征湮灭或爆炸。
现在,让我们看看标准答案是如何从数学、优化与架构三个层面揭示残差连接的核心价值的:
【基本原理】
残差连接(Residual Connection)由 He Kaiming 等人提出。其核心思想是:与其让神经网络层去直接学习一个理想的映射 H(x)H(x)H(x),不如让它去学习输入与输出之间的差值(残差) F(x)=H(x)−xF(x) = H(x) - xF(x)=H(x)−x。
最终的输出变为:Output=F(x)+xOutput = F(x) + xOutput=F(x)+x。这个"+x+x+x"的操作通过一个"捷径"(Shortcut/Skip Connection)将输入信息直接绕过非线性层传递到后面。
示意图:
捷径 Shortcut/Identity
输入 X
权重层 Fx
激活函数
权重层 Fx
- 输出: Fx + X
【回答模板】
残差连接从根本上解决了深层网络训练难的问题,其逻辑如下:
- 数学形式 :设第 lll 层的输出为 xl+1=f(xl)+xlx_{l+1} = f(x_l) + x_lxl+1=f(xl)+xl。
- 梯度流向 :根据微积分的链式法则,损失函数 L\mathcal{L}L 对输入 xlx_lxl 的导数为:
∂L∂xl=∂L∂xl+1⋅∂xl+1∂xl=∂L∂xl+1⋅(∂f(xl)∂xl+1)\frac{\partial \mathcal{L}}{\partial x_l} = \frac{\partial \mathcal{L}}{\partial x_{l+1}} \cdot \frac{\partial x_{l+1}}{\partial x_l} = \frac{\partial \mathcal{L}}{\partial x_{l+1}} \cdot \left( \frac{\partial f(x_l)}{\partial x_l} + 1 \right)∂xl∂L=∂xl+1∂L⋅∂xl∂xl+1=∂xl+1∂L⋅(∂xl∂f(xl)+1) - 核心突破 :在传统的深层网络中,梯度是通过多个小于 1 的导数连乘得到的(类似 0.9100≈00.9^{100} \approx 00.9100≈0),从而引发梯度消失。而在残差网络中,梯度表达式包含了一个常数项 "1" 。即使 f(xl)f(x_l)f(xl) 的梯度 ∂f∂x\frac{\partial f}{\partial x}∂x∂f 变得非常小,整体梯度依然能保持在 ∂L∂xl+1\frac{\partial \mathcal{L}}{\partial x_{l+1}}∂xl+1∂L 附近。
- 结论 :这个"1"为梯度提供了一条无损传输的"高速公路",使得深层信息和梯度能够跨越层级进行交互。
【深入理解】
- 打破网络加深的瓶颈 :
在残差结构出现前,简单增加网络深度会导致训练误差反而上升(退化问题)。残差连接确保了:如果某一层是多余的,模型只需将权重 f(x)f(x)f(x) 学习为 0,这一层就变成了恒等映射(Identity Mapping),至少性能不会比浅层网络差。这极大地降低了模型学习的难度。 - 模型集成(Ensemble)视角 :
有一种深刻的见解认为(如 Residual Networks Behave Like Ensembles of Relatively Shallow Networks ),残差网络并不是一个单一的极深路径,而是由指数级个不同长度的浅层路径组合而成的。这种多路径特性增强了模型的泛化能力和鲁棒性。 - 对 Transformer 的意义 :
Transformer 每一层都包含 Attention 和 FFN,如果没有残差连接,多达几十层甚至上百层的 Transformer 在反向传播时,底层(靠近输入端)的梯度会迅速衰减到 0,导致模型无法更新。残差连接是训练深层大模型(LLM)的生存基石。 - 初始化与信号传递 :
残差连接配合良好的初始化,可以使得前向传播时信号的方差、反向传播时梯度的方差在跨越层级时保持稳定,从而避免了严重的数值不稳定问题。
20. 什么是词嵌入 (Embedding)?它在计算图中是怎样的一层? [校: ★★★ | 社: ★★]
子问题拆解(引导思考)
20.1 为什么不能直接用 One-hot 编码?
One-hot 向量维度等于词表大小(如 50,000),极度稀疏且无法表达语义相似性(任意两词距离相同)。嵌入将其压缩到稠密低维空间(如 4096 维),并让语义相近的词在向量空间中靠近。
20.2 Embedding 层在计算图中是线性层吗?
逻辑上是 :输入 One-hot 向量 x∈{0,1}V\mathbf{x} \in \{0,1\}^Vx∈{0,1}V,输出 y=xW\mathbf{y} = \mathbf{x} Wy=xW,其中 W∈RV×dW \in \mathbb{R}^{V \times d}W∈RV×d。
实现上不是 :实际通过索引查找(W[idx])避免构造巨大稀疏矩阵,效率提升 O(V)→O(1)O(V) \to O(1)O(V)→O(1)。
20.3 反向传播时如何更新 Embedding?
只有当前 batch 中出现的词对应的行会接收梯度。例如,若 batch 包含 ["cat", "dog"],则仅更新 WcatW_{\text{cat}}Wcat 和 WdogW_{\text{dog}}Wdog,其余行不变。
20.4 为何要共享 Embedding 与输出层权重?
在语言模型中,预测下一个词的输出层也是一个 d×Vd \times Vd×V 矩阵。若令其等于 Embedding 矩阵的转置(Wout=Wemb⊤W_{\text{out}} = W_{\text{emb}}^\topWout=Wemb⊤),可:
- 减少近 50% 参数;
- 使输入/输出语义对齐,提升向量质量。
20.5 Embedding 是否可冻结?
可以。在某些任务(如微调)中,若语料领域接近预训练数据,可冻结 Embedding 层以减少过拟合和计算开销。
现在,让我们看看标准答案是如何清晰定义 Embedding 的本质、实现与优化策略的:
【基本原理】
词嵌入(Word Embedding)是连接自然语言与深度学习模型的"桥梁"。计算机无法直接处理离散的单词,因此需要将每个单词映射为一个连续的、低维的实数向量。
在数学上,Embedding 是一个查找表(Lookup Table) 。假设词表大小为 VVV,嵌入维度为 ddd,则 Embedding 层就是一个形状为 [V,d][V, d][V,d] 的矩阵 WWW。输入一个单词的索引 iii,输出就是矩阵中的第 iii 行。
示意图:
渲染错误: Mermaid 渲染失败: Parse error on line 5: ...] R0[Row 0: [0.1, -0.2, ...]] ----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'SQS'
【回答模板】
- 什么是词嵌入 :
词嵌入是将离散的符号(Token)转换为稠密向量(Dense Vector)的技术。相比于传统的 One-hot 编码,它具有两个核心优势:- 降维:将数万维的稀疏空间压缩到几百或上千维的连续空间。
- 语义表征:在预训练过程中,语义相似的单词在向量空间中的距离会相互接近(例如"猫"和"狗"的余弦相似度较高)。
- 计算图中的位置 :
在计算图中,Embedding 层通常被视为第一层线性变换 。虽然在工程实现上通过"索引查找"(Indexing)来加速,但其逻辑上完全等价于:输入一个 One-hot 向量 x\mathbf{x}x 与权重矩阵 WWW 相乘 ,即 y=xW\mathbf{y} = \mathbf{x}Wy=xW。- 输入 :形状为
[batch_size, seq_len]的整型张量。 - 权重 :形状为
[vocab_size, embedding_dim]的可学习参数矩阵。 - 输出 :形状为
[batch_size, seq_len, embedding_dim]的浮点型张量。
- 输入 :形状为
【深入理解】
- 高效的"矩阵乘法" :
在深度学习框架(如 PyTorch 的nn.Embedding)中,并不会真的进行 One-hot 矩阵乘法,因为 One-hot 矩阵极其稀疏,绝大多数乘法结果都是 0。使用索引查找(Index Select)可以将计算复杂度从 O(V⋅d)O(V \cdot d)O(V⋅d) 降低到 O(d)O(d)O(d),极大地提升了运算速度。 - 反向传播的特殊性 :
在反向传播(Backpropagation)过程中,Embedding 层也是极其稀疏的。每次迭代中,只有被选中的那些词对应的行(Row)会接收到梯度并进行更新,其余未出现在当前批次中的单词权重保持不变。 - 共享权重(Weight Tying) :
在许多 Transformer 模型(如 GPT)中,Embedding 层的权重矩阵与输出层(预测下一个词的 Linear 层)的权重矩阵是**共享(参数复用)**的。这样做不仅可以减少近一半的参数量,还能让词向量在输入和输出端受到双重约束,从而学习到更稳健的语义特征。 - 初始化与学习 :
Embedding 矩阵通常随机初始化,并随着模型任务(如语言模型预训练)一起进行端到端(End-to-End)训练。最终,这个矩阵会通过海量语料学习到复杂的语言规律,如性别、时态、单复数等在向量空间中的几何关系。
21. 为什么 Embedding 维度的选择通常是 2 的幂次方? [校: ★★ | 社: ★]
子问题拆解(引导思考)
21.1 Embedding 维度是否必须是 2 的幂?
不是数学必需,而是工程优选。理论上,任何正整数维度都可行。但实际中,选择 512、1024、4096 等值能显著提升硬件效率。
21.2 GPU 的 Warp 机制如何影响维度选择?
NVIDIA GPU 以 32 线程为一个 Warp,所有线程同步执行同一指令。若张量某维度是 32 的倍数,则每个线程可处理一个元素,无空闲;否则需填充或分支,降低利用率。
21.3 内存访问为何偏好对齐地址?
GPU 显存按 Cache Line(如 128 字节) 读取。若数据未对齐(如维度=767),一次读取可能跨越两个 Cache Line,触发两次内存事务,带宽效率下降近 50%。
21.4 多头注意力对维度有何约束?
设总维度 dmodel=h×dkd_{\text{model}} = h \times d_kdmodel=h×dk。若 dmodeld_{\text{model}}dmodel 是 64 的倍数(如 4096 = 64 × 64),则无论头数 hhh 是 8、16、32,每头维度 dkd_kdk 都是 64、256、128------均为硬件友好值。
21.5 为何 BERT 使用 768 而非 1024?
768 = 12(头数)× 64(每头维度)。虽然 768 不是 2 的幂(29=512,210=10242^9=512, 2^{10}=102429=512,210=1024),但其因子 64 是关键 。这说明:单头维度对齐比总维度是否为 2 的幂更重要。
现在,让我们看看标准答案是如何从硬件、算法与实践三个层面解释这一工程惯例的:
【基本原理】
在深度学习模型的实现中,Embedding 维度(如 512, 768, 1024, 4096)通常选择 2 的幂次方或其倍数。这并非出于数学理论的必然要求,而是为了适配计算机底层硬件的计算特性 (尤其是 GPU)以及内存访问效率。
示意图:内存对齐与计算效率
text
[ 维度 d = 8 (2³)] [ 维度 d = 7 (非2的幂)]
| x | x | x | x | x | x | x | x | | x | x | x | x | x | x | x | _ |
<------- 1个计算周期 -------> <------- 1个计算周期 ------->
(完全填充,无带宽浪费) (存在空白位,浪费计算/存储空间)
GPU 线程组 (Warp): [T1, T2, ..., T32]
若维度是 32 的倍数,每个线程刚好处理一个维度,实现负载绝对均衡。
【回答模板】
选择 2 的幂次方作为 Embedding 维度,主要基于以下三个工程考量:
- 硬件计算对齐(Hardware Alignment) :
现代显卡(GPU)的最小计算单元通常以 32 个线程为一个组(NVIDIA 称为 Warp )。当数据的维度是 32 或 64 的倍数时,计算任务可以均匀地分配给每个线程,避免某些线程空闲,从而最大化利用 Tensor Cores 的吞吐能力。 - 内存带宽与访存效率 :
内存(HBM/VRAM)的存取通常是按 32 字节、64 字节或 128 字节的块(Cache Line)进行的。如果 Embedding 维度对齐到 2 的幂次方,数据的起始地址和跨度更能匹配内存控制器的读取规律,减少内存读取的次数(Coalesced Memory Access),大幅提升 I/O 速度。 - 多头注意力(MHA)的均分需求 :
Transformer 架构需要将总维度 dmodeld_{model}dmodel 均分给 hhh 个注意力头。选择 2 的幂次方(如 512 分为 8 个头,每头 64)可以确保每个头的维度也是整数且对齐,避免在切分张量时产生余数或复杂的形状变换。
【深入理解】
- SIMD 向量化指令 :
CPU 上的 AVX 扩展或 GPU 的指令集底层都是 SIMD(单指令多数据流)。它们一次处理的数据长度通常是 128-bit 或 256-bit。由于浮点数(FP32)占 4 字节,这相当于一次处理 4 或 8 个元素。维度选择 2 的幂次方能完美契合这些底层指令的步长,避免额外的边界检查开销。 - 库函数的优化(如 cuBLAS, cutlass) :
NVIDIA 提供的深度学习算子库针对特定的维度(如 8, 16, 32 的倍数)编写了专门的汇编级代码优化。如果维度选择不规则,系统会回退到通用的、性能较差的算法实现。 - 例外情况 :
虽然 2 的幂次方是主流,但也并非绝对。例如 BERT-base 的维度是 768 ,它虽然不是 2 的幂,但它是 12×6412 \times 6412×64。这里 64 保证了单头的硬件对齐,12 保证了 12 个头的逻辑切分。核心原则依然是:保证单个 Attention Head 的维度对齐到 16/32/64 等硬件友好的数值。
22. 解释自回归 (Autoregressive) 的生成过程。 [校: ★★★★★ | 社: ★★★]
子问题拆解(引导思考)
22.1 自回归的核心思想是什么?
"用过去预测未来" :模型在生成第 ttt 个 Token 时,仅依赖于已生成的前 t−1t-1t−1 个 Token。这严格遵循了语言的因果性------当前词由历史上下文决定。
22.2 为何不能一次性生成整句话?
因为语言具有强顺序依赖性 。若并行生成所有词(如非自回归模型),模型无法知道"下一个词"应该与"上一个词"如何衔接,导致语义断裂或语法错误。自回归通过串行决策确保每一步都基于真实历史。
22.3 训练和推理阶段有何区别?
- 训练 :使用 Teacher Forcing ,即输入完整句子,但通过 Causal Mask 强制模型只能看到当前位置之前的 Token。此时可并行计算所有位置的损失。
- 推理 :必须逐 Token 生成,每步将新 Token 拼接到输入末尾,重新送入模型。
22.4 为什么自回归推理慢?
每生成一个 Token 都需执行一次完整的前向传播(从 Embedding 到 Output)。对于 70B 模型,单次前向可能耗时 10--50ms,生成 100 个词即需 1--5 秒------这是 LLM 延迟的主要来源。
22.5 KV Cache 如何加速自回归?
在第 ttt 步,只需计算当前 Token 的 Qt,Kt,VtQ_t, K_t, V_tQt,Kt,Vt,而 K1:t−1,V1:t−1K_{1:t-1}, V_{1:t-1}K1:t−1,V1:t−1 已缓存在显存中。Attention 计算变为:
Attention(Qt,[K1:t−1;Kt],[V1:t−1;Vt]) \text{Attention}(Q_t, [K_{1:t-1}; K_t], [V_{1:t-1}; V_t]) Attention(Qt,[K1:t−1;Kt],[V1:t−1;Vt])
避免了重复计算历史 K,VK, VK,V,将时间复杂度从 O(t2)O(t^2)O(t2) 降至 O(t)O(t)O(t)。
现在,让我们看看标准答案是如何系统阐述自回归的数学基础、工程实现与局限性的:
【基本原理】
自回归(Autoregressive, AR)生成是一种逐位(Token-by-token)迭代的序列产生机制。其核心逻辑在于:模型在生成序列的第 ttt 个元素时,会将前 t−1t-1t−1 个已经生成的元素作为输入上下文的一部分。换言之,模型当前的输出,将成为其下一轮迭代的输入。这种像"接龙"一样的递归过程,是目前绝大多数大语言模型(如 GPT、Llama)生成文本的底层模式。
示意图:
Step_3
Step_2
Step_1
Prompt
LLM
Token 1
Prompt + Token 1
LLM
Token 2
Prompt + Token 1 + Token 2
LLM
Token 3
【回答模板】
- 数学本质 :自回归生成是基于概率的链式法则(Chain Rule of Probability)。它将序列 XXX 的联合概率分布分解为一系列条件概率的乘积:
P(x1,x2,...,xT)=∏t=1TP(xt∣x1,...,xt−1)P(x_1, x_2, \dots, x_T) = \prod_{t=1}^{T} P(x_t \mid x_1, \dots, x_{t-1})P(x1,x2,...,xT)=t=1∏TP(xt∣x1,...,xt−1)
模型每一轮迭代都在预测下一个 Token 的概率分布 P(xt∣x<t)P(x_t \mid x_{<t})P(xt∣x<t)。 - 生成循环 :
- 输入:初始提示词(Prompt)。
- 预测:模型计算词表中每个单词作为下一个词的概率。
- 采样:根据某种策略(如 Greedy Search 或 Top-P Sampling)选定一个 Token。
- 拼接:将选定的 Token 拼接到已有序列末尾。
- 终止 :重复上述过程,直到模型输出了终止符号(
<EOS>)或达到了最大长度限制。
【深入理解】
- 串行推理的代价(Latency) :
由于自回归必须等待前一个词生成后才能开始下一个词的计算,这导致了 LLM 的生成无法像训练阶段那样进行大规模并行。每生成一个 Token 都要完整经过一次模型的前向传播,这是导致大模型生成速度慢(推理时延高)的根本原因。 - KV Cache 的引入 :
在自回归过程中,历史 Token 的 KKK 和 VVV 矩阵在后续每一步计算中都是重复且不变的。为了优化性能,现代模型会使用 KV Cache 技术,将这些中间状态缓存在显存中。这样,在生成第 nnn 个词时,只需要计算当前词的 Q,K,VQ, K, VQ,K,V,并与缓存的旧 K,VK, VK,V 拼接,避免了 O(n2)O(n^2)O(n2) 的重复计算,将单步复杂度降至 O(n)O(n)O(n)。 - 曝光偏差(Exposure Bias) :
在训练时,模型看到的始终是正确的历史词(Teacher Forcing);但在推理生成时,一旦某一步预测错误并被带入下一步,错误就会随时间步不断累积。这是自回归模型常见的一个退化问题,也是为什么采样策略(如 Temperature)对生成质量至关重要。 - 与非自回归(Non-Autoregressive)对比 :
非自回归模型(如某些快速翻译模型)尝试一次性并行生成所有词,虽然速度极快,但由于无法建模词语间的顺序依赖关系,生成的文本往往缺乏逻辑和流畅度。目前,自回归架构依然是追求高语义质量大模型的唯一选择。
23. 什么是各向异性 (Anisotropy) 问题? [校: ★★ | 社: ★★★]
子问题拆解(引导思考)
23.1 各向同性 vs 各向异性:理想与现实的差距?
- 理想(各向同性):词向量在高维球面上均匀分布,任意两向量夹角接近 90°,余弦相似度 ≈ 0。
- 现实(各向异性):所有向量挤在一个狭窄锥体内,任意两向量夹角很小,余弦相似度普遍 > 0.8,甚至 > 0.95。
23.2 为什么会出现"向量塌陷"?
根本原因在于语言建模目标与优化机制的副作用:
- Softmax 的极小化偏好:为最大化正确词的概率,模型倾向于将所有上下文向量拉向同一个方向(便于线性分类器区分)。
- 高频词主导:如 "the", "is" 等高频词出现次数远超低频词,导致优化过程偏向这些词的语义中心。
- LayerNorm 的归一化效应:虽稳定训练,但强制所有向量具有相同 L2 范数,抑制了空间多样性。
23.3 各向异性对下游任务有何影响?
- 语义检索失效:用余弦相似度找最相关句子时,可能返回语义无关但"位置相近"的结果。
- 聚类性能下降:K-means 等算法依赖距离度量,而塌陷空间中所有点距离相近,难以有效聚类。
- 少样本学习困难:新类别样本易被拉入已有锥体,无法形成独立语义簇。
23.4 如何检测各向异性?
计算随机采样向量对的平均余弦相似度:
- 若 ≈ 0 → 各向同性;
- 若 > 0.7 → 存在显著各向异性。
BERT-base 的平均余弦相似度常达 0.92 以上。
23.5 为何大模型仍难完全避免该问题?
尽管 GPT-4 等模型因规模更大、训练更充分而有所缓解,但只要使用自回归语言建模 + Softmax 分类头 ,向量空间就天然存在"聚集倾向"。这是目标函数诱导的几何偏置,而非训练不足。
现在,让我们看看标准答案是如何系统揭示各向异性现象的本质、成因与应对策略的:
【基本原理】
在理想状态下,模型学习到的词向量(Word Embeddings)应该在向量空间中均匀分布,充分利用整个空间的表达能力,这被称为各向同性(Isotropy)。
然而,研究发现预训练模型(如 BERT、GPT)学到的向量往往呈现出各向异性(Anisotropy)。这意味着向量并不是均匀散布的,而是聚集在一个狭窄的"锥形"(Narrow Cone)区域内。在这种状态下,即便两个单词在语义上完全无关,它们的向量方向也会非常接近。
示意图:
text
Isotropy (各向同性 - 理想) Anisotropy (各向异性 - 实际)
(均匀分布) (狭窄锥体/塌陷)
Y Y
^ ^
* * | * * | //
* * | * * | // <-- 向量高度聚集
----------+-----------> X ----------+-----------> X
* * | * * |/
* * | * * /
【回答模板】
- 定义:各向异性是指模型学到的表征(Representations)在向量空间中占据一个低维凸锥(Narrow Cone)的现象。
- 核心特征 :
- 高余弦相似度:任意两个随机抽取的词向量,其余弦相似度通常都非常高(例如平均值大于 0.9),导致模型难以通过距离区分微小的语义差别。
- 表征塌陷:向量空间存在严重的冗余,大量维度被浪费,模型的有效表达容量远小于其理论维度。
- 产生原因 :
- 词频偏差:受齐夫定律(Zipf's Law)影响,高频词倾向于靠近原点,而低频词被推向边缘,形成拉伸。
- Softmax 偏置:为了最小化训练损失,模型倾向于将所有向量推向同一个方向,以方便通过线性变换预测下一个词。
- 层归一化(LayerNorm):虽然稳定了训练,但也可能限制了特征在空间中的自由分布。
【深入理解】
- 对相似度计算的冲击 :
由于所有向量都挤在一起,使用传统的**余弦相似度(Cosine Similarity)**来衡量语义相关性会变得不再准确。即便是一个完全错误的回答,其语义向量也可能因为"地理位置"接近而获得高分。 - 稀有词(Rare Words)的劣势 :
在各向异性的空间中,稀有词的向量往往偏移得更远。这导致模型在处理低频领域知识时,其检索和推理表现显著下降。 - 缓解策略 :
- 标准化变换 (Whitening):通过白化变换将锥形分布拉回到球形分布。
- 提示词修正 (Prompt Tuning):通过减去空间中的"平均向量"来消除共性偏置。
- 正则化约束:在训练中加入对比学习(Contrastive Learning)损失,强制让不相关的词在空间中拉开距离(如 SimCSE)。
- 现代大模型的现状 :
虽然各向异性在早期 BERT 模型中非常严重,但随着模型规模的增大(如 GPT-4)和非线性激活函数(如 SwiGLU)的使用,这种"表征塌陷"现象在一定程度上得到了缓解,但依然是大模型语义空间理解中的一个核心挑战。
24. Transformer 的时间复杂度随序列长度 LLL 是如何变化的? [校: ★★★★★ | 社: ★★★★]
子问题拆解(引导思考)
24.1 Transformer 中哪些操作依赖于序列长度 LLL?
- Self-Attention :需计算所有 Token 对之间的交互,涉及 QK⊤∈RL×LQK^\top \in \mathbb{R}^{L \times L}QK⊤∈RL×L。
- FFN :对每个 Token 独立做非线性变换,共 LLL 次。
- Embedding / LayerNorm / Residual :均为 O(Ld)O(Ld)O(Ld),可忽略。
24.2 为什么 Self-Attention 是 O(L2d)O(L^2 d)O(L2d)?
- 计算 QK⊤QK^\topQK⊤:[L,d]×[d,L]→[L,L][L, d] \times [d, L] \to [L, L][L,d]×[d,L]→[L,L],乘法次数为 L⋅d⋅L=L2dL \cdot d \cdot L = L^2 dL⋅d⋅L=L2d。
- 加权求和 AVA VAV:[L,L]×[L,d]→[L,d][L, L] \times [L, d] \to [L, d][L,L]×[L,d]→[L,d],同样 L2dL^2 dL2d。
- 总计:O(L2d)O(L^2 d)O(L2d)。
24.3 FFN 为何是 O(Ld2)O(L d^2)O(Ld2)?
- 第一层:xW1x W_1xW1,x∈RL×d,W1∈Rd×4dx \in \mathbb{R}^{L \times d}, W_1 \in \mathbb{R}^{d \times 4d}x∈RL×d,W1∈Rd×4d → O(L⋅d⋅4d)=O(Ld2)O(L \cdot d \cdot 4d) = O(L d^2)O(L⋅d⋅4d)=O(Ld2)。
- 第二层同理。总 FFN 复杂度仍为 O(Ld2)O(L d^2)O(Ld2)。
24.4 何时 Attention 成为瓶颈?
比较 L2dL^2 dL2d 与 Ld2L d^2Ld2:
- 当 L>dL > dL>d 时,L2d>Ld2L^2 d > L d^2L2d>Ld2 → Attention 主导。
- 例如:LLM 中 d=4096d = 4096d=4096,若 L=32768L = 32768L=32768,则 L/d=8L/d = 8L/d=8,Attention 计算量约为 FFN 的 8 倍。
24.5 显存是否也受 L2L^2L2 影响?
是的!Attention Score 矩阵需存储 L×LL \times LL×L 个浮点数。
- L=8192L = 8192L=8192 → 矩阵大小 ≈ 256 MB(FP16);
- L=131072L = 131072L=131072 → 矩阵大小 ≈ 64 GB (FP16),远超单卡显存。
因此,显存瓶颈往往比计算瓶颈更早出现。
现在,让我们看看标准答案是如何清晰拆解 Transformer 复杂度构成,并揭示其在长上下文场景下的核心挑战的:
【基本原理】
Transformer 模型的时间复杂度主要由两个核心部分组成:自注意力机制(Self-Attention)和前馈神经网络(FFN)。
在计算复杂度时,我们通常关注两个关键维度:序列长度 LLL(Token 数量)和模型隐藏层维度 ddd(Embedding Size)。由于 LLL 和 ddd 的增长对计算量的贡献方式不同,Transformer 的表现表现出明显的特征:FFN 随 LLL 线性增长,而 Self-Attention 随 LLL 呈平方增长。
示意图:复杂度瓶颈对比
text
序列长度 L ----> 增加
[ FFN 层 ] : 每一个 Token 独立计算,计算量随 L 均匀增加
Token1: [===]
Token2: [===]
Token3: [===] --> O(L * d²) (线性增长)
[ Attention 层 ] : 每一个 Token 都要看其他所有 Token (全连接矩阵)
T1 T2 T3
T1 [ * * * ]
T2 [ * * * ] --> O(L² * d) (平方增长)
T3 [ * * * ]
(当 L 翻倍时,计算量翻 4 倍!)
【回答模板】
Transformer 的时间复杂度可以拆分为以下两部分:
-
自注意力机制 (Self-Attention):
- 计算过程 :首先计算 QKTQ K^TQKT(形状为 [L,d]×[d,L][L, d] \times [d, L][L,d]×[d,L]),得到注意力分数矩阵(形状为 [L,L][L, L][L,L])。接着,将该得分矩阵与 VVV 相乘。
- 复杂度 :O(L2⋅d)O(L^2 \cdot d)O(L2⋅d)。
- 特征 :随着序列长度 LLL 的增加,计算开销呈二次方(平方)增长。这是长文本处理(Long Context)的主要计算瓶颈。
-
前馈神经网络 (FFN) 与线性投影:
- 计算过程 :对序列中的每个 Token 进行独立的线性变换(通常是 d→4d→dd \to 4d \to dd→4d→d)。
- 复杂度 :O(L⋅d2)O(L \cdot d^2)O(L⋅d2)。
- 特征 :计算开销随 LLL 线性增长,但随维度 ddd 的平方增长。
结论 :在模型维度 ddd 固定的情况下,Transformer 的总时间复杂度随序列长度 LLL 呈现 O(L2)O(L^2)O(L2) 的变化趋势。
【深入理解】
-
LLL 与 ddd 的博弈:
- 在处理短文本 时,通常 d2>L2⋅dd^2 > L^2 \cdot dd2>L2⋅d(例如 BERT 中 d=768,L=512d=768, L=512d=768,L=512),此时计算压力主要集中在 FFN 和投影层。
- 在处理长文本 时(如 LLM 的 32k 或 128k 上下文),L2⋅dL^2 \cdot dL2⋅d 会迅速超过 L⋅d2L \cdot d^2L⋅d2,此时 Attention 矩阵的计算和存储将占据绝大部分算力。
-
显存压力 :
不仅是时间复杂度,Attention 的空间复杂度也是 O(L2)O(L^2)O(L2)(因为要存储那张 L×LL \times LL×L 的得分矩阵)。这也是为什么显存会在长文本输入时迅速"炸裂"。
-
工程上的突破(Flash Attention) :
为了缓解 O(L2)O(L^2)O(L2) 带来的压力,现代大模型使用了 Flash Attention 技术。虽然它在数学上的理论复杂度依然是 O(L2)O(L^2)O(L2),但通过分块计算(Tiling)和减少显存读写次数(IO-Aware),它在实际运行中极大地提高了计算速度,使得处理超长序列成为可能。
-
线性注意力的追求 :
为了打破 O(L2)O(L^2)O(L2) 的魔咒,学术界提出了许多线性注意力(Linear Attention)模型(如 RWKV、Mamba),它们尝试将复杂度降至 O(L)O(L)O(L),但在复杂语义理解任务上的表现目前仍与原生 Transformer 有细微差距。
25. 解释什么是 Cross-attention。 [校: ★★★ | 社: ★★]
子问题拆解(引导思考)
25.1 Self-attention 和 Cross-attention 的根本区别是什么?
- Self-attention :Q,K,VQ, K, VQ,K,V 全部来自同一个序列,用于建模序列内部的依赖关系(如"主语"和"谓语"的关联)。
- Cross-attention :QQQ 来自目标序列 ,K,VK, VK,V 来自源序列 ,用于建立两个不同序列之间的跨域对齐(如"英文词"对齐"中文词")。
25.2 为什么需要 Cross-attention?
在 Encoder-Decoder 架构中,编码器已将源序列压缩为上下文表示,但解码器不知道该关注哪一部分。Cross-attention 让解码器能动态查询编码器输出,实现"按需取用",而非使用固定向量(如 RNN 中的 final hidden state)。
25.3 Cross-attention 的注意力矩阵形状如何?
若目标序列长度为 LtL_tLt,源序列长度为 LsL_sLs,则注意力权重矩阵为 Lt×LsL_t \times L_sLt×Ls。
例如:翻译 "Hello" → "你好"(Lt=2,Ls=1L_t=2, L_s=1Lt=2,Ls=1),则生成每个目标词时都会查看唯一的源词。
25.4 Decoder-only 模型(如 GPT)为何不需要 Cross-attention?
因为所有输入(Prompt + 已生成 Token)被拼接成单一序列 ,通过 Causal Masked Self-attention 即可实现"未来不可见、过去全可见"的信息流动,无需分离源/目标。
25.5 Cross-attention 在多模态中如何工作?
以 CLIP 或 Flamingo 为例:
- 图像 patch 特征 → 作为 K,VK, VK,V;
- 文本 token 表示 → 作为 QQQ;
或反之。Cross-attention 成为跨模态语义对齐的核心机制。
现在,让我们看看标准答案是如何清晰定义 Cross-attention 的结构、功能与应用场景的:
【基本原理】
Cross-attention(交叉注意力)是 Transformer 架构中连接两个不同序列的"桥梁"。在标准的 Self-attention 中,Q,K,VQ, K, VQ,K,V 均来自同一个输入序列;而在 Cross-attention 中,QQQ 来自一个序列(通常是解码器端),而 KKK 和 VVV 则来自另一个序列(通常是编码器端)。
它的核心作用是让一个序列(生成端)根据需求去"查询"并"提取"另一个序列(上下文端)中的相关信息。
示意图:
解码器端 - 目标序列
编码器端 - 源序列
编码器输出特征
W^K
W^V
Key
Value
当前解码器状态
W^Q
Query
相似度计算/Softmax
提取上下文特征
解码器下一层
【回答模板】
- 定义:Cross-attention 是一种用于处理两个不同模态或不同序列之间交互的注意力机制。
- 输入来源 :
- Query (Q):来自目标序列(如正在翻译的句子)。它代表"我现在需要什么样的信息"。
- Key (K):来自源序列(如原始输入的待翻译句子)。它代表"我有这些特征可供检索"。
- Value (V):来自源序列。它代表"我实际包含的内容信息"。
- 数学形式 :
Cross-Attention(Qdec,Kenc,Venc)=softmax(QdecKencTdk)Venc\text{Cross-Attention}(Q_{dec}, K_{enc}, V_{enc}) = \text{softmax}\left(\frac{Q_{dec}K_{enc}^T}{\sqrt{d_k}}\right)V_{enc}Cross-Attention(Qdec,Kenc,Venc)=softmax(dk QdecKencT)Venc - 典型应用 :在 Encoder-Decoder 架构(如 T5, Transformer 原始机器翻译模型)中,解码器通过 Cross-attention 来观察编码器的输出,从而决定翻译时应该关注原文的哪个部分。
【深入理解】
- 不对称性 :
Self-attention 是对称的(输入相同),其注意力矩阵是 L×LL \times LL×L(LLL 为序列长度)。而 Cross-attention 是不对称的,其注意力矩阵形状为 Ltarget×LsourceL_{target} \times L_{source}Ltarget×Lsource。这意味着目标序列的每一个位置都会扫描源序列的所有位置。 - 信息的桥接器 :
在翻译任务"我爱中国 -> I love China"中,当解码器准备生成"China"时,它的 Query 会与编码器输出中"中国"对应的 Key 产生极高的匹配分,从而引导模型从"中国"对应的 Value 中提取语义,实现精准翻译。 - 多模态的基石 :
Cross-attention 不仅用于文本。在 Stable Diffusion (文本生成图像)中,图像的特征作为 QQQ,文本的特征作为 KKK 和 VVV。通过 Cross-attention,文本的信息被注入到图像的生成过程中,实现了"按描述画图"。 - 为什么目前的 Decoder-only 模型没有它?
像 GPT-4、Llama 这样的模型只有解码器,它们处理的是单一序列。所有的上下文信息(包括之前的提示词)都包含在同一个序列中,因此通过带掩码的 Self-attention 就能完成信息的提取,不再需要专门的 Cross-attention。但在处理多模态任务(如看图说话)时,Cross-attention 依然是不可或缺的组件。
26. 什么是 Padding Token?它在 Attention 计算中如何被忽略? [校: ★★★ | 社: ★★]
子问题拆解(引导思考)
26.1 为什么需要 Padding Token?
GPU/TPU 等硬件擅长处理规则张量 (如 B×L×dB \times L \times dB×L×d)。若 batch 中句子长度不同(如 [5, 3, 7]),无法直接堆叠。通过在短句末尾添加 [PAD],统一长度为 max(L),实现高效并行计算。
26.2 Padding Token 会带来什么问题?
- 语义污染 :模型可能学习到"
[PAD]与某些词相关",破坏表征。 - 注意力干扰 :在 Self-Attention 中,真实词可能将部分注意力分配给无意义的
[PAD],降低上下文建模质量。
26.3 如何在 Attention 中屏蔽 [PAD]?
核心是 Padding Mask:
- 构造 mask:对每个序列,标记非
[PAD]位置为True(或 1),[PAD]为False(或 0)。 - 扩展为 L×LL \times LL×L 矩阵(Encoder)或与 Causal Mask 合并(Decoder)。
- 将 mask 为
False的位置在 QK⊤QK^\topQK⊤ 中设为 −∞-\infty−∞。 - Softmax 后,这些位置权重 = 0。
示例:若某行 attention score 原为
[2.1, -0.5, 1.8],对应 mask 为[1, 1, 0],则 masked score 变为[2.1, -0.5, -1e9]→ softmax ≈[0.71, 0.29, 0.0]。
26.4 为何用 −∞-\infty−∞ 而非 0?
Softmax 对所有输入敏感。若设为 0,当其他分数也很小时(如 [-3, -4, 0]),[PAD] 反而获得最高权重(≈0.95)。只有 −∞-\infty−∞ 能绝对抑制其概率。
26.5 损失函数是否也需要处理?
是的!训练时,标签序列也包含 [PAD]。若不忽略,模型会因"预测 [PAD] 错误"而更新参数,浪费梯度。PyTorch 的 CrossEntropyLoss(ignore_index=0) 即为此设计。
现在,让我们看看标准答案是如何系统阐述 Padding Token 的作用、掩码机制与工程实践的:
【基本原理】
在深度学习中,为了实现高效的批量训练(Batch Processing),我们需要将同一个 Batch 里的所有序列对齐成相同的长度。由于自然语言的句子长短不一,我们会在较短的句子末尾填充特殊的占位符,即 Padding Token (通常表示为 [PAD],索引为 0)。
然而,Padding Token 并不包含任何实际语义,它只是为了凑齐张量形状。在计算自注意力时,如果不加处理,模型会把注意力分配给这些无意义的 [PAD],从而干扰真实词汇的表征。
示意图:
text
句子 A: "我 爱 学习" (长度 3)
句子 B: "大 模型" (长度 2)
对齐后的 Batch (最大长度 3):
[ "我", "爱", "学习" ]
[ "大", "模型", "[PAD]" ] <-- [PAD] 是多余的
注意力分数矩阵 (Score Matrix):
大 模型 [PAD]
大 [ 0.5, 0.3, 0.2 ] <-- 0.2 是分配给 [PAD] 的错误权重
模型 [ 0.4, 0.4, 0.2 ]
[PAD] [ 0.3, 0.3, 0.4 ]
【回答模板】
- 什么是 Padding Token :它是用于填充非等长序列的特殊符号。它确保了一个 Batch 内的所有数据具有相同的张量维度(Batch×Seq_Len×Hidden_DimBatch \times Seq\_Len \times Hidden\_DimBatch×Seq_Len×Hidden_Dim),以便在 GPU 上进行大规模矩阵并行运算。
- 如何被忽略(Padding Mask 机制) :
- 生成 Mask 矩阵 :创建一个与注意力得分矩阵 QKTQK^TQKT 大小相同的二进制掩码矩阵。其中,真实 Token 的位置为 1,
[PAD]的位置为 0。 - 数值替换(Masked Fill) :在执行 Softmax 之前,将掩码中为 0 的位置在注意力得分矩阵中替换为一个极大的负数 (通常是 −∞-\infty−∞ 或 −1e9-1e9−1e9)。
- 归一化 :当计算 softmax\text{softmax}softmax 时,e−1e9e^{-1e9}e−1e9 会无限趋近于 0。
- 结果 :所有
[PAD]位置的注意力权重(Attention Weights)都变为了 0,从而在后续对 Value (VVV) 进行加权求和时,完全排除了填充字符的影响。
- 生成 Mask 矩阵 :创建一个与注意力得分矩阵 QKTQK^TQKT 大小相同的二进制掩码矩阵。其中,真实 Token 的位置为 1,
【深入理解】
- 为什么要用 −1e9-1e9−1e9 而不是直接设为 0?
注意力机制的第一步是计算点积得分(Scores),这些得分可以是正数也可以是负数。如果直接将分数设为 0,经过 softmax(0)\text{softmax}(0)softmax(0) 后,它依然会得到一个非零的概率(例如 e0/∑exe^0 / \sum e^xe0/∑ex),导致模型依然会"关注"到这些位置。只有设为负无穷,才能确保其概率权重彻底消失。 - 损失函数中的忽略 :
除了在 Attention 中忽略,我们在计算交叉熵损失(Cross Entropy Loss)时,也需要指定ignore_index=[PAD_ID]。这样,模型在学习时,预测[PAD]位置的错误不会产生梯度,确保模型只学习预测真实有意义的词。 - 双向与单向的影响 :
- 在 Encoder 中,Padding Mask 是双向的,每个词都要屏蔽掉 Batch 里的所有
[PAD]。 - 在 Decoder 中,Padding Mask 通常会与 Causal Mask(因果掩码)合并,形成一个综合掩码,既屏蔽掉未来信息,又屏蔽掉填充信息。
- 在 Encoder 中,Padding Mask 是双向的,每个词都要屏蔽掉 Batch 里的所有
- 性能优化 :
对于极长序列中含有大量 Padding 的情况,现代深度学习库提供了PackedSequence或Flash Attention等技术,可以在底层直接跳过 Padding 部分的计算,从而节省宝贵的算力。
27. 解释 LayerNorm 在推理阶段是否可以被优化(融合)? [校: ★★ | 社: ★★★★]
子问题拆解(引导思考)
27.1 BatchNorm 能"折叠",LayerNorm 为什么不能?
- BatchNorm :推理时使用固定的全局均值 μ\muμ 和方差 σ2\sigma^2σ2,可将归一化操作吸收进前一层的权重和偏置:
y=γx−μσ2+ϵ+β=W′x+b′ y = \gamma \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta = W' x + b' y=γσ2+ϵ x−μ+β=W′x+b′
因此可完全移除 BN 层。 - LayerNorm :均值 μi=1d∑jxij\mu_i = \frac{1}{d}\sum_j x_{ij}μi=d1∑jxij 和方差 σi2\sigma_i^2σi2 依赖于当前样本的特征维度 ,每次输入都不同,无法预计算,故无法数学折叠。
27.2 什么是"算子融合"?它如何提升性能?
现代 GPU 的瓶颈常在显存带宽而非计算能力。若 LayerNorm 单独作为一个算子:
- 线性层输出 → 写回显存;
- LayerNorm 读取 → 计算 → 再写回显存;
- 下一层再读取......
多次读写造成 I/O 浪费 。
通过融合(如Linear + LayerNorm合并为一个 Kernel),数据在寄存器/SRAM 中流转,仅一次读、一次写,显著提速。
27.3 哪些推理引擎支持 LayerNorm 融合?
- TensorRT :自动识别
Add + LayerNorm模式,替换为AddLayerNorm插件。 - ONNX Runtime:通过图优化 pass 合并 LN 与相邻算子。
- vLLM / FlashAttention:在自定义 kernel 中内联 LN 计算,尤其在 Decoder 的 FFN 或 Attention 输出后。
27.4 RMSNorm 为何更易融合?
RMSNorm 省略了减均值步骤,仅计算:
y=xmean(x2)+ϵ⋅γ y = \frac{x}{\sqrt{\text{mean}(x^2) + \epsilon}} \cdot \gamma y=mean(x2)+ϵ x⋅γ
- 减少了同步点(无需先算均值再减);
- 计算流程更线性,更适合 GPU 并行;
- 在 Llama、Mistral 等模型中广泛采用,推理速度比标准 LN 快 10--20%。
27.5 融合是否影响数值精度?
通常不会。融合只是改变计算顺序和存储路径,数学等价。但在极端情况下(如 FP16 下大动态范围),中间结果不写回显存可能减少舍入误差累积,反而提升精度。
现在,让我们看看标准答案是如何厘清 LayerNorm 优化的本质边界与工程实践的:
【基本原理】
在深度学习模型的推理加速中,"融合"(Fusion)通常指将两个或多个算子合并为一个计算核(Kernel),以减少显存读写(I/O)开销。
对于 LayerNorm (LN),我们需要区分两种不同意义的"融合":
- 数学上的折叠(Folding) :像 BatchNorm (BN) 那样将参数直接融入前一层的权重 WWW 中。
- 工程上的算子融合(Operator Fusion):将归一化操作与前后的线性层或激活函数合并在一个 GPU Kernel 中执行。
示意图:算子融合与计算瓶颈
text
未优化的计算流 (存在多次显存读写):
[线性层输出] --写回显存--> [显存] --读取--> [计算均值/方差] --写回--> [显存] --读取--> [归一化/缩放]
融合后的计算流 (一次 I/O):
[线性层输出] --在寄存器中直接计算--> [均值/方差/归一化] --写回显存--> [最终结果]
【回答模板】
- 结论 :LayerNorm 在推理阶段不能像 BatchNorm 那样在数学上被折叠进权重矩阵 ,但可以进行工程上的算子融合。
- 为什么不能数学折叠 :
BatchNorm (BN) 在推理时使用预训练好的全局均值和方差,它们是常数,因此可以预先合并进线性层的 WWW 和 bbb。但 LayerNorm 的均值和方差是动态 的,取决于当前输入序列 的特征。由于 E[x]E[x]E[x] 和 Var[x]Var[x]Var[x] 随输入变化,我们无法在推理前预计算出它们。 - 如何进行工程优化 :
- Kernel Fusion(算子融合):通过编写高性能 CUDA 或 Triton 内核,将 LayerNorm 与其前面的 Add(残差连接)或后面的 Linear 投影合并。这样数据只需从显存读取一次,在 GPU 的片上 SRAM 中完成所有计算。
- 消除冗余统计:在推理时,利用算子库(如 TensorRT, FasterTransformer)优化对均值和方差的重复访问,减少中间变量的存储。
【深入理解】
- 访存受限(Memory Bound)特性 :
LayerNorm 属于典型的"访存密集型"算子。它的计算量极小(仅涉及加减乘除),但需要遍历整个向量来计算均值和方差。这意味着计算时间大部分花在了"从显存读数据"和"往显存写数据"上。通过算子融合,可以显著降低这种 I/O 延迟。 - 推理引擎的自动优化 :
当你使用 TensorRT 或 ONNX Runtime 加载模型时,引擎会自动寻找计算图中的层归一化模式,并将其替换为高效的融合版本。例如,将Residual Add + LayerNorm融合为一个AddLayerNorm插件。 - RMSNorm 的优势 :
现代大模型(如 Llama)偏向使用 RMSNorm,因为它省去了计算均值的步骤,只算均方根。这在工程实现上更容易编写高效的并行融合算子,因为它进一步简化了数据依赖,提高了推理吞吐量。 - 与 BatchNorm 的本质区别 :
BN 是"横向"归一化(跨样本),推理时已经"凝固";LN 是"纵向"归一化(跨特征),推理时依然"鲜活"。这种本质区别决定了 LN 的优化重心在于提升 I/O 效率 而非减少参数计算。
28. 什么是"词表大小"对模型显存的影响? [校: ★★★ | 社: ★★]
子问题拆解(引导思考)
28.1 为什么词表大小直接影响显存占用?
- Embedding 层 :将离散的 Token ID 映射为连续的向量表示,矩阵大小为 [V,d][V, d][V,d]。
- LM Head 层 :在输出端进行分类预测,同样需要一个 [V,d][V, d][V,d] 的矩阵。
这两个层的参数量直接与词表大小 VVV 成正比。对于半精度(FP16/BF16),每个参数占 2 字节,因此显存消耗为 V×d×2V \times d \times 2V×d×2 Bytes。
28.2 词表增大对推理时显存有何影响?
推理时,除了存储权重外,还需要临时存储Logits (每个 Token 的得分)。形状为 [Batch×Seq,V][Batch \times Seq, V][Batch×Seq,V]。当 VVV 增大时,即便 Batch Size 和序列长度固定,Logits 矩阵也会迅速耗尽显存。
28.3 训练时显存开销如何变化?
训练不仅需要存储权重,还需存储梯度 和优化器状态(如 Adam 的 m、v)。通常,训练时显存需求是仅权重时的 8~12 倍。大词表导致:
- 更多参数 → 更大显存;
- 更大的 Logits 矩阵 → 更高显存峰值;
- 更小的最大 Batch Size → 更低训练效率。
28.4 如何缓解大词表带来的显存压力?
- 权重共享 :Embedding 和 LM Head 共享权重(Wout=WinTW_{out} = W_{in}^TWout=WinT),减少一半显存。
- 张量并行:将词表矩阵切分到多个 GPU 上,降低单卡负担。
- 特殊算子:使用高效实现(如 Flash Attention)来处理大词表下的 Logits 计算。
28.5 大词表 vs 小词表,利弊是什么?
- 大词表 :
- 优点:更细粒度的词汇表示,适合多语言、稀有词;减少碎片化,提升上下文理解。
- 缺点:显著增加显存开销;计算可能变为访存受限。
- 小词表 :
- 优点:轻量化,显存占用低。
- 缺点:可能导致词语被拆分成多个片段,损失语义信息。
现在,让我们看看标准答案是如何系统阐述词表大小对显存的具体影响及其应对策略的:
【基本原理】
在 Large Language Model (LLM) 中,词表大小 (VVV) 是指模型能够识别和生成的不同 Token 的总数。词表大小直接决定了模型中两个核心矩阵的体积:输入端的 Embedding 层 和输出端的 LM Head 层。
这两层本质上都是巨大的线性映射矩阵,其形状均为 [V,d][V, d][V,d](ddd 为模型的隐藏层维度)。因此,词表大小与显存占用之间存在直接的线性正比关系。
示意图:词表相关的显存开销
text
[ Embedding 层 ] : 形状 [V, d]
[ LM Head 层 ] : 形状 [V, d] (通常与 Embedding 共享权重或独立存在)
显存占用计算 (以 BF16/FP16 为例, 每个参数 2 字节):
显存 (GB) ≈ (V * d * 2 * 矩阵数量) / 10^9
示例: V=100,000, d=4096 (约 7B 模型配置)
单个矩阵大小 = 100,000 * 4096 * 2 Bytes ≈ 0.8 GB
两层总计 ≈ 1.6 GB (这仅是参数本身,不含梯度和优化器状态)
【回答模板】
词表大小对模型显存的影响主要体现在以下三个方面:
- 静态参数显存(Static Weights) :
词表大小直接决定了 Embedding 矩阵和 Output Projection 矩阵的大小。例如,如果词表从 3.2w(如 Llama 2)扩大到 12.8w(如 Llama 3),且隐藏层维度为 4096,那么仅这部分的参数量就增加了约 3.8×1083.8 \times 10^83.8×108 个,在半精度下会多占用约 0.75 GB 的显存。 - 推理时的 Logits 矩阵(Logits Overheads) :
在推理的最后一步,模型需要计算每个 Token 的得分(Logits)。这会产生一个形状为 [Batch×Seq,V][Batch \times Seq, V][Batch×Seq,V] 的中间张量。当 VVV 非常大时(如 256k),即便 Batch Size 较小,这一步也可能瞬间消耗数 GB 的显存,极易引发 OOM (Out of Memory)。 - 训练时的梯度与优化器状态(Training State) :
在训练阶段,每个参数不仅占用显存,还需要存储对应的梯度(Gradient)和优化器状态(如 Adam 的两个动量矩)。通常,训练时的显存需求是参数本身的 8~12 倍。一个巨大的词表会显著压缩训练时的最大 Batch Size。
【深入理解】
- 权重的权衡(The Trade-off) :
- 大词表 :每个 Token 包含的信息量大,序列长度变短,计算注意力时的 L2L^2L2 开销减小,且模型更擅长处理多语言和稀有词。
- 小词表:模型更轻量,显存占用低,但一个词可能被拆分成过多的碎片,导致上下文窗口被快速填满。
- 权重共享策略(Weight Tying) :
为了节省显存,许多模型(如早期 GPT 和部分 T5 变体)会将 Embedding 层和输出层的权重矩阵绑定(共享) 。这意味着 Wout=WinTW_{out} = W_{in}^TWout=WinT,从而将词表相关的显存占用直接砍掉一半。 - 计算密度的影响 :
虽然词表层参数多,但它们的计算是高度离散的(输入是 Embedding Lookup,输出是全连接)。在大词表场景下,输出层的计算往往会变成**访存受限(Memory-bound)**的,这要求工程上使用特殊的算子(如分块 Cross-Entropy)来优化。 - 现代趋势 :
随着多语言和多模态的需求,大词表已成为趋势。Llama 3 将词表扩大到 128k,Qwen 甚至更高。为了支撑这种规模,开发者必须通过张量并行(Tensor Parallelism)将词表矩阵切分到多张显卡上,以缓解单卡显存压力。
29. 什么是权重初始化在大模型中的挑战? [校: ★★★ | 社: ★★★]
子问题拆解(引导思考)
29.1 什么是权重初始化?为什么它在神经网络训练开始前就很重要?
- 权重初始化是指在训练开始前,给神经网络的所有参数(如权重矩阵)赋予初始数值。
- 如果初始值太大,信号在前向传播中会爆炸(数值溢出);如果太小,信号会消失(梯度接近零),导致模型无法学习。
29.2 大模型(如 LLM)相比普通神经网络,在层数上有何特点?这对初始化提出了什么新挑战?
- 大模型通常有几十层甚至上百层(如 Llama 有 80+ 层 Transformer)。
- 每一层都会对信号进行变换,微小的初始化偏差会在多层堆叠后被指数级放大或缩小,使训练一开始就崩溃。
29.3 在 Transformer 架构中,残差连接(Residual Connection)如何影响初始化的设计?
- 残差连接会将每一层的输出加到输入上(xout=xin+F(xin)x_{out} = x_{in} + F(x_{in})xout=xin+F(xin))。
- 如果子层 F(⋅)F(\cdot)F(⋅) 的输出方差过大,经过多层累加后,总激活值会爆炸;过小则主干信号主导,子层学不到东西。
- 因此,初始化必须控制 F(⋅)F(\cdot)F(⋅) 的初始输出方差,使其与恒等路径匹配。
29.4 为什么说"方差控制"是大模型初始化的核心?
- 理想情况下,希望每一层的输出方差与输入方差大致相等(称为"信号保稳")。
- 数学上,若每层输出方差为 σ2\sigma^2σ2,N 层后总方差约为 N⋅σ2N \cdot \sigma^2N⋅σ2(因残差累加)。
- 所以需要让 σ2∝1/N\sigma^2 \propto 1/Nσ2∝1/N,即初始化标准差应随层数增加而减小。
29.5 半精度训练(FP16/BF16)对初始化提出了哪些额外限制?
- FP16 最大可表示数约 65504,若初始化过大,前向计算可能直接溢出为 Inf 或 NaN。
- 因此,即使理论上合理的初始化,在低精度下也可能失效,需进一步缩放或裁剪。
29.6 有哪些专门针对大模型的初始化策略?它们如何解决上述问题?
- 按深度缩放初始化 :如 GPT 系列将 Attention 输出投影层(WOW_OWO)和 FFN 第二层的权重初始化标准差设为 1/2N1/\sqrt{2N}1/2N ,其中 NNN 是层数。
- 零初始化(Zero Init) :将残差分支的最后一层(如 WOW_OWO)初始化为全零,使初始时 F(x)≈0F(x) \approx 0F(x)≈0,模型行为接近恒等映射,极大提升深层稳定性。
- 适配 Pre-norm 结构:在 LayerNorm 在子层前的架构中,初始化可稍宽松,但仍需保证各层激活量级一致。
现在,我们将完整、一字不差地呈现您最初提供的全部原始内容作为本题的标准答案总结:
【基本原理】
权重初始化(Weight Initialization)是指在训练开始前为神经网络的参数赋予初始数值的过程。其核心目标是确保在模型的前向传播过程中信号不会消失或爆炸,并在反向传播时梯度能维持在合理的范围内。
在大模型(LLM)中,由于网络层数极深(通常超过 80 层甚至上百层),初始化微小的偏差都会随着层数的堆叠被指数级放大或缩小,导致训练在起步阶段就崩溃。
示意图:信号在深层网络中的传播
初始化不当后果
初始化过大: 信号方差爆炸 -> 数值溢出 NaN
初始化过小: 信号方差消失 -> 梯度为 0
输入信号 X
Layer 1
Layer 2
...
Layer 100
【回答模板】
权重初始化在大模型中的挑战主要体现在以下三个方面:
- 方差爆炸与消失(Variance Accumulation) :
在 Transformer 架构中,残差连接(Residual Connection)会将每一层的输出累加。如果每一层的输出方差都略大于 1,经过 100 层的累加,深层的激活值将变得极大,导致数值溢出(NaN)。反之,如果初始化过小,深层网络将收不到任何有效的信号。 - 残差分支与主干的平衡 :
初始化必须平衡"残差分支(Attention/FFN)"与"恒等映射主干(Shortcut)"之间的权重。如果残差分支在初始阶段贡献过大,会破坏主干路径上的信息流动,使得深层梯度变得极其不稳定。 - 对优化器稳定性的影响 :
大模型通常使用 AdamW 优化器。不合理的初始化会导致损失函数在初始阶段产生巨大的梯度波动,使优化器的动量(Momentum)累积错误的方向,从而引发训练不收敛。
【深入理解】
为了应对这些挑战,大模型通常采用以下改进策略:
- 按深度缩放(Scaled Initialization) :
这是 GPT 系列采用的策略。在初始化残差层的权重时,将其标准差除以层数的平方根(即 σ∝1/2N\sigma \propto 1/\sqrt{2N}σ∝1/2N ,其中 NNN 是层数)。这样可以确保随着层数增加,残差路径的总方差增长处于可控范围,维持输出方差的平稳。 - 针对 Pre-norm 的专门设计 :
在 Pre-norm 架构中,输入信号在进入子层前先经过 LayerNorm。这虽然缓解了爆炸问题,但初始化依然需要确保激活值的量级在各层之间保持一致。 - Zero Initialization(零初始化)的局部应用 :
在某些高级策略中,会将残差分支的最后一层线性层(如 WOW_OWO 或 FFN 的第二层)初始化为 0。这样在训练初期,模型表现得就像是一个简单的恒等映射(Identity Mapping),随着训练进行,模型再逐渐学习如何利用残差分支,极大地增强了深层模型的训练稳定性。 - 与精度(FP16/BF16)的适配 :
大模型使用半精度训练。如果初始化导致数值范围超过 FP16 的表示范围(65504),会直接触发 NaN。因此,初始化必须保证数值处于低精度的"安全区"。
30. 为什么 Transformer 弃用 RNN 的循环结构? [校: ★★★★★ | 社: ★★★]
为了帮助初学者循序渐进地理解这个问题,我们将原始问题拆解为若干引导性子问题。每个子问题都聚焦一个关键概念,逐步构建对整体答案的理解。请注意:您提供的全部原始内容将在最后完整保留,一字不删。
子问题拆解(引导思考)
30.1 RNN 是如何处理序列数据的?它的核心计算方式是什么?
- RNN 采用循环结构 ,在时间步 ttt 计算隐藏状态 ht=f(ht−1,xt)h_t = f(h_{t-1}, x_t)ht=f(ht−1,xt)。
- 这意味着必须先完成 t−1t-1t−1 步的计算,才能开始第 ttt 步------形成时间上的串行依赖。
30.2 为什么 RNN 的串行依赖会限制训练效率?
- 现代 GPU/TPU 擅长大规模并行计算(如同时处理成千上万个矩阵运算)。
- 但 RNN 无法在同一时间步内并行处理整个序列,因为每一步都依赖前一步的结果。
- 这导致硬件利用率低,训练超长序列或大规模语料时速度极慢。
30.3 RNN 在处理长序列时会遇到什么信息传递问题?
- 假设序列长度为 LLL,第一个词的信息要传到第 LLL 个词,需经过 L−1L-1L−1 次非线性变换。
- 在反向传播中,梯度也要沿这条路径回传,极易发生梯度消失 (gradient vanishing)或爆炸(exploding)。
- 结果:模型难以捕捉相距较远的词之间的语义关系(即"长距离依赖"问题)。
30.4 Transformer 如何实现"任意两个位置直接交互"?
- Transformer 使用自注意力机制(Self-Attention):对输入序列中的所有 Token 同时计算注意力权重。
- 对于任意两个位置 iii 和 jjj,它们的交互通过注意力分数直接建立,路径长度恒为 1 (即 O(1)O(1)O(1) 距离)。
- 这使得模型能"一眼看到"整个上下文,无需逐步传递信息。
30.5 并行计算在 Transformer 中是如何实现的?
- 所有 Token 的表示被一次性打包成矩阵(如 X∈RL×dX \in \mathbb{R}^{L \times d}X∈RL×d)。
- 自注意力通过矩阵乘法(QKTQK^TQKT)一次性计算所有位置对的相似度,完全可并行。
- 因此,Transformer 的训练速度远超 RNN,尤其适合大规模分布式训练。
30.6 放弃 RNN 的循环结构后,Transformer 如何保留"顺序信息"?
- RNN 天然具有顺序性(从左到右处理),而 Transformer 是"无序"的全连接结构。
- 为弥补这一点,Transformer 引入了位置编码(Positional Encoding),将位置信息以向量形式加到 Token Embedding 上。
- 这样,模型既能并行计算,又能感知词序。
30.7 Transformer 的这种改变带来了哪些更深远的影响?
- 它标志着 NLP 从"时序建模"转向"空间表征建模"------不再假设语言必须按时间顺序理解。
- 这一转变使得大规模预训练成为可能:模型可以在海量文本上高效训练,学习通用语言表示。
- 最终催生了 BERT、GPT、Llama 等大模型时代。
现在,我们完整、逐字呈现您最初提供的全部原始内容作为本题的标准总结答案:
【基本原理】
循环神经网络(RNN)的核心逻辑是顺序处理 :为了计算第 ttt 时刻的状态 hth_tht,必须先完成 t−1t-1t−1 时刻的计算。这种时间上的串行依赖导致了两个根本性问题:一是无法利用现代 GPU 的大规模并行计算能力;二是信息的传递路径过长,导致深层语义在长序列中容易丢失。
Transformer 通过弃用循环结构,改用自注意力机制(Self-Attention) ,实现了序列信息的"一步到位":任何两个位置之间的信息交互距离都是常数 O(1)O(1)O(1),且所有 Token 的计算可以同时开始。
示意图:计算模式对比
Transformer: 全局并行
X1, X2, X3, X4...
Attention
O1, O2, O3, O4...
所有 Token 同时进入 Attention 矩阵并行计算
RNN: 串行依赖
X1
H1
H2
X2
H3
X3
必须等 H1 完才能算 H2
【回答模板】
Transformer 弃用 RNN 的循环结构主要基于以下三个深层次原因:
- 并行计算效率(Parallelization) :
RNN 的计算复杂度在时间轴上是 O(L)O(L)O(L) 的,即必须经过 LLL 步串行操作。这限制了其在超大规模语料上的训练效率。Transformer 的自注意力层允许所有位置并行计算,极大提升了模型在现代硬件(GPU/TPU)上的计算利用率,使训练超千亿参数的模型成为可能。 - 解决长距离依赖(Long-range Dependencies) :
在 RNN 中,第一位的信息要传递到第 nnn 位,需要经过 n−1n-1n−1 次非线性变换,梯度在漫长的路径中极易消失或爆炸。而在 Transformer 中,任意两个 Token 之间的交互路径长度始终为 1。这种"全局视野"使得模型能够更精准地捕捉到跨度极大的语义关联。 - 计算路径的稳定性(Gradient Flow) :
RNN 依赖于隐藏状态(Hidden State)的不断更新来存储记忆,这是一种"有损压缩"。Transformer 通过自注意力矩阵直接建立 Token 间的显式联系,并配合残差连接(Residual Connection),确保了即使在极深的网络中,底层信号和梯度也能无损地向上传递。
【深入理解】
- 从"归纳偏置"到"纯粹注意力" :
RNN 包含一个强烈的归纳偏置(Inductive Bias):认为距离越近的词关系越紧密,且处理顺序必须是从左往右。Transformer 放弃了这种偏置,认为序列中任何两个词的关系应由数据动态决定。为了弥补丢失的顺序信息,Transformer 引入了位置编码(Positional Encoding)。 - 计算复杂度的折中 :
虽然 Transformer 解决了并行化问题,但它付出的代价是自注意力机制的平方复杂度 O(L2)O(L^2)O(L2)(RNN 是线性 O(L)O(L)O(L))。然而,在现代工业界,**"计算的可并行性"通常比"理论上的低复杂度"**更重要,因为并行化能换取更短的训练时间和更庞大的参数容量。 - 历史意义 :
弃用 RNN 是自然语言处理(NLP)从"时序建模"转向"空间表征建模"的分水岭。这一转变直接导致了大规模预训练(Pre-training)范式的崛起,因为只有摆脱了循环结构的束缚,模型才能在万亿级的互联网文本中高效地汲取知识。
31. 什么是 Tying Embedding(权重共享)? [校: ★★★ | 社: ★★]
为了帮助初学者循序渐进地理解这一概念,我们将原始问题拆解为若干引导性子问题。每个子问题聚焦一个关键点,逐步构建对"Tying Embedding"机制的完整认知。请放心:您提供的全部原始内容将在最后完整、逐字保留,绝不删减。
子问题拆解(引导思考)
31.1 在语言模型中,输入和输出分别需要哪些矩阵?它们的形状是什么?
- 输入端 :将词表 ID(整数)映射为向量表示,使用 Embedding 矩阵 E∈RV×dE \in \mathbb{R}^{V \times d}E∈RV×d,其中 VVV 是词表大小,ddd 是隐藏维度。
- 输出端 :将最终隐藏状态映射回词表得分(Logits),使用 输出投影矩阵 W∈Rd×VW \in \mathbb{R}^{d \times V}W∈Rd×V。
- 若不共享,这两个矩阵是独立的,总参数量为 2×V×d2 \times V \times d2×V×d。
31.2 什么是"权重共享"(Tying Embedding)?它具体如何操作?
- Tying Embedding 指令:强制让输出投影矩阵等于输入 Embedding 矩阵的转置 ,即 W=E⊤W = E^\topW=E⊤。
- 这意味着输入和输出共用同一份参数,只是方向相反(一个查表,一个做线性分类)。
31.3 为什么可以认为输入和输出矩阵"本质相同"?
- 一个词无论作为上下文 (输入)还是作为预测目标(输出),其语义应保持一致。
- 例如,"apple"在输入中代表水果,在输出中也应被识别为同一概念。这种语义对称性支持参数共享的合理性。
31.4 权重共享能带来哪些直接好处?
- 显存节省 :词表相关参数减少近 50%,对大词表模型(如 V=128kV=128kV=128k)意义重大。
- 训练效率提升:每个词的嵌入向量在输入和输出阶段都会被梯度更新,尤其有利于稀有词的学习。
- 语义一致性增强:避免输入空间和输出空间出现语义漂移。
31.5 对于稀有词,权重共享为何特别重要?
- 稀有词在训练数据中出现频率低。
- 若输入/输出矩阵独立,则该词可能只在输入或输出中被更新一次;而共享后,每次出现(无论角色)都能更新同一向量,显著提升学习效率。
31.6 所有模型都使用 Tying Embedding 吗?有没有例外?
- 主流生成式模型(如 GPT、PaLM、Llama 系列)普遍采用。
- 部分判别式模型(如早期 BERT)或追求极致表达能力的变体可能选择不共享,以保留更多自由度。
- 是否共享,取决于开发者在参数效率 与模型容量之间的权衡。
31.7 从工程角度看,权重共享对大模型部署有何影响?
- 显存占用降低 → 可在单卡上部署更大词表模型;
- 参数总量减少 → 加快加载速度、降低通信开销(在分布式训练中);
- 尤其在 FP16/BF16 下,节省的几百 MB 到几 GB 显存可能决定是否能跑起来。
现在,我们完整、逐字、一字不差地呈现您最初提供的全部原始内容作为本题的标准总结答案:
【基本原理】
Tying Embedding(权重共享,也称为 Weight Tying)是指在语言模型中,让输入层的 Embedding 矩阵和**输出层的线性投影矩阵(Softmax 前的那一层)**共享同一个权重矩阵的参数。
在一个隐藏层维度为 ddd、词表大小为 VVV 的模型中,输入层需要一个 [V,d][V, d][V,d] 的矩阵来将 ID 映射为向量,输出层同样需要一个 [d,V][d, V][d,V] 的矩阵来将隐藏状态映射回词表得分。Tying Embedding 认为这两个矩阵本质上是在处理同一套语义符号,因此可以将它们设为同一个矩阵的转置。
示意图:权重共享的流程
输入 Token ID
共享权重矩阵 E: V x d
隐藏层表示 H
...
最终隐藏状态
共享权重矩阵 E 的转置: d x V
预测词得分
两个粉色矩阵是同一份参数
【回答模板】
- 定义 :Tying Embedding 是一种参数复用技术。它要求模型的输入词嵌入矩阵 EinE_{in}Ein 和输出层的线性变换矩阵 WoutW_{out}Wout 满足 Wout=EinTW_{out} = E_{in}^TWout=EinT。
- 核心作用 :
- 参数减半:词表相关的参数通常占模型总参数量的很大比例。通过共享,可以将这部分显存开销直接砍掉近 50%。
- 语义对齐:强制模型将"输入语义空间"与"输出语义空间"统一。如果两个词在输入端语义接近,那么模型在预测输出时,它们也会获得相似的概率。
- 提升泛化能力:由于每个词的权重在输入和输出端都会受到梯度的双重约束,模型能更高效地学习到稀有词(Rare Words)的表示。
【深入理解】
- 数学合理性 :
语言模型的任务本质上是计算 P(wnext∣wcontext)P(w_{next} | w_{context})P(wnext∣wcontext)。输入 Embedding 是在建模"上下文词的特征",输出投影是在建模"目标词的特征"。在同一个语言体系内,一个词作为上下文出现时的语义与其作为预测目标出现时的语义应当是高度一致的。权重共享正是利用了这种语义对称性。 - 对稀有词的拯救 :
稀有词在语料中出现的次数极少。如果输入和输出矩阵独立,每个词只有一半的机会获得梯度更新。通过 Tying Embedding,无论是该词作为输入还是作为预测目标,都会更新同一份参数,极大地提高了数据的利用率。 - 显存优化视角 :
对于词表极大的模型(如 Llama 3 的 128k 词表),Embedding 矩阵非常庞大。在隐藏层维度为 4096 时,一个词表矩阵就有 5 亿多参数。如果不进行 Tying,仅词表部分就要占据约 2GB 显存(FP16)。在单机多卡训练中,这种显存节省是非常宝贵的。 - 并不是所有模型都 Tying :
虽然权重共享在 GPT、PaLM 等模型中被广泛使用,但有些模型(如某些版本的 BERT 或特定优化后的 LLM)为了追求更强的表达灵活性,选择不进行共享。这取决于开发者在"参数量"与"模型容量"之间的权衡。不过,在生成式长文本模型中,Tying Embedding 依然是极其主流且高效的方案。
32. 解释计算图在反向传播时如何处理 Dropout 层。 [校: ★★★ | 社: ★★]
为了帮助初学者循序渐进地理解 Dropout 在反向传播中的行为,我们将原始问题拆解为若干引导性子问题。每个子问题聚焦一个核心机制,逐步构建对计算图中 Dropout 处理逻辑的完整认知。严格遵守您的约定:您提供的全部原始内容将在最后完整、逐字保留,绝不删减、改写或省略。
子问题拆解(引导思考)
32.1 Dropout 在训练时做了什么操作?它为什么能防止过拟合?
- Dropout 在训练过程中以概率 ppp 随机将某些神经元的输出置为 0。
- 这相当于在每次前向传播时"临时删除"一部分网络连接,迫使模型不依赖于特定神经元,从而提升泛化能力。
32.2 为什么 Dropout 需要"缩放"(scaling)?什么是 Inverted Dropout?
- 如果直接丢弃神经元而不调整,训练时的期望输出会比测试时小(因为测试时所有神经元都激活)。
- Inverted Dropout 的做法是:在训练时,将保留下来的神经元值除以 (1−p)(1-p)(1−p),使得期望值与测试阶段一致。
- 公式:Y=11−p(X⊙M)Y = \frac{1}{1-p} (X \odot M)Y=1−p1(X⊙M),其中 MMM 是随机二进制掩码。
32.3 在计算图中,Dropout 被建模为什么样的操作?
- 它被建模为一个**逐元素相乘(element-wise multiplication)**节点,输入是原始张量 XXX 和随机掩码 MMM,并附带缩放因子。
- 这个操作是可微的(尽管掩码是离散的),因此可以纳入自动微分系统。
32.4 反向传播时,梯度是如何流经 Dropout 层的?
- 根据链式法则,梯度从输出 ∂L∂Y\frac{\partial \mathcal{L}}{\partial Y}∂Y∂L 回传到输入 ∂L∂X\frac{\partial \mathcal{L}}{\partial X}∂X∂L。
- 由于前向是 Y=11−p(X⊙M)Y = \frac{1}{1-p}(X \odot M)Y=1−p1(X⊙M),对 XXX 求导得:∂Y∂X=M1−p\frac{\partial Y}{\partial X} = \frac{M}{1-p}∂X∂Y=1−pM。
- 所以反向梯度为:∂L∂X=∂L∂Y⊙M1−p\frac{\partial \mathcal{L}}{\partial X} = \frac{\partial \mathcal{L}}{\partial Y} \odot \frac{M}{1-p}∂X∂L=∂Y∂L⊙1−pM。
32.5 为什么反向传播必须使用前向传播时生成的同一个掩码?
- 如果反向时重新生成掩码,会导致:
- 前向被丢弃的位置(输出为 0)在反向却可能收到梯度;
- 前向保留的位置反而可能被错误地切断梯度。
- 这会破坏梯度更新的正确性,导致训练失败。
- 因此,计算图必须缓存(cache)前向的掩码 MMM,并在反向时复用。
32.6 Dropout 在推理(eval)阶段的行为有何不同?
- 推理时关闭 Dropout,所有神经元都参与计算。
- 由于训练时已通过 Inverted Dropout 缩放,推理时无需再调整数值------直接输出 XXX 即可。
- 此时 Dropout 层等价于恒等函数(Identity)。
32.7 Dropout 对显存和计算有什么实际影响?
- 虽然计算简单(主要是位掩码和乘法),但需要额外存储与输入同形状的掩码 MMM。
- 在大 Batch 或高维特征图下,这可能占用数百 MB 显存,成为限制因素之一。
现在,我们完整、逐字、一字不差地呈现您最初提供的全部原始内容作为本题的标准总结答案:
【基本原理】
Dropout 是一种在训练过程中通过随机"丢弃"(置零)部分神经元来防止过拟合的正则化技术。在计算图中,Dropout 被视为一个逐元素相乘的操作。
为了保证前向传播和反向传播的数学一致性,Dropout 层在执行时会生成一个与输入张量形状完全相同的二进制掩码(Binary Mask)。这个掩码在训练的每一步都是随机生成的,并在反向传播时被复用。
示意图:Dropout 的前向与后向流
渲染错误: Mermaid 渲染失败: Parse error on line 16: ...ask -.-> Mask_Cache [存储在缓存中] -----------------------^ Expecting 'SEMI', 'NEWLINE', 'SPACE', 'EOF', 'AMP', 'COLON', 'START_LINK', 'LINK', 'LINK_ID', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'SQS'
【回答模板】
在计算图中,Dropout 的处理逻辑分为以下两个阶段:
-
前向传播(Forward Pass):
- 生成掩码 :模型根据概率 ppp 随机生成一个布尔矩阵 MMM(000 表示丢弃,111 表示保留)。
- 缩放(Inverted Dropout) :为了保证输出的期望值与测试阶段一致,保留下来的元素会除以 (1−p)(1-p)(1−p)。公式为:Y=11−p(X⊙M)Y = \frac{1}{1-p} (X \odot M)Y=1−p1(X⊙M)。
- 缓存 :计算图会将这个掩码 MMM 存储在内存(Cache)中,供反向传播调用。
-
反向传播(Backward Pass):
- 梯度流向 :根据链式法则,损失函数对输入的导数为:
∂L∂X=∂L∂Y⊙M1−p\frac{\partial \mathcal{L}}{\partial X} = \frac{\partial \mathcal{L}}{\partial Y} \odot \frac{M}{1-p}∂X∂L=∂Y∂L⊙1−pM - 逻辑解释 :在反向传播时,Dropout 层直接复用前向传播时保存的掩码 。
- 如果前向传播时某个神经元被置为 0,则该位置在反向传播时的梯度也直接为 0(通路断开)。
- 如果某个神经元被保留,则其梯度按原样回传,并同样乘以缩放因子 1/(1−p)1/(1-p)1/(1−p)。
- 梯度流向 :根据链式法则,损失函数对输入的导数为:
【深入理解】
- 掩码的一致性(Consistency) :
这是 Dropout 处理中最关键的一点。反向传播绝不能重新生成随机掩码,否则会导致梯度更新到了"错误"的神经元上。计算图必须通过缓存机制确保"哪里丢弃,哪里没梯度"。 - Inverted Dropout(反向丢弃)的优势 :
现代框架(PyTorch, TensorFlow)采用的是 Inverted Dropout。这意味着在训练时直接进行缩放(除以 1−p1-p1−p),这样在推理(Inference)阶段,模型可以直接关闭 Dropout 层而不需要进行任何额外的数值调整,保持了推理逻辑的简洁性。 - 计算开销与显存 :
虽然 Dropout 的计算很简单(只是位运算和乘法),但由于需要存储掩码 MMM,它会消耗额外的显存。在处理超大规模模型时,这有时会成为限制 Batch Size 的因素之一。 - 推理阶段的行为 :
在model.eval()模式下,Dropout 层在计算图中变成了恒等映射(Identity Mapping),即输出等于输入,不再生成掩码,也不进行缩放。此时,所有的神经元都参与计算,共同贡献特征。