介绍一下self-attention。

Self-Attention是一种在序列建模中使用的机制。它的核心思想是:序列里的每个元素可以动态地决定该关注哪些其他元素。具体做法是把输入向量映射成 QueryKeyValue,用 QueryKey 点积算出相关性权重,再用这个权重对 Value 加权求和,这样每个位置的表示都会包含全局上下文的信息。相比 RNNCNN,它能更好地捕捉长距离依赖,还能并行计算。Transformer 就是建立在这个机制上的,有时候通过多头注意力来从不同角度理解语义关系。
A t t e n t i o n ( Q , K , V ) = S o f t m a x ( Q ⋅ K T d k ) ⋅ V Attention(Q, K, V) = Softmax(\frac{Q \cdot K^T}{\sqrt{d_k}}) \cdot V Attention(Q,K,V)=Softmax(dk QKT)V

1. 为什么self-attention中计算score要除根号dk?

  • 【作用】归一化作用,防止 Q ⋅ K T Q \cdot K^T QKT内积过大而导致Softmax后梯度消失。
    • 点积结果 的期望和方差会随维度增大;
    • softmax 的输入如果数值很大,会趋向于“极端化”(过饱和):某个维度接近 1,其他接近 0。会导致 梯度消失(大部分梯度接近 0)
    • 通过除以 d k \sqrt{d_k} dk ,点积的方差被缩小到大约 1,避免随着维度增长而过大,从而让 softmax 的输入保持在一个适中的数值范围(避免过饱和)。

2. 为什么不是除dk而是根号dk?

  • 假设QK的每个分量 q ⃗ , k ⃗ \vec{q}, \vec{k} q ,k 均值 0、方差 1的独立随机变量:
    q ⃗ = ( q 1 ,   q 2 ,   . . . ,   q d k ) ,  k ⃗ = ( k 1 ,   k 2 ,   . . . ,   k d k ) \vec{q} = (q_1,~q_2,~...,~q_{d_k}),~\vec{k} = (k_1,~k_2,~...,~k_{d_k}) q =(q1, q2, ..., qdk) k =(k1, k2, ..., kdk)
  • 那么 Q K T QK^T QKT矩阵中任意元素值等于 q ⃗ ⋅ k ⃗ = ∑ i = 1 d k q i k i \vec{q} \cdot \vec{k} = \sum_{i=1}^{d_k} q_i k_i q k =i=1dkqiki
  • 每一项 q i k i q_i k_i qiki期望是 0,方差是 1
  • d k d_k dk项相加后,期望是 0,方差是 d k d_k dk。==> 标准差为 d k \sqrt{d_k} dk
  • 除以 d k \sqrt{d_k} dk ,能把点积的标准差归一化到大约 1,维度无关

Self-Attention是怎么做归一化的?BN还是LN?对结果有什么影响?

在 Transformer 的整体结构中,不是用 Batch Normalization (BN),而是用 Layer Normalization (LN)。原因如下:

  • BN:对 batch 大小敏感,而 NLP 模型常常需要处理可变长序列、甚至 batch size = 1 的情况,所以BN在 NLP 序列建模里表现不稳定,尤其是长序列或小 batch,会带来训练震荡。

  • LN:是对 单个样本的所有特征维度做归一化,不依赖 batch,更稳定、收敛更快,也能保证不同 batch size 下的一致性。

  • 改进点:后来有 RMSNorm、Pre-LN Transformer 等变体,在实践中能进一步提升训练稳定性和速度。

Pre-Norm和Post-Norm的区别?

方面 Post-Norm Pre-Norm
顺序 x l + 1 = LN ( x l + F ( x l ) ) x_{l+1} = \text{LN}(x_l + F(x_l)) xl+1=LN(xl+F(xl)) x l + 1 = x l + F ( LN ( x l ) ) x_{l+1} = x_l + F(\text{LN}(x_l)) xl+1=xl+F(LN(xl))
梯度传播 梯度可能在深层消失/爆炸 梯度更容易传播
原因 残差经过 LN,梯度被不断扰动 残差绕过 LN,保证一条“干净”梯度路径
训练稳定性 浅层稳定,深层不稳定 深层稳定
最早应用 原版 Transformer 改进版(GPT 系列等常用)
最终性能 有时更高(浅层时) 更稳健,但有时略低

