Attention Mask 笔记

一句话:Mask 是在计算 softmax 之前,把某些位置的注意力分数强制设为 $-\infty$,使 softmax 后这些位置的权重变为 0,相当于"屏蔽掉"不该看的位置。 一、为什么需要 Mask? Attention 的计算是: $$ \text{scores} = \frac{QK^T}{\sqrt{d_k}}, \quad \text{weights} = \text{softmax}(\text{scores}), \quad \text{output} = \text{weights} \cdot V $$ 默认情况下,每个 token 的 Q 会和序列中所有 token 的 K 做点积,包括: 无意义的 [PAD] 填充 token 未来还没生成的 token(训练时) 这两种情况都需要用 Mask 屏蔽掉。 二、两种 Mask 2.1 Padding Mask(填充遮罩) 问题:一个 batch 里不同句子长度不同,需要用 [PAD] token 补齐到相同长度,但 [PAD] 是无意义的,不应该被 Attention 到。 batch 里两个句子(补齐到长度5): 句子1: ["今", "天", "好", "[PAD]", "[PAD]"] ← 实际长度3,补了2个PAD 句子2: ["天", "气", "真", "不", "错" ] ← 实际长度5,无需补 Padding Mask(1=有效位置,0=PAD位置): 句子1: [1, 1, 1, 0, 0] 句子2: [1, 1, 1, 1, 1] 屏蔽效果: ...

May 12, 2026 · 5 min

Batch Norm vs Layer Norm 学习笔记

核心问题:为什么需要归一化?神经网络训练时,每层的输入分布会随参数更新不断变化(Internal Covariate Shift),导致训练不稳定、收敛慢。归一化就是把数据"拉回"到均值为0、方差为1的分布,再通过可学习参数还原表达能力。 一、公式(两者一样,区别在于"沿哪个维度算") $$ \hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}}, \quad y = \gamma \hat{x} + \beta $$ $\mu$、$\sigma^2$:均值和方差(统计维度不同是BN和LN的核心区别) $\gamma$、$\beta$:可学习的缩放和偏移参数 $\epsilon$:防止除零的小常数 二、Batch Norm(BN) 核心思想 跨样本、同一特征维度做归一化。 统计维度 假设输入 shape 为 [B, C, H, W](B=batch,C=通道,H/W=空间): 对每个通道 C,在 B、H、W 三个维度上计算均值和方差 每个通道有一组独立的 $\gamma$、$\beta$ 直觉理解 “把这批图片里,同一个通道的所有像素值,统一归一化” 具体例子 输入:4张图,每张1个通道,2x2像素 数据(展平后每行是一张图的像素): 图1: [1, 2, 3, 4] 图2: [5, 6, 7, 8] 图3: [2, 3, 4, 5] 图4: [6, 7, 8, 9] BN 把这 4×4=16 个数一起算均值和方差: 所有数:1,2,3,4,5,6,7,8,2,3,4,5,6,7,8,9 μ = (1+2+3+4+5+6+7+8+2+3+4+5+6+7+8+9) / 16 = 80/16 = 5.0 σ² = [(1-5)²+(2-5)²+...+(9-5)²] / 16 = 88/16 = 5.5 σ = √5.5 ≈ 2.345 归一化示例(以图1的像素值1为例): x̂ = (1 - 5.0) / √(5.5 + ε) ≈ -4.0 / 2.345 ≈ -1.706 所有16个像素值都用同一个 μ=5.0、σ≈2.345 归一化 优点 效果好,训练稳定,允许更大学习率 CV 任务(CNN)的标配 缺点 依赖 batch size:batch 太小时均值/方差估计不准,效果差 推理时需要维护全局统计量(running mean/var) 不适合 RNN/Transformer:序列长度不固定,batch 内样本差异大 三、Layer Norm(LN) 核心思想 同一样本、跨特征维度做归一化。 ...

May 12, 2026 · 2 min

BPE 与 Tokenizer 笔记

