1. Transformer为何使用多头注意力机制?为什么不用一个头?
✅ 答案:
多头注意力(Multi-Head Attention)允许模型在不同子空间中并行学习多种类型的表示,提升表达能力。
🔍 详细解释:
- 单个注意力头只能捕捉一种“关系模式”(如主谓宾、因果、指代等)。
- 多头注意力通过多个线性投影(WQ,WK,WVW^Q, W^K, W^VWQ,WK,WV)将输入映射到不同的子空间,在每个子空间独立计算注意力权重。
- 最后拼接结果再做一次线性变换,融合所有视角。
💡 类比:
就像一个人用多个“眼睛”同时观察同一场景:一个看颜色,一个看形状,一个看运动——整体理解更丰富。
📌 数学表达:
MultiHead(Q,K,V)=Concat(head1,…,headh)WOwhere headi=Attention(QWiQ,KWiK,VWiV) \text{MultiHead}(Q,K,V) = \text{Concat}(head_1,\dots,head_h)W^O \\ \text{where } head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) MultiHead(Q,K,V)=Concat(head1,…,headh)WOwhere headi=Attention(QWiQ,KWiK,VWiV)
✅ 结论:单头无法建模复杂依赖 → 多头增强模型的表达能力。
2. Transformer为什么Q和K使用不同的权重矩阵生成?为何不能使用同一个值进行自身的点乘?(注意和第一个问题的区别)
✅ 答案:
Q 和 K 使用不同矩阵是为了让查询(Query)和键(Key)在语义上分离,从而支持更灵活的匹配方式。
🔍 详细分析:
- 如果 $ Q = K $,那么注意力得分就是 $ \frac{Q_i \cdot Q_j}{\sqrt{d_k}} $,相当于自相关(self-correlation),只关注“相似度”。
- 实际上,我们希望:
- 查询(Q)代表当前词的“意图”或“上下文需求”
- 键(K)代表其他词的“特征”或“可被查询的内容”
✅ 举个例子:
- 句子:“他喜欢苹果。”
- 当前词“苹果”想问:“谁喜欢我?” → Q 是“苹果”的查询向量
- 其他词“他”提供“我是谁”的信息 → K 是“他”的键向量
❌ 若 Q=K:
- “苹果”会去问自己:“我像不像我?” —— 无意义,缺乏语义交互。
✅ 所以:
- 不同的 $ W^Q $ 和 $ W^K $ 能够解耦“提问”和“回答”的语义角色。
- 这种设计使得模型可以更好地建模跨句依赖、指代消解等任务。
3. Transformer计算attention的时候为何选择点乘而不是加法?两者计算复杂度和效果上有什么区别?
✅ 答案:
点乘(dot-product attention)具有更好的数值稳定性、更高的计算效率和更强的语义对齐能力。
🔍 对比分析:
维度 | 点乘注意力(Dot-Product) | 加法注意力(Additive Attention) |
---|---|---|
公式 | $ \text{score} = Q \cdot K^\top $ | $ \text{score} = \text{MLP}(Q + K) $ |
计算复杂度 | $ O(d) $ | $ O(d^2) $(因MLP含非线性层) |
可扩展性 | 更适合长序列(高效) | 随维度增长慢,但不适合高维 |
效果 | 在实践中表现更好 | 理论上更灵活,但训练不稳定 |
💡 关键点:
- 点乘本质是 余弦相似度(归一化后),衡量两个向量方向是否一致。
- 加法注意力虽能引入非线性,但需额外参数(MLP),且训练难度更高。
✅ 因此:点乘更简单、更快、更稳定 → 成为标准选择。
4. 为什么在进行softmax之前需要对attention进行scaled? (为什么除以dk的平方根),并使用公式推导进行讲解
✅ 答案:
为了防止梯度消失/爆炸,保持数值稳定性。
🔍 推导过程:
设 $ Q, K $ 是 $ d_k $ 维向量,假设它们服从标准正态分布(均值0,方差1),则:
E[Qi⋅Kj]=∑k=1dkQikKjk∼N(0,dk) \mathbb{E}[Q_i \cdot K_j] = \sum_{k=1}^{d_k} Q_{ik} K_{jk} \sim \mathcal{N}(0, d_k) E[Qi⋅Kj]=k=1∑dkQikKjk∼N(0,dk)
即:点积期望为0,方差为 $ d_k $
当 $ d_k $ 很大时(如512),点积值可能达到几十甚至上百,导致:
- softmax 输出接近 [0, …, 1, …, 0](尖峰分布)
- 梯度几乎为0 → 梯度消失
- 训练不稳定
✅ 解决方案:缩放因子 $ \frac{1}{\sqrt{d_k}} $
Scaled Score=Q⋅K⊤dk \text{Scaled Score} = \frac{Q \cdot K^\top}{\sqrt{d_k}} Scaled Score=dkQ⋅K⊤
→ 方差变为 $ \frac{d_k}{d_k} = 1 $,避免指数爆炸。
📌 通俗理解:
就像考试成绩标准化:原始分太高(98 vs 99)差异很小,但经过Z-score后更容易比较。
5. 在计算attention score的时候如何对padding做mask操作?
✅ 答案:
使用 mask 矩阵屏蔽 padding 位置,使其在 softmax 中不参与计算。
🔍 实现方式:
# 假设 input_ids: [batch_size, seq_len]
# padding_mask: 1 表示有效,0 表示填充
mask = (input_ids != pad_token_id).unsqueeze(1).unsqueeze(2)
# 注意力得分矩阵:[batch, heads, q_len, k_len]
scores = scores.masked_fill(mask == 0, float('-inf'))
# 再做 softmax
attention_weights = F.softmax(scores / sqrt(d_k), dim=-1)
🎯 效果:
- Padding 位置的 attention weight ≈ 0
- 不影响有效 token 的注意力分配
✅ 必须在 softmax 前 mask,否则会因 -inf 导致 NaN
6. 为什么在进行多头注意力的时候需要对每个head进行降维?
✅ 答案:
这是为了控制总输出维度,保证后续层输入大小一致。
🔍 说明:
- 每个 head 输出维度为 $ d_v $
- 若有 $ h $ 个 head,则总输出为 $ h \times d_v $
- 通常设置 $ h \times d_v = d_{model} $(如 8×64 = 512)
✅ 例如:d_model=512, h=8 → 每个 head 输出 64 维
✅ 目的:
- 保持模型结构对称
- 控制参数量(避免爆炸)
- 提升训练稳定性
7. 讲一下Transformer的Encoder模块
✅ 结构图解:
Input → Embedding → Positional Encoding →
↓
[Multi-Head Attention] → Add & Norm →
↓
[Feed-Forward Network] → Add & Norm → Output
🔍 核心组件:
- 嵌入层(Embedding):将 token ID 映射为向量
- 位置编码(Positional Encoding):注入顺序信息
- 多头自注意力(Self-Attention):捕捉全局依赖
- 前馈网络(FFN):非线性变换
- 残差连接 + LayerNorm:加速收敛,缓解梯度消失
✅ Encoder 是纯自注意力结构,没有外部输入。
8. 为何在获取输入词向量之后需要对矩阵乘以embedding size的开方?
✅ 答案:
防止初始嵌入向量过大,导致激活函数饱和或梯度爆炸。
🔍 原理:
- 嵌入矩阵 $ E \in \mathbb{R}^{vocab \times d_{emb}} $
- 初始随机初始化时,若 $ d_{emb} $ 很大,向量范数可能很大
- 后续通过
Linear
层放大,可能导致激活值过大
✅ 解决方法:
在 embedding 后乘以 $ \frac{1}{\sqrt{d_{emb}}} $,使输出均值为0,方差为1。
✅ 实践中常写成:
embedding = embedding * math.sqrt(d_model)
9. 简单介绍一下Transformer的位置编码
✅ 两种类型:
正弦/余弦编码(Sinusoidal PE):
- 使用固定频率的波形,无需训练
- 支持任意长度序列
- 公式:
PE(pos,2i)=sin(pos100002i/dmodel)PE(pos,2i+1)=cos(pos100002i/dmodel) PE_{(pos,2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) \\ PE_{(pos,2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i)=sin(100002i/dmodelpos)PE(pos,2i+1)=cos(100002i/dmodelpos)
可学习位置编码(Learnable PE):
- 添加可训练的嵌入向量
- 性能略好,但不支持超长序列
✅ 优点:
- 保留相对位置信息
- 可扩展性强(Sinusoidal)
10. 了解哪些关于位置编码的技术?
✅ 主流技术:
技术名称 | 特点 |
---|---|
Sinusoidal PE | 固定、可泛化、支持任意长度 |
Learnable PE | 可训练、性能略优 |
Relative Positional Encoding | 显式建模相对距离(如 T5, Longformer) |
Rotary Positional Embedding (RoPE) | 旋转嵌入,适用于长文本(Llama 2+) |
ALiBi | 使用斜率衰减模拟位置偏移 |
✅ RoPE 已成为 LLM 的主流选择(如 Llama、ChatGPT)
11. 简单讲一下Transformer中的残差结构以及意义
✅ 定义:
残差连接(Residual Connection):将输入直接加到输出上:
Output=LayerNorm(x+Sublayer(x)) \text{Output} = \text{LayerNorm}(x + \text{Sublayer}(x)) Output=LayerNorm(x+Sublayer(x))
✅ 意义:
- 缓解梯度消失:即使 sublayer 输出小,输入仍可通过 skip connection 传递
- 加速收敛:网络可以学习“增量变化”
- 提高稳定性:防止深度网络退化
✅ 类比:高速公路 → 输入可以直接“绕过”某些层
12. 为什么Transformer块使用LayerNorm而不是BatchNorm?
✅ 答案:
因为 BatchNorm 依赖 batch 内统计量,而 Transformer 通常 batch size 小、序列长度变化大。
🔍 对比:
特性 | LayerNorm | BatchNorm |
---|---|---|
归一化维度 | 每个样本单独归一化(per sequence) | 每个 batch 统计(mean/std) |
对 batch size 敏感 | 否 | 是(batch太小 → 不稳定) |
支持变长序列 | ✅ | ❌(需固定长度) |
推理阶段行为 | 一致(无统计量更新) | 需用训练时统计量(移动平均) |
✅ 所以:LayerNorm 更适合 NLP 任务!
13. 讲一下BatchNorm技术及其优缺点
✅ 作用:
- 对 batch 内数据进行归一化(均值0,方差1)
- 减少内部协变量偏移(Internal Covariate Shift)
✅ 优点:
- 加速训练
- 提高泛化能力
❌ 缺点:
- 依赖 batch size(小 batch 不稳定)
- 不适用于变长序列(如 RNN)
- 推理时需保存移动平均统计量
14. 简单描述一下Transformer中的前馈神经网络?使用了什么激活函数?相关优缺点?
✅ 结构:
FFN(x) = max(0, xW_1 + b_1)W_2 + b_2
- 两层全连接 + ReLU 激活
- 通常中间维度是 $ d_{model} \times 4 $
✅ 激活函数:ReLU
✅ 优点:
- 非线性表达能力强
- 计算简单
❌ 缺点:
- 死区问题(负值被置零)
- 可能导致梯度消失
✅ 替代方案:GELU(在 BERT、GPT 中广泛使用)
15. Encoder端和Decoder端是如何进行交互的?
✅ 交互机制:
- Encoder → Decoder:通过 Cross-Attention 实现
- Decoder 的 Query 来自自身(当前词),Key 和 Value 来自 Encoder 输出
🔍 流程:
- Encoder 输出:$ H_E = \text{Encoder}(X) $
- Decoder 输入:$ Y $(目标序列)
- Cross-Attention:
- $ Q = \text{Decoder_output}, K = H_E, V = H_E $
- 实现“从源语言到目标语言”的翻译逻辑
✅ 仅允许 Decoder 查看已生成的部分(因果掩码)
16. Transformer的并行化提现哪个地方?Decoder端可以做并行化吗?
✅ Encoder 并行化:
- 自注意力完全并行 → 所有 token 同时处理
- 无需等待前序 token
❌ Decoder 并行化限制:
- 因为 因果掩码(Causal Mask),每个 token 只能看到前面的 token
- 所以只能逐个生成(Autoregressive)
✅ 但在训练时,可以并行处理整个目标序列(带 mask)
✅ 推理时必须串行生成(除非用 Beam Search 或 PagedAttention)
17. 描述一下wordpiece model和 byte pair encoding?Dropout是如何设定的,位置在哪里?Dropout在测试的时候需要注意什么?
✅ WordPiece Model(Google/BERT):
- 将词汇拆分为子词单元
- 优先保留常见组合(如 “un”, “happy”)
- 适合处理罕见词
✅ Byte Pair Encoding (BPE)(OpenAI/GPT):
- 从字节对开始,迭代合并最频繁的字符对
- 如:“th” → “the” → “they”
- 支持任意字符集,通用性强
✅ Dropout 设置:
- 位置:LayerNorm 后、FFN 中间、Attention 后
- 通常设置为 0.1 ~ 0.3
- 训练时开启,推理时关闭
⚠️ 测试时必须关闭 dropout!否则预测不稳定
18. Transformer训练的时候学习率是如何设定的?
✅ 学习率策略:
Warmup + Cosine Decay
- 初始阶段逐步增加学习率(warmup)
- 达到峰值后按余弦衰减
- 公式:
ηt=ηmax⋅min(tTwarmup,cos(π(t−Twarmup)Ttotal−Twarmup)) \eta_t = \eta_{max} \cdot \min\left(\frac{t}{T_{warmup}}, \cos\left(\frac{\pi(t-T_{warmup})}{T_{total}-T_{warmup}}\right)\right) ηt=ηmax⋅min(Twarmupt,cos(Ttotal−Twarmupπ(t−Twarmup)))
常用配置:
- Warmup steps:100~1000
- Max LR:1e-4 ~ 5e-4
- Total steps:10000~100000
✅ 为什么?避免早期梯度爆炸,后期精细调整
19. Dropout是如何设定的?
见第17题,补充:
- 一般在 FFN 和 Attention 输出后添加
- 值:0.1(BERT)、0.3(GPT-3)
- 动态调整:有时在训练后期逐渐减少
20. Bert的mask为何不学习transformer在attention处进行屏蔽score的技巧?
✅ 问题澄清:
BERT 的 mask 是“输入级”的,不是 attention 级的。
🔍 区别:
类型 | BERT | Transformer(如 GPT) |
---|---|---|
Mask 位置 | 输入层(token 被替换为 [MASK]) | Attention 层(score 设为 -inf) |
目标 | 预测被遮蔽的词 | 防止未来信息泄露(因果性) |
✅ 为什么 BERT 不用 attention mask?
- 因为 BERT 是 双向模型,不需要因果约束
- 它的目标是 masked language modeling(MLM)
- 所以它直接在输入中用
[MASK]
替换 token,然后让模型预测
✅ 本质不同:BERT 是“输入遮蔽”,Transformer 是“注意力遮蔽”
✅ 总结:Transformer 核心知识点地图
模块 | 关键概念 |
---|---|
Attention | 多头、点乘、缩放、mask、softmax |
Positional Encoding | Sinusoidal、RoPE、Learnable |
Normalization | LayerNorm > BatchNorm |
Residual | 加速训练、防止梯度消失 |
FFN | ReLU/GELU、两层全连接 |
Encoder-Decoder | Self-Attention + Cross-Attention |
Training | Warmup + Cosine Decay、Dropout、AdamW |
Tokenization | WordPiece、BPE、Subword |