为什么现在 transformer 都用 LayerNorm 而不是 BatchNorm?

特性 BatchNorm LayerNorm
归一化维度 在一个 batch 的样本中,对每个特征维度取均值和方差 在单个样本的所有特征维度上取均值和方差
依赖 batch 大小 ✅ 是的(需要整个 batch 计算统计量) ❌ 否(只依赖单个样本)
适用场景 CNN(卷积网络)中常见 RNN / Transformer 等序列模型中常见

1. 序列长度不固定、Batch 尺寸不稳定
在 NLP 等任务中,句子长度差异大,padding 也不同。
BatchNorm 需要在一个 batch 内统计均值和方差,这会导致:

  • 不同 batch 的统计结果波动大;
  • padding 部分干扰统计;
  • batch size 太小(如推理时)统计量不稳定。

2. Transformer 的并行化设计
Transformer 同时处理整段序列(self-attention),而不是逐步输入。BatchNorm 在这种高并行环境下计算统计量的代价更高,并且在多 GPU 训练中还需要同步 batch 统计量(SyncBN),这会降低效率。

3. LN对位置无关的特征表示更友好
LayerNorm 在每个 token 的维度上进行归一化,保证每个 token 的内部表示有稳定的分布,而不受其他样本的影响。 这非常适合注意力机制,因为注意力是跨 token 的,而每个 token 自身的分布要尽可能稳定。

4. 推理阶段稳定性
BatchNorm 在推理时需要使用训练时的均值和方差估计(好像要在时间上平均),这在小 batch 或分布变化时容易出问题。
LayerNorm 在推理阶段与训练阶段一致,不需要额外的统计量,行为更可预测。

为什么现在都用 RMSNorm 而不是 LayerNorm?

1. 更简单、更快
RMSNorm 少了“减均值”这步计算,开销更低,计算图更简单。
在大模型训练中,这点优化虽然小,但在数十亿参数规模下非常可观。

👉 例如:LLaMA 和 T5 系列模型都发现 RMSNorm 在相同性能下速度更快、内存更省。

2. 在大模型中,减均值其实没啥帮助
实证研究表明(Zhang & Sennrich, 2019;T5 论文):
对 Transformer 的隐藏表示来说,移除均值几乎不会改变分布或稳定性。也就是说:

  • 均值项的变化很小;
  • 减去均值对训练稳定性帮助不大;
  • 在注意力结构中,scale 的一致性更重要。

3. 训练更稳定、数值更平滑
RMSNorm 保留了向量的方向信息(因为没有中心化),这对于像注意力机制这种依赖方向的操作更自然。在梯度传播时,RMSNorm 也表现出更小的抖动和更好的数值稳定性。

4. 和 Pre-LayerNorm 架构更匹配
现代 Transformer(尤其是 decoder-only 模型,如 GPT、LLaMA)通常采用 PreNorm 架构(即在残差前做归一化)。RMSNorm 的形式与这种结构天然契合:

  • 没有均值平移;
  • 保留特征方向;
  • 在残差叠加时更平滑。

5. 推理效率更高
RMSNorm 的推理阶段完全一致(和训练时无差别),而且少计算均值,可以减少延迟、简化实现。
因此在推理优化库(如 FlashAttention、xFormers)中更好支持。

Self-Attention 和 LSTM ?

Self-Attention 和 LSTM 都是序列建模方法,但机制和作用点不同。

LSTM

  • 核心功能:通过门控机制(输入门、遗忘门、输出门)来记忆和遗忘信息,解决普通 RNN 的梯度消失/爆炸问题。
  • 擅长的地方:
    • 顺序建模(时间序列、语音、传统 NLP)。
    • 保留短期到中期的上下文信息。
  • 局限性:
    • 序列太长时,长距离依赖捕捉效果仍有限
    • 计算是顺序的,难以并行,训练慢。