一句话:BPE(Byte Pair Encoding)是一种把文本切分成"子词单元"的算法,是现代大模型 Tokenizer 的核心。tiktoken 是 OpenAI 实现的高性能 BPE 库,GPT 系列模型使用它。 一、为什么需要 Tokenizer? 模型不能直接处理文字,需要先把文字转成数字(token ID),再转成向量(embedding)。 原始文本:"今天天气很好" ↓ Tokenizer token 序列:["今天", "天气", "很", "好"] ↓ 查词表 token ID:[1234, 5678, 910, 1112] ↓ Embedding 层 向量矩阵:[[...], [...], [...], [...]] ← 模型真正处理的输入 二、三种切分粒度的对比 在 BPE 出现之前,有两种极端方案: 方案1:词级别(Word-level) "unhappiness" → ["unhappiness"] ← 一个词一个 token 问题: 词表会非常大(英语有几十万个词) 遇到训练时没见过的新词(OOV,Out-of-Vocabulary)就不认识 不同语言、不同形态的词需要分别存储(“run”、“running”、“ran” 是三个不同 token) 方案2:字符级别(Character-level) "unhappiness" → ["u","n","h","a","p","p","i","n","e","s","s"] ← 每个字符一个 token 问题: 序列太长,Attention 的 $O(T^2)$ 复杂度爆炸 字符本身语义信息太少,模型难以学习 方案3:子词级别(Subword-level)—— BPE 的目标 "unhappiness" → ["un", "happi", "ness"] ← 有意义的子词单元 优点: ...

May 12, 2026 · 5 min

KV Cache 笔记

一句话:KV Cache 是推理时把已经算过的 Key 和 Value 缓存起来,避免每生成一个新 token 都重复计算历史 token 的 K/V,是大模型推理加速的核心技术。 一、为什么需要 KV Cache? 大模型生成 token 的方式:自回归(Auto-regressive) 大模型生成文本是一个 token 一个 token 地生成的,每次生成下一个 token 时,都要把所有历史 token 作为输入重新过一遍 Transformer。 输入: "今天天气" 生成: "今天天气" → "很" 生成: "今天天气很" → "好" 生成: "今天天气很好" → "!" 每一步生成,Attention 都要计算: $$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$ 其中 Q、K、V 都来自当前所有 token(包括历史的)。 没有 KV Cache 时的重复计算 假设已经生成了 t 个 token,现在要生成第 t+1 个: 第1步生成"很": 对 token ["今","天","天","气"] 全部计算 K、V → K = [K_今, K_天, K_天, K_气] → V = [V_今, V_天, V_天, V_气] 第2步生成"好": 对 token ["今","天","天","气","很"] 全部计算 K、V → K = [K_今, K_天, K_天, K_气, K_很] ← 前4个和上一步完全一样! → V = [V_今, V_天, V_天, V_气, V_很] ← 前4个和上一步完全一样! 第3步生成"!": 对 token ["今","天","天","气","很","好"] 全部计算 K、V → 前5个 K/V 和上一步完全一样! 历史 token 的 K/V 每次都重新算,纯属浪费。 ...

May 12, 2026 · 8 min

Linear Attention(线性注意力)笔记

一句话:标准 Attention 的复杂度是 $O(N^2)$,Linear Attention 通过改变计算顺序,把复杂度降到 $O(N)$,代价是用核函数近似替代 softmax,牺牲了一定的表达能力,但换来了推理时的递推形式(类似 RNN),天然支持无限长序列。 一、问题背景:标准 Attention 的瓶颈 标准 Attention 的计算: $$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$ 序列长度为 $N$ 时: 计算 $QK^T$ 需要 $O(N^2)$ 时间和空间 中间的 $N \times N$ 注意力矩阵需要 $O(N^2)$ 显存 后果:序列长度翻倍,计算量翻 4 倍,显存翻 4 倍。长序列(如 100K token)几乎不可能用标准 Attention。 二、核心思想:改变计算顺序 标准 Attention 的计算顺序 $$\text{out} = \underbrace{\text{softmax}(QK^T)}_{\text{先算这个,}N \times N \text{ 矩阵}} V$$ 必须先把完整的 $N \times N$ 矩阵算出来,才能乘以 $V$。 Linear Attention 的关键洞察 如果去掉 softmax,矩阵乘法满足结合律: $$\text{out} = (QK^T) V = Q \underbrace{(K^T V)}_{\text{先算这个,}d \times d \text{ 矩阵}}$$ ...

May 12, 2026 · 4 min

LoRA / QLoRA / Unsloth 微调笔记

