# 几何深度学习 (Geometric Deep Learning)

## 实验作业 4（必做）：RSI 应用场景思考

**发布日期**：2026 年 9 月 28 日

**截止日期**：2026 年 9 月 28 日 23:59（CST）

## 作业要求

请撰写短文，谈谈你理解的 RSI 可能应用场景，全文 **150 字以内**。

请独立思考，不要直接照搬他人观点。

## 提交要求

请通过[作业提交系统](https://ly633.github.io/text-submission/)提交短文。系统有两项校验：

1. **字数校验**：字数超限无法提交。
2. **语义比对**：系统会用 AI 做语义比对。如果你的内容和之前已提交作业语义高度相似，系统会驳回，请重新思考修改后再提交。

## 实验作业 4（选做）：Transformer 与机器翻译

**发布日期**：2026 年 9 月 28 日

**截止日期**：2026 年 9 月 28 日 23:59（CST）

---

## 一、作业背景

在前三次作业中，我们从 MLP 到 CNN，逐步理解了深度学习如何利用数据的**结构性先验**——MLP 不假设任何结构，CNN 利用图像的局部性和平移等变性。本次作业我们将进入另一个核心架构：**Transformer**。

Transformer 由 Vaswani 等人在 2017 年论文 *"Attention Is All You Need"* 中提出，其核心思想是用 **Self-Attention（自注意力）** 替代 CNN 的局部卷积，让每个位置能直接关注序列中的所有其他位置。回顾作业三 Q7 中的讨论：CNN 需要多层堆叠才能让感受野覆盖全局，而 Self-Attention 仅需一层就能实现全局信息交互——代价是 $O(n^2)$ 的计算复杂度。

机器翻译是 Transformer 最经典的应用场景之一。本次作业以**英中翻译**为实验任务，使用 Hugging Face 生态工具微调一个预训练的 Encoder-Decoder Transformer 模型，体验从数据加载、模型微调到 BLEU 评估的完整流程。

> **为什么选择微调而非从头训练？** 从头训练一个翻译模型需要数百万句对和数十 GPU 天的算力。微调（Fine-tuning）在预训练模型的基础上，用少量数据和算力即可让模型适应特定任务——这与作业三的迁移学习思想一脉相承。

---

## 二、环境准备

### 安装依赖

```bash
pip install torch transformers[torch] datasets evaluate sacrebleu sentencepiece matplotlib
```

> **注意**：`sentencepiece` 是 MarianMT 模型分词器的必要依赖，缺少它会导致 tokenizer 加载失败。

### 模型与数据下载

代码首次运行时会自动从 Hugging Face Hub 下载模型和数据集。如果网络受限，可设置镜像：

```bash
export HF_ENDPOINT=https://hf-mirror.com
```

---

## 三、作业内容

### 任务一：微调翻译模型（`finetune_translation.py`）

编写 Python 脚本，使用 Hugging Face 的 `Seq2SeqTrainer` 微调预训练翻译模型，并评估翻译质量。

#### 方案选择

本次作业提供**两种翻译方案**，默认使用英中翻译，备选英德翻译：

| 项目 | 英中翻译（默认） | 英德翻译（备选） |
|------|-----------------|-----------------|
| 模型 | `Helsinki-NLP/opus-mt-en-zh` | `Helsinki-NLP/opus-mt-en-de` |
| 数据集 | `wmt19`（config: `zh-en`） | `wmt14`（config: `de-en`） |
| 训练样本 | 子采样 50,000 对 | 子采样 50,000 对 |
| 语言前缀 | 需添加 `>>cmn<<` | 不需要 |
| BLEU 评估 | `tokenize="zh"` | 默认 tokenize |

> **推荐使用英中方案**：你可以直接阅读翻译结果，直观判断模型的翻译质量。如因网络原因无法下载 WMT19 数据集（约 2.5GB），可切换到英德方案。

#### 具体步骤

1. **加载预训练模型与分词器**：从 Hugging Face Hub 加载 MarianMT 模型和对应的 tokenizer。

2. **加载并子采样数据集**：从 WMT19 中加载英中平行语料，随机采样 50,000 对句子，按 9:1 划分训练集和验证集。

3. **数据预处理**：
   - **英中方案**：在英文源句前添加语言前缀 `>>cmn<<`（这是多目标模型的必要标记，指示模型生成简体中文）
   - 使用 tokenizer 对源文本和目标文本分别编码
   - 设置 `max_length=128`，超长句截断

4. **定义评估函数**：使用 `sacrebleu` 计算 BLEU 分数（中文需设置 `tokenize="zh"` 以正确处理中文分词）。

5. **配置训练参数**：使用 `Seq2SeqTrainingArguments` 配置训练超参数。

6. **微调模型**：使用 `Seq2SeqTrainer` 进行训练。

7. **评估与展示**：打印微调前后的 BLEU 分数对比，并展示 5 条翻译样例（原文 / 参考译文 / 模型输出）。

8. **交互式翻译**：训练完成后，脚本自动进入交互模式——输入任意英文句子，模型实时返回翻译结果。请自行尝试 3–5 句不同风格的句子（日常对话、新闻标题、技术术语等），观察模型的翻译能力和局限性。

#### 参考超参数

| 参数 | 建议值 | 说明 |
|------|--------|------|
| `per_device_train_batch_size` | 16 | 单 GPU batch 大小 |
| `per_device_eval_batch_size` | 16 | 评估 batch 大小 |
| `learning_rate` | 2e-5 | 微调常用学习率 |
| `num_train_epochs` | 3 | 训练轮数 |
| `max_source_length` | 128 | 源文本最大 token 数 |
| `max_target_length` | 128 | 目标文本最大 token 数 |
| `eval_strategy` | `"epoch"` | 每个 epoch 结束时评估 |
| `predict_with_generate` | `True` | 评估时使用自回归生成 |

#### 显存说明

MarianMT 约 148M 参数，上述配置在 **6GB 显存**（如 RTX 2060）上可正常运行，训练峰值约 3.5GB。若显存不足，可尝试以下降级配置：

```python
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
fp16=True,  # 混合精度训练，显存减半
```

#### 代码框架（供参考）

```python
from transformers import MarianMTModel, MarianTokenizer
from transformers import Seq2SeqTrainer, Seq2SeqTrainingArguments
from transformers import DataCollatorForSeq2Seq
from datasets import load_dataset
import evaluate
import numpy as np

# ======================== 配置 ========================

MODEL_NAME = "Helsinki-NLP/opus-mt-en-zh"
LANG_PREFIX = ">>cmn<< "   # 英中模型需要语言前缀；英德模型设为 ""
MAX_LENGTH = 128
NUM_SAMPLES = 50000

# ======================== 加载模型与分词器 ========================

tokenizer = MarianTokenizer.from_pretrained(MODEL_NAME)
model = MarianMTModel.from_pretrained(MODEL_NAME)

# ======================== 加载并子采样数据 ========================

raw_dataset = load_dataset("wmt19", "zh-en")
# TODO: 从训练集中随机采样 NUM_SAMPLES 条，再按 9:1 划分 train/val

# ======================== 数据预处理 ========================

def preprocess_function(examples):
    inputs = [LANG_PREFIX + ex["en"] for ex in examples["translation"]]
    targets = [ex["zh"] for ex in examples["translation"]]
    # TODO: 使用 tokenizer 编码 inputs 和 targets
    # Hint: tokenizer(inputs, max_length=MAX_LENGTH, truncation=True, padding="max_length")
    # Hint: 使用 tokenizer(text_target=targets, ...) 编码目标文本
    ...

tokenized_dataset = dataset.map(preprocess_function, batched=True)

# ======================== 评估函数 ========================

metric = evaluate.load("sacrebleu")

def compute_metrics(eval_pred):
    predictions, labels = eval_pred
    # TODO: 将 prediction token IDs 解码为文本
    # TODO: 将 label token IDs 解码为文本（注意替换 -100 为 pad_token_id）
    # TODO: 计算 BLEU 分数
    # Hint (英中): metric.compute(predictions=..., references=..., tokenize="zh")
    ...

# ======================== 训练配置 ========================

training_args = Seq2SeqTrainingArguments(
    output_dir="./translation_output",
    # TODO: 填写训练超参数（参考上方超参数表格）
    predict_with_generate=True,
)

trainer = Seq2SeqTrainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_dataset["train"],
    eval_dataset=tokenized_dataset["val"],
    tokenizer=tokenizer,
    data_collator=DataCollatorForSeq2Seq(tokenizer, model=model),
    compute_metrics=compute_metrics,
)

# ======================== 训练与评估 ========================

# TODO: 微调前先评估基线 BLEU
# TODO: trainer.train()
# TODO: 微调后评估 BLEU
# TODO: 打印 5 条翻译样例对比
```

---

### 任务二（可选）：注意力可视化

选择一条翻译样例，提取模型的 **Cross-Attention** 权重（Encoder 输出与 Decoder 之间的注意力），绘制源语言与目标语言之间的注意力热力图。

**Hint**：使用 `model.generate(..., output_attentions=True, return_dict_in_generate=True)` 获取注意力权重：

```python
outputs = model.generate(
    input_ids,
    output_attentions=True,
    return_dict_in_generate=True,
    max_length=MAX_LENGTH,
)
# outputs.cross_attentions 是一个嵌套元组：
# cross_attentions[生成步][层][batch, head, 1, src_len]
```

---

## 四、具体要求

| 项目 | 要求 |
|------|------|
| 编程语言 | Python 3.8+ |
| 框架 | PyTorch + Hugging Face（transformers, datasets, evaluate） |
| 模型 | `Helsinki-NLP/opus-mt-en-zh`（默认）或 `opus-mt-en-de`（备选） |
| 数据集 | WMT19 zh-en 子采样 50,000 对（或 WMT14 de-en） |
| 评估指标 | BLEU 分数（sacrebleu） |
| GPU 支持 | 代码自动检测 CUDA，兼容纯 CPU 运行 |
| 代码规范 | 结构清晰，关键步骤有注释 |

---

## 五、运行方式

```bash
# 完整流程：训练 + 评估 + 交互翻译
python finetune_translation.py

# 跳过训练，直接加载已保存的微调模型进入交互翻译
python finetune_translation.py --interact
```

> **提示**：首次运行需下载模型（~300MB）和数据集（WMT19 zh-en ~2.5GB）。训练 3 个 epoch 在 RTX 2060 上约需 30–45 分钟；纯 CPU 运行约需 4–6 小时，建议先将 `NUM_SAMPLES` 调小至 5,000 验证流程。
>
> **`--interact` 模式**：训练完成后，模型会保存到 `./translation_output/best_model/`。之后可以随时使用 `--interact` 加载已有模型，直接体验翻译，无需重新训练。

---

## 六、检查方法

1. **训练流程**：脚本能正常运行至完成，控制台打印每 epoch 的 loss 和 BLEU 分数。
2. **BLEU 提升**：微调后的 BLEU 分数应高于微调前的基线。
3. **翻译样例**：打印的 5 条翻译对比中，微调后的翻译应比微调前更流畅、更准确。
4. **交互翻译**：使用 `--interact` 模式输入自选英文句子，记录 3–5 条翻译结果，简要评价翻译质量（是否通顺、有无遗漏、有无明显错误）。
5. **日志输出**：保存训练日志截图或终端输出，包含 BLEU 分数和交互翻译的截图。

---

## 七、思考问题（可选）

### Q1 | Self-Attention 的计算

考虑一个长度为 3 的序列，每个 token 的嵌入维度 $d=4$。输入矩阵为：

$$X = \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 1 & 0 & 0 \end{bmatrix} \in \mathbb{R}^{3 \times 4}$$

Query、Key、Value 的投影矩阵分别为（简化为 $d_k = d_v = 2$）：

$$W_Q = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 0 \\ 0 & 1 \end{bmatrix}, \quad W_K = \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ 0 & 1 \\ 1 & 0 \end{bmatrix}, \quad W_V = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 0 & 1 \\ 1 & 0 \end{bmatrix}$$

(a) 计算 $Q = XW_Q$，$K = XW_K$，$V = XW_V$。

(b) 计算注意力分数 $\frac{QK^T}{\sqrt{d_k}}$，然后对每行做 Softmax，得到注意力权重矩阵 $A$。

(c) 计算最终输出 $\text{Attention}(Q,K,V) = A \cdot V$。

(d) 观察注意力权重矩阵 $A$：哪些 token 对之间的注意力最强？这与它们的 Query-Key 内积有什么关系？

(e) **数值稳定性**：在本题中，缩放后的注意力分数最大值为 2.83，$e^{2.83} \approx 17$，计算没有问题。但在实际模型中（$d_k = 512$），$QK^T$ 的元素量级可能达到数百。直接计算 $e^{z_i}$ 会遇到什么数值问题？如何修改 Softmax 的计算方式来避免？修改后的结果与原始公式是否数学等价？

> **Hint**：Softmax 的公式为 $\text{softmax}(z_i) = \frac{e^{z_i}}{\sum_j e^{z_j}}$。$\sqrt{d_k}$ 的缩放是为了防止内积过大导致 Softmax 梯度消失——想象 $d_k=512$ 时，内积的量级与 $d_k$ 成正比，Softmax 输入过大会趋近 one-hot。对于 (e)，$e^{500}$ 在 FP32（最大约 $e^{88}$）和 FP16（最大约 $e^{11}$）下都会溢出为 `inf`。提示：对每行先减去该行的最大值 $m_i = \max_j z_j$，再计算指数，最大的指数变成了多少？这个技巧在 Q12 的 FlashAttention 中还会再次出现。

---

### Q2 | 位置编码：为什么 Transformer 需要它？

Self-Attention 的核心计算 $\text{Softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$ 对输入序列的**排列**是等变的。形式化地：

$$\text{Attention}(\Pi X) = \Pi \cdot \text{Attention}(X)$$

其中 $\Pi$ 是任意排列矩阵。

(a) 证明上述等变性：如果将输入 $X$ 的行重新排列为 $\Pi X$，证明输出也会做相同的行排列。

(b) 这个等变性意味着，如果不加位置编码，"I love you" 和 "you love I" 经过 Self-Attention 后得到的输出（在对应位置上）是**相同的**。解释为什么这对翻译任务是致命的。

(c) 原始 Transformer 使用正弦位置编码 $\text{PE}_{(pos, 2i)} = \sin(pos / 10000^{2i/d})$。为什么不直接用整数位置 $[0, 1, 2, \ldots]$？正弦编码有什么优势？

> **Hint**：对于 (a)，注意 $Q = \Pi X W_Q$, $K = \Pi X W_K$，代入注意力公式展开即可。对于 (c)，考虑三个维度：数值范围是否有界、能否编码相对位置、能否推广到训练时未见过的长度。

---

### Q3 | 从绝对到相对：旋转位置编码（RoPE）

Q2 中讨论的正弦编码和可学习嵌入都是**绝对位置编码**——将位置向量直接加到 token 嵌入上。2023 年后的大语言模型（LLaMA、Qwen、Mistral 等）几乎统一采用了一种不同的方案：**旋转位置编码（RoPE, Rotary Position Embedding）**。

RoPE 不修改输入嵌入，而是在 Attention 计算中，对 $Q$ 和 $K$ 向量施加位置相关的旋转。具体地，将 $d_k$ 维向量拆成 $d_k/2$ 组维度对，每组视为一个 2D 平面，对位置 $m$ 的 token 施加旋转角 $m \cdot \theta_i$：

$$\begin{pmatrix} \tilde{q}_{2i} \\ \tilde{q}_{2i+1} \end{pmatrix} = \begin{pmatrix} \cos(m\theta_i) & -\sin(m\theta_i) \\ \sin(m\theta_i) & \cos(m\theta_i) \end{pmatrix} \begin{pmatrix} q_{2i} \\ q_{2i+1} \end{pmatrix}, \quad \theta_i = 10000^{-2i/d}$$

(a) 利用旋转矩阵的性质 $R(\alpha)^T = R(-\alpha)$ 和 $R(\alpha)R(\beta) = R(\alpha+\beta)$，证明旋转后 $Q_m$ 和 $K_n$ 的内积只依赖**相对位置** $n - m$：

$$\tilde{Q}_m^T \tilde{K}_n = Q_m^T \, R(n-m) \, K_n$$

(b) 不同维度对使用不同频率 $\theta_i$：高频（$\theta$ 大）的维度对每移动一个位置就旋转很大角度，低频（$\theta$ 小）的维度对几乎不动。从"两个向量在各 2D 平面上的对齐程度"的角度，解释为什么**近距离的 token 对注意力分数更高，远距离的更低**。

(c) Q2 中的可学习绝对位置嵌入（`nn.Embedding(max_seq_len, d_model)`）有一个硬伤：如果训练时 `max_seq_len=512`，推理时遇到位置 513 就没有对应的嵌入向量了。RoPE 为什么天然支持**长度外推**——即在短序列上训练后，能泛化到更长的序列？

> **Hint**：对于 (a)，将 $\tilde{Q}_m = R(m)Q_m$ 和 $\tilde{K}_n = R(n)K_n$ 代入内积公式，利用 $(AB)^T = B^T A^T$ 展开。对于 (b)，想象每组维度对是一个以不同速度转动的时钟指针——近距离的两个 token，各指针的角度差都很小，向量在所有平面上都"对齐"；远距离时，高频指针已经转过多圈，对齐被破坏。对于 (c)，RoPE 的旋转角 $m\theta_i$ 对任意正整数 $m$ 都有定义——它不查表，只做数学计算。

---

### Q4 | 多头注意力

多头注意力将嵌入空间分成 $h$ 个子空间，每个头独立计算注意力后拼接：

$$\text{MultiHead}(Q,K,V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W_O$$

(a) 如果嵌入维度 $d=512$，头数 $h=8$，每个头的 $d_k = d_v = d/h = 64$。单头注意力与 8 头注意力的**总参数量**分别是多少？（只计算 $W_Q, W_K, W_V, W_O$）

(b) 为什么要用多头而非单头？类比 CNN 中的多通道卷积核：每个卷积核检测一种局部模式（边缘、纹理）。Attention 中的每个头可能在关注什么不同的模式？

(c) 如果某个头学到的注意力权重几乎是均匀分布（即对所有位置赋予相同权重），这个头在做什么操作？它等价于哪种池化？

> **Hint**：对于 (a)，单头的 $W_Q, W_K, W_V$ 各为 $512 \times 512$，$W_O$ 不需要（或为恒等映射）；多头的每个头 $W_Q^i$ 为 $512 \times 64$，共 8 个，加上 $W_O$ 为 $512 \times 512$。

---

### Q5 | Encoder-Decoder 中的三种 Attention

本次作业微调的 MarianMT 采用标准 Encoder-Decoder Transformer 架构，其中包含三种注意力机制：

| 注意力类型 | 所在位置 | Q 来自 | K, V 来自 | Mask |
|-----------|---------|--------|----------|------|
| Encoder Self-Attention | Encoder | ？ | ？ | ？ |
| Decoder Masked Self-Attention | Decoder | ？ | ？ | ？ |
| Cross-Attention | Decoder | ？ | ？ | ？ |

(a) 填写上表中的 "？"。

(b) Decoder 的 Masked Self-Attention 为什么需要 **causal mask**（下三角 mask）？如果去掉这个 mask，自回归生成过程会出什么问题？

(c) Cross-Attention 是翻译模型的"对齐"核心。在翻译 "The cat sat on the mat" → "猫坐在垫子上" 时，当 Decoder 生成 "猫" 这个 token 时，Cross-Attention 应该主要关注源句中的哪个词？

> **Hint**：对于 (b)，自回归生成时，位置 $t$ 的 token 只能依赖位置 $1, \ldots, t$ 的已有输出。如果训练时没有 mask，模型会"偷看"未来的 token，训练和推理产生不一致（train-test mismatch）。

---

### Q6 | 三种 Transformer 架构：Encoder、Decoder 与它们的组合

Q5 讨论了 Encoder-Decoder 架构内部的 mask。实际上，Transformer 衍生出了三种主流架构，它们对 Encoder 和 Decoder 的**取舍和组合方式**不同，导致适用场景也不同。

(a) BERT 在训练时将输入中随机 15% 的 token 替换为 `[MASK]`，然后让模型预测被遮住的词。它的 Attention 矩阵是**全 1 的**（每个位置都能看到所有其他位置）。而本次作业 Decoder 使用的 causal mask 是下三角矩阵（每个位置只能看到左侧）。分别写出这两种方式的训练目标：

- BERT：$P(x_{\text{mask}} \mid \text{？})$
- GPT / Decoder：$P(x_t \mid \text{？})$

两者对"上下文"的使用有什么本质区别？

(b) 填写下表，对比三种主流 Transformer 架构：

| 架构 | 组成 | Attention 方向 | 训练方式 | 代表模型 | 擅长任务 |
|------|------|---------------|---------|---------|---------|
| Encoder-only | ？ | ？ | ？ | BERT | ？ |
| Decoder-only | ？ | ？ | ？ | GPT, LLaMA | ？ |
| Encoder-Decoder | ？ | ？ | ？ | MarianMT, T5 | ？ |

(c) 2023 年后，几乎所有大语言模型（LLaMA、GPT-4、Qwen、Mistral 等）都采用了 **Decoder-only** 架构，而非 Encoder-Decoder。Decoder-only 架构没有 Encoder，也没有 Cross-Attention，只有带 causal mask 的 Self-Attention。它是怎么做翻译的？（提示：将翻译任务重新表述为文本续写任务）

> **Hint**：对于 (a)，BERT 看到的是被遮住的词的**左右两侧上下文**，GPT 看到的只是**左侧上下文**。双向上下文信息更丰富，但无法直接用于生成——因为生成时右侧还不存在。对于 (c)，Decoder-only 可以将翻译表述为："Translate English to Chinese: The cat sat on the mat. → "，然后让模型续写。这种方式的灵活性和局限性分别是什么？

---

### Q7 | FFN 的多重身份：分类器还是特征变换器？

全连接层（FFN / MLP）出现在我们每一次作业中，但它扮演的角色截然不同：

| | 作业二 MLP | 作业三 CNN 分类头 | 本次作业 Transformer FFN |
|---|---|---|---|
| 结构 | 784→512→256→10 | 256→128→2 | 512→2048→512 |
| 位置 | 整个网络 | 网络末端 | 每层的中间 |
| 输出维度 | 类别数（10） | 类别数（2） | 与输入相同（512） |

(a) 对比上表中三种 FFN 的**输入维度与输出维度的关系**。作业二和作业三中 FFN 的输出维度等于类别数，它在做什么？Transformer 的 FFN 输出维度等于输入维度（512→2048→512），它在做什么？两者的核心区别是什么？

(b) Transformer 的 FFN 使用了"先升维再降维"的结构（512→2048→512），中间维度是输入的 4 倍。为什么不直接用 512→512 的单层线性变换？中间的 2048 维和 ReLU 各自扮演什么角色？

(c) 如果 Transformer 的 FFN 是"每个 token 独立处理，不看其他 token"，那 token 之间的信息交互完全由谁负责？一个 Encoder Layer 中 Self-Attention 和 FFN 的分工可以类比为什么？

(d) Transformer 中真正起"分类"作用的层是哪一个？它的输入维度和输出维度分别是多少？这个低维到高维的映射（$512 \to 65001$）在几何上意味着什么？（提示：输出权重矩阵的每一行对应词表中的一个词）

> **Hint**：对于 (b)，想象 512 维是一个"拥挤的房间"，2048 维是一个"宽敞的工作台"——先展开到大空间，ReLU 在其中做特征选择（激活或关闭），再压缩回来。对于 (c)，类比"小组讨论"：Self-Attention 是组员之间交流观点，FFN 是每个人回到座位上独立消化吸收。对于 (d)，`output_projection = Linear(512, 65001)` 的权重矩阵有 65001 行，每行是一个 512 维向量——512 维空间中能放下 65001 个互相可区分的方向吗？

---

### Q8 | 从 BatchNorm 到 LayerNorm 再到 RMSNorm

作业三中 CNN 的每个 ConvBlock 使用了 `BatchNorm2d`，而本次作业 Transformer 的每个 Encoder/Decoder Layer 使用了 `LayerNorm`。

(a) 给定一层的输出张量，BatchNorm 和 LayerNorm 分别沿哪些维度计算均值 $\mu$ 和方差 $\sigma^2$？填写下表：

| | CNN 输出 `(B, C, H, W)` | Transformer 输出 `(B, T, D)` |
|---|---|---|
| **BatchNorm** | 对 ？ 维度算 $\mu, \sigma$ | — |
| **LayerNorm** | — | 对 ？ 维度算 $\mu, \sigma$ |

(b) Transformer 为什么不能用 BatchNorm？请从以下三个角度各给出一句话解释：
   - 变长序列与 padding
   - 自回归生成时的 batch size
   - Decoder 的因果性（causal mask）

(c) CNN 能否改用 LayerNorm？如果对 CNN 特征图 `(B, C, H, W)` 的 `(C, H, W)` 三个维度一起做 LayerNorm，隐含了什么假设？这个假设对 CNN 来说合理吗？（提示：CNN 中不同 channel 各自检测什么？它们的激活值分布相同吗？）

(d) 现代大语言模型（LLaMA、Qwen 等）进一步用 **RMSNorm** 替代了 LayerNorm。RMSNorm 的公式为：

$$\text{RMSNorm}(\mathbf{x}) = \gamma \odot \frac{\mathbf{x}}{\sqrt{\frac{1}{d}\sum_{j=1}^{d} x_j^2 + \epsilon}}$$

与 LayerNorm 相比，它省略了什么操作？为什么省略后效果几乎不变？

> **Hint**：对于 (b)，想象推理时 Decoder 逐 token 生成，此时 batch 中只有 1 个 token——BatchNorm 需要跨 batch 算统计量，1 个样本的均值就是它自己。对于 (c)，CNN 的 channel 0 可能是"边缘检测器"，channel 1 可能是"颜色检测器"，它们的输出值域可能相差 10 倍——混在一起归一化合理吗？对于 (d)，LayerNorm = 减均值 + 除标准差，RMSNorm = 只除均方根。实验表明归一化的主要作用来自**缩放**（控制向量长度），减均值（平移）的贡献很小。

---

### Q9 | Pre-Norm vs Post-Norm：LayerNorm 该放在哪？

Q8 讨论了**用什么归一化**（BatchNorm → LayerNorm → RMSNorm）。本题讨论另一个正交的设计维度：**归一化放在哪个位置**。

原始 Transformer（Vaswani et al. 2017）采用 **Post-Norm**——先做残差加法，再做 LayerNorm：

$$x_{l+1} = \text{LayerNorm}\!\big(x_l + \text{Sublayer}(x_l)\big) \qquad \textbf{(Post-Norm)}$$

后来 GPT-2 等模型改用 **Pre-Norm**——先做 LayerNorm，再进子层，残差路径保持"干净"：

$$x_{l+1} = x_l + \text{Sublayer}\!\big(\text{LayerNorm}(x_l)\big) \qquad \textbf{(Pre-Norm)}$$

(a) 画出 Post-Norm 和 Pre-Norm 各一层的**数据流图**（包含 $x_l$、Sublayer、LayerNorm、残差加法、$x_{l+1}$），标注 LayerNorm 的位置。两种方案中，**梯度从 $x_{l+1}$ 回传到 $x_l$ 时，是否必须经过 LayerNorm 的 Jacobian？**

(b) 将 Pre-Norm 从第 $0$ 层展开到第 $L$ 层，可以得到：

$$x_L = x_0 + \sum_{l=0}^{L-1} F_l\!\big(\text{LN}(x_l)\big)$$

对 $x_l$ 求梯度 $\frac{\partial x_L}{\partial x_l}$，证明结果中包含一个**恒等矩阵 $I$**。这个 $I$ 意味着什么？为什么它对深层网络的训练至关重要？

(c) 对 Post-Norm 做同样的梯度分析。说明为什么 Post-Norm 中**不存在**这样一条"干净"的梯度直通路径，以及这如何导致训练不稳定（需要 learning rate warmup）。

(d) 既然 Pre-Norm 训练更稳定，为什么有研究指出 Post-Norm 在**最终性能**上可能略优？从 "LayerNorm 包裹残差 = 更强的逐层正则化" 的角度给出直觉解释。

(e) 现代大语言模型（LLaMA, Qwen 等）的标准配置是 **Pre-RMSNorm**。结合 Q8(d) 和本题的结论，用一句话总结这个选择的逻辑。

> **Hint**：对于 (a)，Post-Norm 中残差加法的结果被 LayerNorm "包裹"，梯度回传时必须穿过 $J_{\text{LN}}$；Pre-Norm 中残差路径是 $x_{l+1} = x_l + (\cdots)$，对 $x_l$ 求导时加法的梯度直接是 $I$。对于 (b)，这与 ResNet v2（He et al. 2016）的核心思想一致——保持 shortcut 路径的"身份映射"是深层残差网络能训练的关键。对于 (d)，Post-Norm 的 LayerNorm 对每层输出的范数做了约束，相当于不让任何一层的输出"偏离太远"，这种额外的约束在充分训练后可能带来更好的泛化。

---

### Q10 | 回填作业三 Q7 架构比较表格

结合本次作业对 Transformer 的理解，补全作业三 Q7 中 **Self-Attention** 那一行：

| 机制 | 连接方式 | 权重共享 | 编码的对称性 | 适用数据结构 |
|------|---------|---------|------------|------------|
| **MLP** | （已填） | （已填） | （已填） | （已填） |
| **CNN** | （已填） | （已填） | （已填） | （已填） |
| **GNN** | ？ | ？ | ？ | ？（图结构数据） |
| **Self-Attention** | ？ | ？ | ？ | ？ |

并回答：Self-Attention 对应的对称群是什么？它比 CNN 的平移群"大"还是"小"？这对模型的数据效率（data efficiency）意味着什么？

> **Hint**：CNN 假设平移不变性，这是一个很强的先验。Self-Attention 仅假设排列等变性（加位置编码后打破），先验更弱。先验越强 → 需要的数据越少 → 但假设错误的代价也越大。这是 Transformer 需要大量数据才能超越 CNN 的根本原因。

---

### Q11 | 从 CNN 到 Transformer：局部 vs 全局的权衡

(a) 用下表对比 CNN 和 Self-Attention 在三个维度上的差异：

| 维度 | CNN（$3\times3$ 卷积） | Self-Attention |
|------|----------------------|----------------|
| 单层感受野 | ？ | ？ |
| 权重来源 | ？ | ？ |
| 单层计算复杂度 | ？ | ？ |

(b) ViT（Vision Transformer）将图像切成 $16\times16$ 的 patch，每个 patch 作为一个 token。对于 $224\times224$ 的图像，ViT 的序列长度为 $14\times14=196$ 个 token。计算 Self-Attention 在这个序列上的计算量（$O(n^2 d)$），并与一个 $3\times3$ 卷积层在同等图像上的计算量（$O(n \cdot k^2 \cdot d)$）对比。哪个更大？

(c) 为什么 ViT 在小数据集上通常不如 CNN，但在大数据集（如 JFT-300M）上反超？用归纳偏置（inductive bias）的概念解释。

> **Hint**：CNN 的卷积核是**静态的**（训练后固定），而 Attention 的权重是**输入自适应的**（由 QK 内积动态计算）。静态权重 = 强先验（好处是数据高效，坏处是灵活性差）；动态权重 = 弱先验（好处是灵活，坏处是需要更多数据才能学好）。

---

### Q12 | $O(n^2)$ 的代价：Transformer 能看多远？

本次作业中，MarianMT 设置了 `max_seq_len=512`，即模型一次最多处理 512 个 token。Self-Attention 的注意力矩阵大小为 $n \times n$，当 $n=512$ 时仅需 $512^2 \approx 262\text{K}$ 个元素，轻松放入显存。

(a) 如果我们想让模型直接处理一篇 10 万 token 的长文档（$n = 100{,}000$），注意力矩阵需要多少个元素？假设每个元素占 2 字节（FP16），仅**一层、一个注意力头**的注意力矩阵就需要多少 GB 显存？

(b) 这个 $O(n^2)$ 的限制意味着，**标准 Transformer 的"全局注意力"只在固定长度窗口内是全局的**。对于本次翻译任务，逐句翻译在大多数情况下效果不错。但请举出一个例子，说明"只看当前句子、看不到上文"会导致翻译错误或不自然的场景。

(c) 突破上下文长度限制是大语言模型（LLM）的核心挑战之一。下表列出了几种代表性方法，请为每种方法填写"一句话本质"——用最简洁的语言概括它**到底改了什么**：

| 方法 | 一句话本质（请填写） | 改了什么层面 |
|------|-------------------|------------|
| **FlashAttention** | ？ | IO 调度（数学等价） |
| **Sparse Attention**（Longformer, BigBird） | ？ | 注意力矩阵结构 |
| **Linear Attention**（Performer） | ？ | 计算顺序 |
| **Ring Attention** | ？ | 分布式并行 |
| **PagedAttention**（vLLM） | ？ | 显存管理 |
| **Mamba / RWKV** | ？ | 整体架构 |

(d) 上面六种方法，按"改动的层面"可以归入四个类别。请将它们分类，并回答：哪些方法**不改变数学结果**（即与标准 Attention 完全等价），哪些方法**做了近似或替代**？

| 类别 | 包含的方法 | 是否数学等价 |
|------|-----------|------------|
| ① 纯 IO / 工程优化（不改公式，只改调度或内存管理） | ？ | ？ |
| ② 稀疏化 / 近似（改注意力矩阵本身） | ？ | ？ |
| ③ 分布式并行（把计算分到多卡） | ？ | ？ |
| ④ 架构替代（不用 Attention） | ？ | ？ |

(e) **Linear Attention** 是一个特别优雅的思路。标准 Attention 计算 $\text{softmax}(QK^T)V$，必须先算 $n \times n$ 的 $QK^T$ 矩阵。Linear Attention 用核函数 $\phi$ 近似 softmax，将公式变为 $\phi(Q)(\phi(K)^T V)$。

- 标准 Attention 的乘法顺序是 $(QK^T) \cdot V$，先算括号内的 $QK^T$ 是 $n \times n$ 矩阵；
- Linear Attention 的乘法顺序是 $\phi(Q) \cdot (\phi(K)^T V)$，先算括号内的 $\phi(K)^T V$ 是 $d \times d$ 矩阵。

这只是改变了**矩阵乘法的结合顺序**。解释为什么这一改变能将复杂度从 $O(n^2 d)$ 降为 $O(n d^2)$，并说明在什么条件下（$n$ 与 $d$ 的大小关系）这种改变是有利的。

(f) **从 safe softmax 到 online softmax**：Q1(e) 中你知道了计算 softmax 时需要先减去行最大值以避免溢出。但 FlashAttention 将注意力计算**分块（tiling）** 进行——处理当前块时，尚不知道整行的全局最大值。这似乎与 safe softmax 矛盾。FlashAttention 是如何在分块条件下仍然保证数值稳定性的？请描述其核心思路。

> **Hint**：对于 (a)，$100{,}000^2 = 10^{10}$，乘以 2 字节后换算为 GB。注意实际模型有多层、多头，总显存还要乘以层数 $\times$ 头数。对于 (b)，考虑代词消解：当一句话中出现"它"、"他"、"该公司"等指代时，正确翻译依赖于上文中被指代的对象。对于 (c)，FlashAttention 的本质不是"加速计算"，而是改变数据在 GPU 内存层次（HBM ↔ SRAM）之间的搬运方式；PagedAttention 可以类比操作系统中的虚拟内存分页机制。对于 (d)，关键区分标准是：给定相同输入，输出是否**严格相同**？FlashAttention 是严格等价的，而 Sparse Attention 丢弃了部分位置的注意力，结果是近似的。对于 (e)，$(QK^T)$ 是 $(n \times d)(d \times n) = n \times n$ 矩阵，再右乘 $V$（$n \times d$）总计 $O(n^2 d)$；$(\phi(K)^T V)$ 是 $(d \times n)(n \times d) = d \times d$ 矩阵，再左乘 $\phi(Q)$（$n \times d$）总计 $O(nd^2)$。当 $n \gg d$（长序列、低维度）时收益最大。对于 (f)，关键词是 **online softmax**（Milakov & Gimelshein, 2018）：处理每个新块时，如果发现了更大的最大值，可以用一个修正因子 $e^{m_{\text{old}} - m_{\text{new}}}$ 去 rescale 之前块累积的结果。想一想：为什么这个 rescale 因子一定 $\leq 1$？

---

### Q13 | 从训练到推理：解码策略与 KV Cache

训练时，Decoder 使用 **Teacher Forcing**：一次性将完整的目标序列 $[y_0, y_1, \ldots, y_{T-1}]$ 作为输入，同时预测 $[y_1, y_2, \ldots, y_T]$。但推理时，目标序列还不存在——模型必须**逐 token 生成**。

(a) 推理时，Decoder 生成第 $t$ 个 token 时，Self-Attention 的 Query 来自哪里？Key 和 Value 来自哪里？Cross-Attention 的 Query、Key、Value 又分别来自哪里？用下表整理：

| Attention 类型 | Q 来自 | K, V 来自 |
|---|---|---|
| Decoder Self-Attention | ？ | ？ |
| Cross-Attention | ？ | ？ |

(b) 每步生成时，Decoder 需要重新计算所有已生成 token 的 Key 和 Value 吗？**KV Cache** 的核心思想是什么？为什么只缓存 K 和 V 而不缓存 Q？

> **Hint**：Self-Attention 中，位置 $t$ 的 Query 只在当前步使用——它的作用是"向前面的 token 提问"。但位置 $t$ 的 Key 和 Value 在**所有后续步骤**中都会被新 token 查询。Cross-Attention 的 K、V 来自 Encoder 输出，在整个生成过程中不会变化。

(c) 假设模型有 $L$ 层 Decoder，每层有 Self-Attention 和 Cross-Attention 两个子层，隐藏维度为 $d$。生成到第 $t$ 步时，KV Cache 需要存储多少个浮点数？（分别计算 Self-Attention 和 Cross-Attention 的缓存量）

(d) 获得每个位置的 logits 后，如何选择下一个 token？以下是几种常见的**解码策略**，分析它们各自的特点：

| 策略 | 做法 | 特点 |
|------|------|------|
| Greedy | 每步选概率最高的 token | ？ |
| Beam Search（束宽 $k$） | 每步保留概率最高的 $k$ 条候选路径 | ？ |
| Top-$k$ Sampling | 从概率最高的 $k$ 个 token 中按概率采样 | ？ |
| Top-$p$ (Nucleus) Sampling | 从累积概率达到 $p$ 的最小 token 集合中采样 | ？ |

为什么机器翻译通常使用 Beam Search，而 ChatGPT 等对话模型使用 Sampling？

> **Hint**：翻译追求**准确性和确定性**——同一句话的"标准翻译"通常只有少数几种。对话追求**多样性和创造性**——如果每次回答都一样，对话就变得无聊了。`temperature` 参数通过 $\text{softmax}(z_i / T)$ 控制概率分布的"尖锐程度"：$T \to 0$ 趋向 Greedy，$T \to \infty$ 趋向均匀采样。

---

### Q14 | 残差连接的进化：从固定累加到深度注意力

Q9 分析了 Pre-Norm 残差连接 $x_{l+1} = x_l + F_l(\text{LN}(x_l))$ 的梯度优势。本题进一步追问：**残差连接本身还能改进吗？**

#### 背景

将 Pre-Norm 从第 0 层展开到第 $L$ 层：

$$h_L = v_0 + v_1 + v_2 + \cdots + v_{L-1}$$

其中 $v_0$ 是词嵌入，$v_i = F_i(h_i)$ 是第 $i$ 层的输出。可以将这个求和写成更一般的形式：

$$h_l = \sum_{i=0}^{l-1} M_{i \to l} \cdot v_i$$

其中 $M_{i \to l}$ 表示"第 $i$ 层的输出对第 $l$ 层输入的贡献权重"。标准残差连接中 $M_{i \to l} = 1$（对所有 $i < l$）。我们称 $M$ 为**深度混合矩阵**。

---

(a) 标准残差中 $M_{i \to l} = 1$ 意味着每一层的贡献被**无差别地等权累加**。这带来了什么问题？请从以下两个角度各给一句话：
   - 第 20 层能否"选择性地"多关注第 3 层、少关注第 5 层的输出？
   - 随着层数 $L$ 增大，$h_L = \sum_{i=0}^{L-1} v_i$ 的范数会如何变化？这对深层的 $v_i$ 意味着什么？

(b) **Hyper-Connections（HC）** 提出用 $n$ 条平行的残差流替代单条残差流。每条流是一个 $d$ 维向量，层间传递的状态从 $h \in \mathbb{R}^d$ 变为 $H = (h_1, h_2, \ldots, h_n)^\top \in \mathbb{R}^{n \times d}$。

由于 Attention/FFN 的内部结构不变（仍只接受一个 $d$ 维向量），HC 需要三组权重：

| 权重 | 作用 |
|------|------|
| $\alpha_l$（Pre-mapping） | 从 $n$ 条流加权聚合出层的输入 |
| $\beta_l$（Post-mapping） | 将层的输出按权重分发回 $n$ 条流 |
| $A_r^l$（Residual-mapping） | $n$ 条流之间的混合矩阵 |

当 $n=1$ 且 $\alpha=\beta=A_r=1$ 时，HC 退化为标准 Pre-Norm 残差。请解释：为什么 $n > 1$ 时，网络可以在不同的流上保留不同层的信息？这相比标准残差有什么优势？

(c) 将 HC 的多流机制展开，可以得到其深度混合矩阵的元素为：

$$M_{i \to l}^{\text{HC}} = \beta_i \cdot \left(\prod_{t=i+1}^{l-1} A_r^t\right) \cdot \alpha_l$$

与标准残差的 $M_{i \to l} = 1$ 对比，HC 的 $M$ 由哪三个因素决定？请分别解释 $\beta_i$、$\prod A_r^t$ 和 $\alpha_l$ 的直觉含义（提示：类比 Self-Attention 中的 Key、位置编码、Query）。

(d) **Attention Residuals（AttnRes）** 提出了一种更直接的方案：用 **softmax 注意力**来计算深度混合权重。具体地，每一层 $l$ 有一个可学习的 $d$ 维向量 $w_l$，第 $l$ 层的输入为：

$$h_l = \sum_{i=0}^{l-1} \alpha_{i \to l} \cdot v_i, \quad \alpha_{i \to l} = \frac{\exp(w_l^\top \cdot \text{RMSNorm}(v_i))}{\sum_{j=0}^{l-1} \exp(w_l^\top \cdot \text{RMSNorm}(v_j))}$$

请将这个公式与 Q1 中你计算过的 Self-Attention 做对应。填写下表：

| | Token Self-Attention（Q1） | AttnRes（深度注意力） |
|---|---|---|
| 注意力的方向 | 沿序列：token 看 token | ？ |
| Query | $Q = XW_Q$（由输入投影） | ？ |
| Key | $K = XW_K$（由输入投影） | ？ |
| Value | $V = XW_V$（由输入投影） | ？ |
| 投影矩阵 | 需要 $W_Q, W_K, W_V$ | ？ |
| 每层新增参数 | $3 \times d \times d_k$ | ？ |

(e) AttnRes 论文指出："标准残差连接和 HC 都是深度维度上的**线性注意力**，AttnRes 是深度维度上的 **softmax 注意力**。" 结合你在 Q12(e) 中对 Linear Attention 的理解，解释这个类比：HC 的 $M_{i \to l}$ 为什么是"线性"的？AttnRes 的 $M_{i \to l}$ 为什么是"softmax"的？这与序列维度上 Linear Attention vs Standard Attention 的区别有什么对应关系？

> **Hint**：对于 (a)，Q9(b) 中分析过 $h_L = x_0 + \sum v_i$，当 $L$ 很大时，各层输出被"稀释"——第 50 层的输出只占总和的 $1/50$。对于 (b)，想象两条流分别像两个"笔记本"：一个记录浅层信息，一个记录深层信息，最后按需翻阅。对于 (c)，$\beta_i$ 决定第 $i$ 层"写了什么"（类比 Key），$\alpha_l$ 决定第 $l$ 层"想读什么"（类比 Query），$\prod A_r^t$ 是中间经过的混合变换（类比位置编码）。对于 (d)，AttnRes 的 Query 是一个**可学习参数**而非从输入投影，Key 和 Value 共享来源（都是层输出），不需要投影矩阵。对于 (e)，HC 的 $M$ 是矩阵乘积的线性组合（没有 softmax 归一化），AttnRes 的 $M$ 经过了 softmax 归一化——这正对应序列维度上 Linear Attention 用线性核、Standard Attention 用 softmax 的区别。

---

## 八、提交要求

将以下文件打包为 `学号_姓名_HW4.zip`：

- `finetune_translation.py` — 微调翻译模型的脚本
- 训练日志截图或终端输出（需包含微调前后的 BLEU 分数）
- 交互翻译截图（至少 3 条自选句子的翻译结果及简要评价）
- （可选）注意力可视化热力图

通过课程 QQ 群的作业系统上传。

---

## 九、参考依赖

```
torch
transformers
datasets
evaluate
sacrebleu
sentencepiece
matplotlib
```