Self-Attention

  • 核心功能:让序列中的每个元素根据相关性动态“关注”其他所有位置,实现 全局依赖建模。
  • 擅长的地方:
    • 捕捉长距离依赖,不管两个词离多远都能直接交互。
    • 并行计算(不像 LSTM 必须一步步来)。
    • 可解释性:注意力权重能显示模型在关注哪里。
  • 局限性:
    • 计算量大,复杂度是 O ( n 2 ) O(n^2) O(n2),对特别长的序列开销大。

FlashAttention

FlashAttention 是一种 高效实现 Transformer 注意力机制的算法,最早由 Tri Dao 等人在 2022 年提出。它的核心目标是 加速训练与推理,同时减少显存占用

背景

在标准 Transformer 的 self-attention 里,我们需要计算一个大小为 n × n 的注意力矩阵(其中 n 是序列长度)。这个过程既 耗显存(因为要存储整个矩阵),又 耗时(需要做大量矩阵乘法)

FlashAttention 的思路

  1. 避免显式存储完整的注意力矩阵
    • 传统方法先算出完整的 Q K^T,再 softmax,再和 V 相乘。
    • FlashAttention 采用 分块(tiling)+ 流式计算(streaming),只在需要时计算局部块,并立即进行 softmax 和乘法运算。
    • 这样显存开销O(n^2) 降到 O(n)
  2. 利用 GPU 的硬件特性
    • 算法重新组织了计算顺序,让内存访问模式更高效(符合 GPU 的高速缓存访问规律)。
    • 这也是为什么它叫 Flash ——像闪存一样高效利用内存带宽。
  3. 数值稳定性
    • 在分块的同时,算法对 softmax 做了 在线归一化(online normalization),避免数值溢出。

效果

  • 速度提升:比传统 PyTorch 注意力实现快 2-4 倍。
  • 显存节省:可以训练更长序列的模型,而不需要超大显存 GPU。
  • 应用广泛:已在 Hugging Face Transformers、PyTorch 2.0 的 scaled_dot_product_attention 里集成。

MoE(Mixture of Experts)


KVCache

主要用在 Transformer 推理(inference)阶段,尤其是大语言模型(LLM)的自回归生成中 (token-by-token的预测生成任务)。【不用于训练!】

背景

在 Transformer 的自回归生成里(比如聊天模型一步步生成文本),每一步都要用之前的所有 Key (K) 和 Value (V) 来计算注意力。如果不做优化:

  • 每次生成一个新 token,就要重复计算之前所有 tokens 的 K 和 V;
  • 这样计算量和显存占用会随着生成长度线性增加。

KV Cache 的思路

KV cache 就是把 之前计算好的 K 和 V 保存下来,下次生成时直接复用:

  1. 第一次计算
    • 输入前几个 token,计算得到它们的 K 和 V,并存到缓存里。
  2. 后续生成:每生成一个新 token,只需要:
    • 计算新 token 的 Query (Q)、Key (K)、Value (V)。
    • 用缓存里的旧 K、V 再加上新 K、V,进行注意力计算。
      这样就避免了重复计算过去所有 token 的 K、V。

效果

  • 显著加速推理:尤其是长文本生成时,速度提升非常明显。
  • 节省计算量:每一步只计算一次新的 K、V,而不是重新算一遍整个序列。
  • 代价:需要额外显存来保存所有历史的 K、V(显存消耗随生成长度增加)。

为什么缓存 KV 而不是 Q?

S a ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Sa(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}}) V Sa(Q,K,V)=softmax(dk QKT)V

  • Q:Query(查询向量,表示“我要看谁”)
  • K:Key(键向量,表示“我是谁”)
  • V:Value(值向量,表示“我的内容”)
  1. Q 是“临时的”
    • 每次新生成一个 token,都会有新的 Query(只针对当前 token)。
    • 而历史的 Q 并不需要再用,因为之前的 token 不会再被“重新查询”。
  2. K 和 V 是“持久的”
    • 每个 token 的 Key/Value 都会在之后的所有步骤里被反复用:
    • Key 用来跟新的 Q 做匹配(QK^T)。
    • Value 用来加权求和得到注意力输出。