一句话:LoRA 用低秩矩阵大幅减少微调参数量;QLoRA 在此基础上把基础模型量化到 4bit,让消费级 GPU 能微调 70B 模型;Unsloth 是工程加速库,把整个流程再提速 2-5×。三者是层层叠加的关系。 一、为什么需要参数高效微调(PEFT)? 全量微调(Full Fine-tuning)的问题: GPT-3(175B 参数)全量微调: - 参数量:175B × 4 bytes(FP32)= 700 GB 显存 - 梯度:再 × 1 = 700 GB - 优化器状态(Adam):再 × 2 = 1400 GB - 合计:约 2800 GB 显存 → 需要 35 张 A100(80GB) 核心矛盾:预训练模型越来越大,但大多数下游任务只需要微调模型的"方向",不需要改变所有参数。 参数高效微调(PEFT) 的思路:冻结大部分参数,只训练少量新增参数,效果接近全量微调,但显存和计算量大幅减少。 二、LoRA:低秩适配(Low-Rank Adaptation) 核心思想 LoRA(2021,微软)的关键洞察:预训练模型的权重更新矩阵是低秩的。 全量微调时,权重更新为: $$W’ = W_0 + \Delta W$$ 其中 $W_0 \in \mathbb{R}^{d \times k}$ 是预训练权重,$\Delta W$ 是更新量。 LoRA 假设 $\Delta W$ 是低秩的,用两个小矩阵的乘积来近似: ...

May 12, 2026 · 7 min

Mamba / SSM(状态空间模型)笔记

一句话:Mamba 是 Linear Attention 的"升级版"——同样是 $O(N)$ 复杂度、固定大小隐状态,但通过选择性机制(Selective SSM) 让模型能动态决定"记住什么、忘记什么",效果接近 Transformer,推理速度接近 RNN。 一、从 Linear Attention 到 Mamba:解决什么问题? 回顾 Linear Attention 的递推公式: $$S_t = S_{t-1} + \phi(k_t) v_t^T$$ 问题:衰减是固定的(没有衰减,或者 RetNet 里用固定的 $\gamma$),模型无法根据输入内容动态决定"这个历史信息重不重要"。 类比: RNN(LSTM):有遗忘门,可以选择性地清除历史 Linear Attention:没有遗忘门,历史信息只增不减,全部堆进 S 矩阵 RetNet:有固定衰减 γ,但 γ 是超参数,不随输入变化 Mamba:衰减因子由输入动态生成,每个 token 的"遗忘程度"不同 二、SSM 的数学基础 Mamba 基于状态空间模型(State Space Model,SSM),这是控制论里的经典框架。 连续时间 SSM $$h’(t) = A h(t) + B x(t)$$ $$y(t) = C h(t)$$ $x(t)$:输入信号 $h(t)$:隐状态(类比 RNN 的 hidden state) $y(t)$:输出 $A$:状态转移矩阵(控制历史信息如何演化) $B$:输入投影矩阵(控制输入如何影响隐状态) $C$:输出投影矩阵(控制隐状态如何映射到输出) 离散化(实际使用的形式) 连续 SSM 需要离散化才能用于序列建模,使用零阶保持(ZOH) 方法: ...

May 12, 2026 · 9 min

MoE(Mixture of Experts)混合专家模型笔记

一句话:MoE 是对 Transformer 中 FFN 层的改进——把一个 FFN 替换成多个并行的"专家"FFN,每个 token 只激活其中少数几个专家,从而在不增加计算量的前提下大幅扩展模型参数量。 一、问题背景:Dense 模型扩参数的代价 标准 Transformer(Dense 模型)每个 token 都要经过所有参数: 参数量翻倍 → 计算量翻倍 → 训练/推理成本翻倍 想要更强的模型,就必须付出更高的计算代价。有没有办法让参数量和计算量解耦? 二、核心思想:条件计算(Conditional Computation) 不是每个 token 都需要用到所有知识,让不同的 token 走不同的"专家"路径。 MoE 的核心设计: 把 FFN 层替换成 N 个并行的专家 FFN 每个 token 由一个路由器(Router)决定激活哪 K 个专家 只有被选中的专家才参与计算,其余专家跳过 结果: 总参数量 = N 个专家的参数之和(很大) 每次计算量 = 只激活 K 个专家(很小) 参数量和计算量不再线性绑定 三、结构对比 Dense FFN(原始) 输入 x(形状:[seq_len, d_model]) ↓ FFN(W_gate, W_up, W_down) ↓ 输出(形状:[seq_len, d_model]) MoE FFN(替换后) 输入 x(形状:[seq_len, d_model]) ↓ Router(路由器):为每个 token 计算各专家的得分,选出 Top-K ↓ 并行调用被选中的 K 个专家 FFN ↓ 按路由权重加权求和,合并输出 ↓ 输出(形状:[seq_len, d_model])← 形状和 Dense FFN 完全一致 注意:Attention 层不变,只有 FFN 层被替换成 MoE。 ...

May 12, 2026 · 3 min

Multi-Head Attention(MHA)多头注意力笔记

前置知识:已了解 Self-Attention(自注意力)。 MHA 的本质:把 Self-Attention 并行做多次,每次关注不同的语义子空间,最后合并结果。 一、为什么需要多头?Self-Attention 有什么不足? 单头 Self-Attention 每次只能学到一种"关注模式"。例如: 句子:"The animal didn't cross the street because it was too tired" 头1 可能学到:it → animal(指代关系) 头2 可能学到:tired → animal(状态描述) 头3 可能学到:cross → street(动作与地点) 单头只能同时关注一种模式,多头让模型在不同子空间里并行捕捉多种关系。 二、MHA 整体结构 输入 X │ ├──→ 线性投影 W_Q^1 → Q1 ─┐ ├──→ 线性投影 W_K^1 → K1 ─┤→ Attention(Q1,K1,V1) → head_1 ─┐ ├──→ 线性投影 W_V^1 → V1 ─┘ │ │ │ ├──→ 线性投影 W_Q^2 → Q2 ─┐ │ ├──→ 线性投影 W_K^2 → K2 ─┤→ Attention(Q2,K2,V2) → head_2 ─┤→ Concat → 线性投影 W_O → 输出 ├──→ 线性投影 W_V^2 → V2 ─┘ │ │ │ ├──→ ...(共 h 个头) │ │ │ └──→ 线性投影 W_Q^h → Qh ─┐ │ 线性投影 W_K^h → Kh ─┤→ Attention(Qh,Kh,Vh) → head_h ─┘ 线性投影 W_V^h → Vh ─┘ 三、完整公式 单头 Scaled Dot-Product Attention(回顾) $$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$ ...

May 12, 2026 · 13 min

优化器(Optimizer)笔记

一句话:优化器决定"用梯度怎么更新参数"。从最朴素的 SGD,到加了动量的 SGD Momentum,再到自适应学习率的 Adam/AdamW,每一步改进都在解决上一代的具体问题。 一、梯度下降的基本框架 所有优化器的核心都是: $$\theta_{t+1} = \theta_t - \text{update}(g_t)$$ 其中 $g_t = \nabla_\theta \mathcal{L}$ 是当前 batch 的梯度,不同优化器只是 $\text{update}$ 的计算方式不同。 三种梯度下降变体(按 batch 大小区分): 批量梯度下降(BGD): 用全部数据算梯度,准确但极慢 随机梯度下降(SGD): 用 1 条数据算梯度,快但噪声大 小批量梯度下降(MSGD):用 mini-batch 算梯度,实践中的标准做法 现代所有"SGD"都指小批量梯度下降。 二、SGD:最朴素的优化器 $$\theta_{t+1} = \theta_t - \eta \cdot g_t$$ $\eta$:学习率(步长) $g_t$:当前 mini-batch 的梯度 问题: 学习率敏感:太大震荡,太小收敛慢 各维度步长相同:不同参数的梯度尺度可能差异极大,一个学习率无法同时适配所有参数 容易卡在鞍点:梯度为零但不是极值点 三、SGD + Momentum:加入惯性 $$v_t = \beta \cdot v_{t-1} + g_t$$ $$\theta_{t+1} = \theta_t - \eta \cdot v_t$$ $v_t$:速度(历史梯度的指数加权平均) $\beta$:动量系数,通常为 0.9 直觉:像一个球滚下山坡,历史的速度会叠加到当前更新上。 ...

May 12, 2026 · 5 min