为什么kvcache只用于推理,不能用于训练时的“推理”(前向过程)吗?

  1. 训练时输入和推理的不同
    • 训练:
      • 一次性把整段序列(比如 512 个 token)喂进模型。
      • 模型在前向传播时会同时处理所有位置的 Query、Key、Value。
      • GPU 矩阵乘法并行性很好,算一次就行,不需要缓存。
    • 推理(生成):
      • 每次只输入一个新 token(自回归生成)。
      • 但注意力公式需要用到 历史所有 token 的 K、V。
      • 如果没有 cache,每次都要重新计算整个历史序列的 K/V,代价极大。
  2. KV cache 在训练中的问题
    • 如果训练时用 KV cache:需要把每个位置的 K/V 存起来,但训练是一次性算所有 token 的注意力,没有“重复使用历史 KV”这个问题。缓存不会带来收益,反而增加内存开销。

KV缓存优化方法?—— MHA / MQA / GQA / MLA

图源:Medium.
在这里插入图片描述

MLA核心原理

把 KV 从“每个 token 都存一份高维表示” → 压缩成“低维潜在表示”,再按需恢复。
  • 将 Key 和 Value 压缩到一个共享的低维 latent 空间中,从而显著减少 KV cache 的存储开销。
  • 具体来说,K 和 V 不再独立存储,而是由同一个 latent 表示通过不同的线性映射恢复得到【共享压缩表示不共享恢复参数!】。
【注意】RoPE不能直接用于MLA
  • 由于 Transformer 使用 RoPE 时将位置信息注入 Q/K 向量中,直接压缩Q/K会破坏这种位置依赖。
  • 为此,MLA 的提出者设计了解耦的 RoPE 方案,通过引入额外的共享键向量参与位置编码,从而将内容信息与位置信息分离处理,保证压缩后的潜在向量在恢复键值时不丢失位置信息影响。

vLLM【仅推理】

1. vLLM是什么

vLLM (Virtual Large Language Model Serving) 是一个由加州大学伯克利分校和业界研究者共同开发的 大语言模型高效推理与部署框架。 它的目标是让 LLM 在 推理(inference)和服务(serving) 阶段更快、更高效、更易扩展。
【核心思想】:通过对内存管理计算调度进行优化,在不改变模型参数的情况下,显著提升 LLM 的吞吐量(throughput)和响应速度(latency)。

2. vLLM 的核心技术:PagedAttention

vLLM 提出的关键创新点是 PagedAttention,这是一种优化注意力机制显存管理的方法。

  • 问题:在 LLM 推理时,每个请求会产生不同长度的 KV cache(注意力缓存),传统实现会浪费显存。
  • 解决方案:PagedAttention 借鉴操作系统的 虚拟内存分页机制,将 KV cache 切分成小的内存块(pages),并在 GPU 内存中动态复用
  • 效果:极大减少显存碎片,提高显存利用率,使得同一显卡可以同时服务更多请求。

3. vLLM 的优势

相比于 Hugging Face TransformersDeepSpeedText Generation Inference (TGI) 等其他推理框架,vLLM 主要优势在于:

  1. 吞吐量高
    • 在相同硬件条件下,vLLM 能同时处理更多并发请求。
  2. 显存利用率高
    • PagedAttention 让模型在有限 GPU 显存中可服务更多用户,减少 OOM(out of memory)。
  3. 高效批处理(batching)
    • 支持动态 batching(continuous batching),能够自动将多个不同请求合并,减少空闲计算。
    • 支持流式输出(streaming)
    • 类似于 OpenAI API 的流式返回结果,适合对话和聊天场景。
  4. 兼容性好
    • 支持 Hugging Face Transformers 模型(如 LLaMA、OPT、Falcon、Mistral 等)。
    • 可以与 OpenAI API 格式兼容,几乎无需修改代码就能替换。

DeepSpeed【训练+推理】

DeepSpeed 是微软开源的分布式深度学习优化库,核心目标是让大模型训练与推理更易用、更高效、可扩展。它把多种并行/内存/通信优化打包在一起,并能与 PyTorch、Hugging Face 生态无缝协作。官方定位“训练与推理两端都加速”。

Zero-1 / Zero-2 / Zero-3对比

ZeRO 阶段 分片内容 显存节省 通信开销 适用场景
Stage 1 Optimizer states 中等模型
Stage 2 + Gradients ⭐⭐ 中等 大模型
Stage 3 + Parameters ⭐⭐⭐ 超大模型(例如 GPT-3、BLOOM)

高性能框架对比

框架 特点 适用场景
Transformers (HF) 最通用,研究开发方便,但推理性能有限 本地实验、研究
DeepSpeed 强调训练 + 推理优化,支持大规模分布式 大规模训练、实验室环境
TGI (Text Generation Inference) Hugging Face 官方推理框架,支持优化 batching 商业推理服务
vLLM PagedAttention,高效显存管理,吞吐量最高,兼容 OpenAI API 高并发推理服务

任务并行 / DP/ DDP

1. 任务并行(Task Parallelism)

  • 原理:
    将整个任务拆分成多个独立的子任务
    每个GPU/进程负责完成一个完整但独立的子任务
    各个进程之间无需通信或极少通信

2. DP(Data Parallel)

  • 原理:
    将整个任务拆分成多个独立的子任务
    每个GPU/进程负责完成一个完整但独立的子任务
    各个进程之间无需通信或极少通信

3. DDP(Distributed Data Parallel)

  • 原理:
    将整个任务拆分成多个独立的子任务
    每个GPU/进程负责完成一个完整但独立的子任务
    各个进程之间无需通信或极少通信
特性 任务并行 DP DDP
并行粒度 任务级 数据级 数据级
进程数 多进程 单进程 多进程
通信需求 几乎无 高(每个batch) 中等(梯度同步)
负载均衡 取决于任务分配 主GPU负载重 均衡
内存使用 各GPU独立 主GPU内存占用大 均衡
扩展性 线性(任务独立) 受限于主GPU 良好
适用场景 独立任务、超参搜索 简单的单机训练 大规模训练
实现复杂度 最简单 简单 中等

监督 / 无监督 / 自监督 / 强化学习

学习范式 数据特点 学习方式 常见例子 典型应用场景
监督学习 有人工标注的输入-输出对 学习“老师给的标准答案” 图像分类、情感分析、KNN(K 最近邻算法) 人脸识别、垃圾邮件检测
无监督学习 只有输入数据,没有标注 发现数据内部结构/模式 聚类(K-mean等)、PCA、异常检测 用户画像、推荐系统、异常检测
自监督学习 无标注,但从数据中构造“伪标签” 预测缺失/掩码部分,利用上下文信息 语言模型(BERT/GPT 的预训练) NLP 预训练、表征学习
强化学习 没有明确标签,只有奖励信号 通过与环境交互、试错、最大化累计奖励 AlphaGo、机器人控制、自动驾驶 游戏 AI、机器人、策略优化

RLHF

RLHF (Reinforcement Learning from Human Feedback) 是大语言模型(例如 ChatGPT)训练中的一个关键方法。简单来说,它的流程是:

  1. 预训练(Pretraining)
    • 先用大量公开文本数据(书籍、网页、代码等)训练模型,让它学会语言的基本结构和知识。
  2. SFT(Supervised Fine-Tuning)
    • 再用人工标注的高质量数据(人类写的示范答案)来训练,让模型更接近人类的表达方式。
  3. Reward Model:人类反馈
    • 人类标注者会对模型的多个回答进行排序(例如哪个更礼貌、逻辑更清晰、事实更准确)。这样可以得到一个 “奖励模型”(Reward Model)
  4. 强化学习(PPO/DPO/GRPO等)—— 利用奖励模型来指导大语言模型的输出:
    • 模型生成候选答案
    • 奖励模型打分
    • 通过强化学习算法(如 PPO,Proximal Policy Optimization)更新模型,让它倾向于生成更符合人类偏好的回答。

PPO

DPO

GRPO

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