LLM
整理各种面试中常见的八股问题,涵盖 Python 基础、PyTorch 基础、算法与数据结构等内容
LLM
Attention
-
点乘注意力中,QKV 矩阵都是什么作用?为什么 Q 和 K 不共用一个?
-
点乘注意力为什么要 scale?scale 为什么是 ?为什么不直接除以 或者其他数值?为什么不做 scale?
-
为了防止点积结果方差随维度 变大而爆炸,导致 softmax 进入饱和区、梯度消失,所以要除以 做归一化
-
根据原始点乘注意力
-
如果不做 scale,就是:
-
假设 Q,K 里的每个元素都是均值 0、方差 1 的独立随机变量,对单个向量 和 的点积:
-
单个 的方差:
-
一共 项独立相加,所以整体方差为:
-
也就是说维度 越大,点积的方差越大,数值越容易变得很大
-
当数值太大时,经过 Softmax 后的分布会极度尖锐,几乎变成 one-hot 向量,梯度会变得极小,出现梯度消失,训练不动
-
因此需要对点积进行缩放,而我们希望缩放后,点积的方差回到 1,设缩放因子为 c:
-
令方差为 1:
-
所以除以 ,可以让点积的方差稳定在 1,与维度无关
-
-
注意力中有哪些类型的掩码?Padding Mask/Sequence Mask/Casual Mask 的作用?
- 在 Transformer 注意力里,掩码本质就是把某些位置的注意力分数强行设为 ,让 softmax 后权重变成 0,从而 “看不见” 这些位置
- Padding Mask(填充掩码):把句子末尾的 padding 位置遮住,不让注意力关注无效的填充位
- Sequence Mask / Key Mask(序列掩码 / Key 掩码):对 key 序列中无效位置做掩码,让 query 不关注这些 key
- Causal Mask(因果掩码 / Look-ahead Mask):Decoder 自注意力中,禁止当前位置看到未来位置的 token,保证自回归生成,本质上是一个下三角掩码,上三角全部设置为 ,保证每个位置只关注自己及之前的 token
-
Attention 计算复杂度,为什么很多时候 attention 不是瓶颈,反而是 MLP?在什么条件下 attention 会变成瓶颈?
- 标准 attention 的复杂度是 ,其中 s 是序列长度,h 是 hidden size
- 而 FFN 的复杂度是 ,因为通常中间层是 4h(甚至更大)
- 关键在于对比 n 和 d 的大小:在 LLM 训练里,常见情况是 (例如 h=4096,s=2k),此时 ,所以 FFN FLOPs 明显更多,所以在很多实际系统里,MLP 才是主要算力消耗者
- 但当 s 很大时(比如长上下文 32k、128k),attention 的 开始爆炸,这时 attention 会成为瓶颈,甚至主导计算和显存
-
Attention 是 memory-bound 还是 compute-bound?
- 理论上 attention 有很多矩阵乘,是 compute-heavy,但在实际 GPU 上往往是 memory-bound
- 原因在于:
- 、softmax、再乘 V,这些步骤之间需要频繁读写中间结果
- softmax 需要做 reduce(max /sum),带来同步和访存压力
- 序列维度访问模式不连续
- 这也是为什么像 FlashAttention 这种方法,通过 “tile + on-chip memory(SRAM)复用” 来减少 HBM 访问,可以显著提速
-
什么是 MHA?为什么要用多个注意力头?MHA 有什么缺点?
- MHA 即 Multi-Head Attention,多头注意力,是 Transformer 的核心组件
- 把 Q、K、V 分成 h 个 “头” 并行做 scaled dot-product attention,最后拼接所有头的输出并做一次线性变换
- 为什么要用多个注意力头:
- 单头注意力只能学到一种全局注意力模式,多头可以学到多组独立的注意力分布
- 让模型能同时关注不同位置、不同类型的依赖关系(比如语法依赖、语义关联、长距离依赖)
- 提升模型表达能力,让不同头专注不同子任务(如位置聚焦、语义匹配、指代消解)
- 并行计算效率高,不显著增加计算量就能大幅提升效果
- 缺点
- KV Cache 显存占用极高:推理时每个头都要独立存储 K、V,序列变长时显存开销呈线性增长
- 访存压力大:HBM 读写次数多,推理带宽受限,成为速度瓶颈
- 计算冗余:多头注意力中部分头学到的模式高度相似,存在冗余计算
-
什么是 MQA?什么是 GQA?
- MQA
- 所有 query 共享同一组 KV,只保留一套 KV 投影
- KV Cache 显存大幅减少,推理速度显著提升,访存压力骤减
- 效果相比 MHA 有明显下降,注意力表达能力受限
- GQA
- 将 Query 头分为若干组,每组内共享一套 K、V,介于 MHA 和 MQA 之间
- 平衡速度、显存与精度,是当前大模型主流方案
- MQA
-
什么是 MLA?MLA 的原理是什么?
-
MLA 解决了传统注意力中 KV Cache 过大的问题,核心做了两件事:
- 共享低维潜在向量:用一个低维向量 同时生成 K 和 V,避免重复缓存
- 位置信息分离:将位置编码(RoPE)从主 K 中分离,单独缓存无位置的压缩向量,大幅降低显存占用
-
Query 侧:内容分支 + 位置分支分开构造
- 内容分支: 负责语义信息,从压缩向量 生成
- 位置分支: 负责位置信息,通过 RoPE 编码
- 最终 Query 是两个分支的拼接,兼顾内容与位置表达
-
Key/Value 侧:低维压缩 + 位置解耦
- 关键压缩点: 是低维共享向量,推理时只缓存这一个向量,而不是缓存完整的 K 和 V
- 位置分支分离: 直接从原始 生成并加 RoPE,不需要缓存,推理时可动态生成
- 显存收益:传统 KV Cache 大小为
2 × seq_len × hidden_dim,MLA 仅需seq_len × d_c(d_c是低维压缩维度,远小于 hidden_dim),显存可降低 70% 以上
-
注意力计算
- 注意力分数同时考虑内容分支和位置分支,缩放因子是两个分支维度和的平方根
- Value 直接使用从 生成的 ,不需要额外缓存
-
-
为什么 RoPE 不能直接对 MLA 中低秩的 Q/K 做位置编码?
-
无 RoPE 时:矩阵吸收 + 低秩压缩(MLA 的基础)
-
在不加入 RoPE 的情况下,MLA 能实现极致的 KV Cache 压缩,核心就是矩阵吸收计算:
-
是一个固定矩阵,可以提前计算好
-
推理时,只需要缓存低维的 ,而不是高维的完整 Key
-
直接用预计算的矩阵和 做一次矩阵乘法,就能还原出 Key 的内积结果
-
缓存的是低维 (维度 ),而不是高维 Key(维度 )
-
KV Cache 显存占用直接降低了 12 倍,这就是 MLA 压缩的核心原理
-
-
加入 RoPE 后:矩阵吸收失效
-
当直接对 Key 应用 RoPE 时,矩阵吸收的前提被破坏了:
-
中间的 是随相对位置变化的,不是固定矩阵
-
RoPE 矩阵插在了两个权重矩阵之间,而矩阵乘法不满足交换律,无法再提前计算吸收
-
这意味着必须为每个 token 重新计算完整的 RoPE Key,压缩收益完全消失,推理效率大幅下降
-
-
为了解决 RoPE 与低秩压缩的矛盾,MLA 设计了双分支拼接结构:
-
分支双工
分支 生成方式 缓存与否 作用 核心特点 内容分支(C) 从低维 生成 缓存 承载语义信息 可矩阵吸收,保持低秩压缩 位置分支(R) 直接从 生成并加 RoPE 不缓存 承载位置信息 采用 MQA 范式,维度很小(64)
-
-
MLA 的显存占用和 KV Cache 大小如何?
- 显存占用(以 DeepSeek-V2 为例)
- :维度 =512(低秩压缩向量,核心缓存)
- :维度 =64(共享位置分支,不缓存,动态生成)
- KV Cache 大小
- MLA 的 KV Cache 维度只跟潜在向量维度
d_c有关,跟注意力头数n_heads完全无关 - 普通 MHA / GQA / MQA 的 KV 维度都是头数 × 头维度,头越多,KV Cache 越大
- MLA 完全不一样:
- 所有头 共享同一个低维潜在向量 ,不管多少头,缓存的都是这个向量
- K 和 V 都是 从这个
c还原出来的,每个头用不同的投影矩阵从 里提取自己的 K/V - 缓存的只有这个
c,不存任何按头分开的 K、V
- MLA 的 KV Cache 维度只跟潜在向量维度
- 显存占用(以 DeepSeek-V2 为例)
-
MLA 的缺点是什么?
- 推理实现复杂
- MLA 不是标准 attention 结构,无法直接用 FlashAttention、FlashAttention-2、xFormers 等高度优化的核,必须自己写 双分支 QKV 构造 + 分拆注意力计算
- 推理引擎(vLLM、TGI、TensorRT-LLM)都要专门适配 MLA,原生不支持
- RoPE 必须解耦,不能简单套用
- 位置分支不缓存,每次都要重新计算,增加一点点推理延迟
- 计算量并没有减少,同时扩展性也不如 GQA/MQA 灵活,想微调精度 / 速度,只能改 (潜在维度),不如 GQA 直观
- 双分支 + 动态位置分支,访存模式更零散,对硬件不友好,老卡更慢
- 推理实现复杂
Tokenizer
- 有哪些分词器算法?各自的优缺点是什么?
- BPE(Byte Pair Encoding)
- 实现流程:
- 初始化词表:所有单个字符 + 基础符号
- 统计语料中相邻字符 / 子词对的出现频率
- 选择频率最高的子词对合并成新子词,加入词表
- 重复合并,直到词表达到预设大小
- 贪心合并,无概率建模,不一定最优
- 实现流程:
- WordPiece(BERT 所用)
- 实现流程
- 初始词表 = 所有单个字符
- 每次选择能最大程度提升语料似然概率的子词对合并
- 用 ## 前缀标记非词首的子词(如 playing → play ##ing)
- 按概率 / 似然合并,语义拆分更合理
- 单语言表现好,多语言较弱
- 实现流程
- Unigram LM(T5、Albert、部分日文分词)
- 实现流程:
- 从大词表(大量子词)开始
- 用 Unigram 模型计算每个句子的生成概率
- 计算去掉每个子词后对整体似然的损失
- 删除损失最小的一部分子词(如 20%)
- 反复裁剪,直到目标词表大小
- 基于概率的 Viterbi 分词,不是贪心,可输出最优拆分
- 概率建模,分词结果更优、更稳定,多语言效果也较好
- 训练比较慢,实现比较复杂
- 实现流程:
- SentencePiece(Google,常用于 LLaMA、Mistral)
- 不是新算法,是一体化实现工具,内置了各种分词算法实现
- 实现流程:
- 把文本当作 Unicode 字节流,不依赖空格分词
- 自动处理多语言、大小写、标点
- 用特殊符号▁表示空格,统一处理空格与子词
- BPE(Byte Pair Encoding)
- 词表的大小应该怎么选择?
- 通用原则:在覆盖度、粒度、计算开销之间做平衡
- 英文单语言:通常 32k ~ 64k 最优
- 多语言:一般 128k ~ 256k
- 中文:建议 40k ~ 80k,太小会切得过碎,太大冗余高
- 过小:序列变长、上下文利用率变低、信息密度下降
- 过大:embedding 层参数量暴涨、训练更难收敛、冗余子词多
- BPE 有哪些参数可以调整?
- vocab_size:目标词表大小
- min_frequency:合并的最低频率阈值,对于中文一般使用 0.995
- 什么是 OOV?分词器如何处理未登录词?
- OOV = Out-of-Vocabulary,未登录词:词表里不存在的词 / 符号
- 现代子词分词器几乎不会输出 <unk>,处理方式:
- 不断拆分成更小的子词,直到拆成单个字节
- 最终兜底是 UTF-8 字节级别的 token
- 旧式词表(全词分词):直接映射为 <unk>,信息完全丢失
- 结论:BPE/WordPiece/Unigram 理论上无 OOV,只有粒度问题
- 为什么中文分词比英文更难?对模型性能有什么影响?
- 英文天然有空格分隔单词,中文无显式边界
- 中文语义高度依赖单字组合,歧义多
- 字符集巨大,生僻字多,Unicode 复杂
- 分词不一致为什么会导致模型推理效果骤降?
- 训练与推理使用不同分词器 / 词表,token ID 完全不匹配
- 相同文本被切成完全不同的序列,语义分布与训练分布偏移
- 长文本场景下,分词粒度如何影响上下文长度利用率?
- 词表过大,稀有词、专业词、生僻字仍会被切碎,词表冗余高,embedding 负担大
- 词表过细,常用词也被切成碎片,序列长度急剧膨胀;同样 max_seq_len 能承载的语义内容大幅减少,长文本建模能力下降
- 常用词尽量成词,稀有词自动拆分,在相同长度下塞更多语义
- 词表大小如何影响显存、参数量、训练速度?
- 直接影响输入层和输出层的参数量,占用显存也会相应变化
- 前向 / 反向时 embedding 与 lm_head 计算量增加,词表过大明显拖慢训练与推理吞吐
Transformer
-
Transformer 的基本结构
- Transformer 的核心可以看成是「Attention + MLP」的堆叠
- 每一层通常包含两大块:Multi-Head Self-Attention 和 Feed-Forward Network(FFN),每个子层外面包一层残差连接,再加归一化(现在主流是 Pre-LN)
- Self-Attention 负责在序列维度上做信息交互,本质是让每个 token 根据内容去 “选择性读取” 其他 token;FFN 则是在 token 内部做非线性变换,相当于对每个位置做一个共享的 MLP,提升表达能力
- 整体结构其实非常 “干净”:没有卷积的局部性约束,也没有 RNN 的时间依赖,完全依赖 attention 做全局建模
-
为什么 Transformer 不用卷积 / RNN?
- inductive bias:模型 “天生自带” 的先验假设 / 偏好,决定了模型更愿意学什么样的函数,更不信什么样的函数
- 给模型一堆数据,理论上有无穷多种函数都能拟合这些数据,但模型会优先选某一类,这就是它的归纳偏置
- 有偏置 → 模型缩小假设空间,更快学到真实规律
- 归纳偏置 = 模型的 “先验世界观”
- RNN
- RNN 的问题本质是 “串行依赖”,它的归纳偏置是序列有序性和时序依赖,每一步都依赖前一步,导致无法高效并行
- 同时长序列上存在梯度消失 / 爆炸问题,虽然 LSTM/GRU 有缓解,但本质没变
- CNN
- 卷积的问题是 “感受野受限 + inductive bias 太强”,它的归纳偏置是局部性(相信附近的像素 / 特征关系更紧密)、权值共享(相信同一模式在不同位置都会出现)、平移不变性
- 虽然可以堆很多层扩大感受野,但远距离依赖建模仍然不如 attention 直接,而且卷积假设局部平移不变性,这对语言并不完全成立
- Transformer 的优势在于几乎没有强结构偏置,使用注意力建模 token 之间的关联,使用位置编码进行
- 第一,完全并行(序列维度可以一次性算)
- 第二,attention 天然是全局的
- 第三,表达能力更灵活,不强加局部或顺序 bias
-
对比一下 Batch Norm 和 Layer Norm
- Batch Norm(BN)
- 沿 batch 维度做归一化,对同一个特征通道、不同样本做标准化
- 均值方差在 (B, L) 上计算,对每个维度 d 独立归一化
- 训练时用 batch 统计量,推理时用训练时固定的滑动均值 / 方差
- 严重依赖 batch 内样本分布一致,且依赖 batch size,batch 越小,统计噪声越大,效果急剧下降
- 自带强正则化,依赖 batch 内样本间信息
- Layer Norm(LN)
- 沿 feature 维度做归一化,对同一个样本、不同特征通道做标准化
- 均值方差在 D 上计算,对每个样本 (B, L) 独立归一化
- LN 只依赖单样本,与 batch 无关,batch size 不影响效果
- 训练和推理计算方式完全一致,无滑动统计、无状态保存
- 正则化较弱,更侧重稳定梯度、加速收敛
- Batch Norm(BN)
-
Transformer 为什么使用 LN 不用 BN?
- BN 按批次归一,受 padding、小 batch、变长序列影响极大,NLP 不稳定
- LN 按单样本自身特征归一,不受批次和长度影响,训练推理一致
- Transformer 样本独立、全局注意力、小 batch 多,LN 更稳定、好训练
-
为什么用 Pre-LN 不用 Post-LN?为什么 Pre-LN 更稳定?为什么 Post-LN 不稳定?为什么 Post-LN 会梯度爆炸 / 消失?
- 结构对比
- Post-LN(原始 Transformer):x → 子层(Attn/FFN)→ 残差相加 → LayerNorm —— LN (x + f (x))
- Pre-LN(主流大模型:LLaMA、GPT 等):x → LayerNorm → 子层 → 残差相加 —— x + f (LN (x))
- 残差路径与梯度传播
- Pre-LN 的残差分支是纯恒等映射(identity path):梯度可以不经任何变换直接从顶层传回底层,路径干净、增益接近 1,让 f (x) 始终在稳定、标准化的特征空间内学习,输出幅值可控,从而使得深层网络也能保持梯度稳定,不容易消失或爆炸
- Post-LN 的残差相加后还要经过 LN,LN 会对张量做缩放与归一化,导致梯度在反向传播时被反复缩放、叠加放大 / 衰减,层数越深,梯度累积畸变越严重
- 梯度消失 / 爆炸(Post-LN)
- Post-LN 中,子层输出 f (x) 会直接累加到 x 上,再进入 LN,随着层数加深,f (x) 的累积幅值容易失控,LN 为了压制幅值会不断缩放,导致梯度被持续衰减 → 梯度消失
- 反之,若初始化不当,残差和幅值快速放大,经过 softmax 等模块会出现极端值,梯度被指数级放大 → 梯度爆炸
- 深层 Transformer 下,这种效应被逐层放大,训练极其不稳定,loss 容易震荡、NaN
- 结构对比
-
为什么用 RMSNorm 而不用 LayerNorm?为什么去掉 mean 只用 variance 就够?
-
公式对比
-
LayerNorm:先减均值,再除方差,含平移 + 缩放两步
-
RMSNorm:只做缩放,不移位,去掉均值
-
-
为什么去掉 mean 依然有效?
- RMSNorm 通过保持非零均值而不强制均值对零的对齐,有效缓解了梯度消失问题
- LayerNorm 的零均值对齐可能导致梯度在反向传播过程中逐层衰减
- 与 LayerNorm 相比,RMSNorm 省去了均值计算、平移操作,减少访存和算子,训练 / 推理速度提升
-
本质原因
- 归一化的核心作用是稳定特征幅值、防止梯度异常,而控制幅值只需要方差缩放即可
- LayerNorm 中的减均值在高维 Transformer 特征中是冗余操作,RMSNorm 保留核心、去掉冗余操作,更适合大规模深度模型训练
-
-
FFN 的作用是什么?
- Attention 负责在不同 token 之间交换信息、建立上下文关联,本质是对序列做加权融合,本身缺乏强非线性的表达
- FFN 则对每个 token 的特征独立地进行高维的映射与激活,为模型引入非线性表达能力,负责特征变换与模式拟合,提升表达上限
- 缺少 FFN 会导致模型拟合能力严重不足,难以学习复杂语言模式与语义知识
-
为什么现在主流模型都使用 Gated FFN(如 SwiGLU)?
-
门控 FFN 结构可统一表示为:
-
通过门控机制对不同特征通道做动态选择与加权,让模型自适应控制信息流通,比普通 ReLU/GELU FFN 表达更精细、效率更高
-
在相同参数量或计算量下,门控 FFN 效果显著优于传统 FFN,收敛更快且泛化更强,已成为 LLaMA、PaLM、GPT 等大模型标配
-
-
为什么要用残差连接?
- 残差的核心作用是提供一条恒等映射的直达路径(identity path),让信息和梯度可以无损穿过深层网络
- 梯度传播:反向时梯度能直接沿残差分支传回底层,避免逐层衰减或放大,有效缓解梯度消失与梯度爆炸
- 解决深层退化:没有残差时,网络越深训练误差反而越高,特征会被反复扭曲导致难以优化;残差让模型优先学习 “微小增量修正”,深层训练更稳定
- 对 Transformer 尤其关键:层数动辄几十上百层,没有残差连接几乎无法收敛,训练极易震荡、崩 loss
-
了解大模型的 Scaling Law(缩放定律)吗?Kaplan ?Chinchilla ?
- 什么是 Scaling Law:大语言模型性能(损失 / 准确率)与参数量 N、数据量 D、计算量 C 呈幂律(Power Law)关系,可预测、可外推
- 给定算力预算,Scaling Law 能够指导如何最优分配资源(模型大小 vs 数据量)
- Kaplan Scaling Law(OpenAI)
- 模型大小 > 数据量,算力应优先堆模型
- 幂律公式(损失 L 越低越好)
- (参数量)
- (数据量)
- (计算量)
- 最优分配(给定算力 C)
- ,
- 算力 ×10 → 模型 ×5.5,数据 ×1.8
- 理念:大模型数据效率更高,应做大模型、早停(不训到收敛)
- 影响:GPT-3(175B, 300B tokens)、早期大模型普遍参数量大、数据少
- Chinchilla Scaling Law(DeepMind)
- 模型与数据应等比例扩展(1:1),早期模型普遍欠训练
- 最优分配(给定算力 C)
- ,
- 算力 ×10 → 模型 ×3.2,数据 ×3.2
- 黄金比例:每 1 参数 ≈ 20 训练 tokens
- 验证:70B Chinchilla(1.4T tokens)= 280B Gopher 同算力,全面更强
- 影响:LLaMA 系列、Llama 3、GPT-4 等均遵循小模型 + 多数据
-
了解 Bert 模型吗?它和 Transformer、GPT 模型有什么区别?
- Bert 是 Transformer Encoder 结构的模型,采用了双向 Transformer Encoder 堆叠
- 预训练任务是 MLM(Masked Language Model)掩码语言模型和 NSP(Next Sentence Prediction)下一句预测
- Bert 模型和 GPT 模型的区别
- Bert 没有因果掩码,能看到完整上下文;GPT 带因果掩码,只能看到当前及左边 token,看不到未来
- Bert 更擅长理解类任务:文本分类、情感分析、语义相似度、命名实体识别、抽取式问答,需要针对任务设计头部并微调
- GPT 更擅长生成类任务:对话、续写、创作、摘要、翻译、代码生成,更适合零样本 / 小样本提示学习
- Bert 的设计细节
- 最终输入向量 = Token Emb + Segment Emb + Position Emb
- Token Embedding:用 WordPiece 分词,包含 [CLS]、[SEP]、[MASK]、[UNK]、[PAD] 等特殊 token
- Segment Emedding:只有 0 / 1 两种向量,用于区分两句话(NSP、QA、推理任务)
- Position Embedding:可学习参数(非正弦),最大长度 512(BERT 上限),位置从 0 开始([CLS]=0)
- [CLS] = Classification Token
- 固定在序列第 0 位,无实际语义,专门用于句子级表示
- [CLS] 能 Attend 到所有 Token(双向);在预训练时,
[CLS]输出接二分类层做下一句预测,从而强制学习全局语义用于 NSP 任务 - 文本分类:取最后一层
[CLS]→ 全连接层 → Softmax - 句对关系(NLI/QA):
[CLS]表示两句话整体关系 - 命名实体识别:不用
[CLS],用每个 token 输出 - 语义相似度:常用
[CLS]或 均值池化(Mean Pooling)
- [SEP]
- 句子边界标记,帮助模型区分句 A / 句 B
- [SEP] 只用于标记边界,不标记 token 归属;因此需要使用 Segment Embedding 告诉模型每个词属于哪一句
- 同时,注意力机制是全局的,没有边界符号,模型会把两句话混在一起理解,因此也必须需要 [SEP]
-
什么是 Temperature
-
Temperature(T)是用来控制概率分布 “陡峭 / 平坦” 的参数:
- T 越小 → 分布越陡 → 模型越自信、越 deterministic、越重复
- T 越大 → 分布越平 → 模型越随机、越多样、越容易胡说
-
模型最后输出 logits(未归一化分数),加 Temperature 后变为
-
即把所有 logits 除以 T,再做 Softmax
-
可见,T 越小趋近于 0,分布会越尖锐,经过 Softmax 后会指数爆炸,从而每次都选概率最高的词,确定性高
-
T 大于 1 时,分布越平滑,概率被拉平,低概率词也容易被选中,具体表现是创意强、发散、容易乱说话、语法错
-
Position Encoding
-
原始 Transformer 用的是什么位置编码?有什么缺点?为什么外推性不好?
-
使用的正余弦位置编码,公式为
-
位置编码直接加在嵌入向量上,经过注意力计算的推导如下:
-
关注两个特定位置 和 之间的注意力分数,则有
-
由此可见,位置编码在进入 attention 层后,内积的距离意识的模式遭到了破坏
-
外推性不好的原因:正余弦编码基于固定三角函数生成,训练时仅学习了指定长度序列的位置分布,当输入序列长度超过训练最大长度时,超出部分的位置编码未在训练中见过,无法被模型适配,会导致注意力权重计算异常,模型性能大幅下降
-
-
为什么 Transformer 必须加位置编码,CNN/RNN 不需要?
- Transformer 基于自注意力机制,本身不具备序列顺序感知能力,自注意力计算会平等处理所有位置的 token,无法区分序列的先后顺序,必须通过位置编码注入位置信息
- CNN 通过卷积核的滑动窗口天然捕捉局部位置关系,卷积操作自带空间位置感知特性
- RNN 按序列顺序逐词迭代处理,输入顺序直接决定计算流程,天然保留时序位置信息
-
介绍下可学习位置编码(Bert)?为什么外推性不好?
- 可学习位置编码是将位置信息初始化为随机向量,随模型训练同步更新优化,Bert 中直接将位置嵌入向量与词嵌入向量逐元素相加,位置向量的维度与词嵌入维度一致
- 外推性不好的原因:编码长度在模型初始化时固定,训练时仅学习了预设长度内的位置向量,当输入序列超出该长度时,没有对应的位置向量可使用,无法直接生成新位置的有效编码,导致模型无法处理超长序列
-
相对位置编码与绝对位置编码的核心区别与优劣?
- 核心区别
- 绝对位置编码:给每个位置 idx 分配一个固定 / 可学习的向量,表示 “这个 token 在序列的第几个位置”,模型学习的是绝对位置信息
- 相对位置编码:不关心具体在第几位,只关心两个 token 之间的距离,注意力权重由相对距离决定,与绝对位置无关
- 绝对位置编码(原生正弦、BERT 可学习)
- 优点:实现简单,直接相加即可;短上下文下位置信息清晰,拟合速度快;与模型结构兼容性好
- 缺点:外推性极差,超过训练长度后无对应编码可用;位置信息与语义耦合,长序列容易混乱;无法自然表达相对距离关系
- 相对位置编码(Transformer-XL、ALiBi、RoPE 类)
- 优点:天然具备外推能力,超长序列仍可计算相对距离;注意力更关注局部与相对关系,长文本更稳定;不受固定位置上限限制
- 缺点:实现更复杂,需要修改注意力计算;部分相对编码会增加计算量;在极短序列上未必比绝对编码更优
- 核心区别
-
ALiBi 位置编码原理,为什么不用显式嵌入也能做外推?
-
ALiBi(Attention with Linear Biases)不修改 token embedding,也不使用显式位置向量,而是直接在注意力分数中加入距离惩罚:
- i 为当前 token 的位置
- j 为被关注的 token 的位置
- 为第 h 个注意力头的固定斜率(不同头使用不同斜率)
-
该设计使得:
- 距离越远,惩罚越大,注意力权重越小,模型天然偏向关注局部上下文
- 不引入额外位置向量,能够在训练长度之外自然外推,可用于长序列建模
-
对于任意一对位置 (i,j),ALiBi 只关注它们的相对距离 |i−j|,并对注意力得分施加线性、无参数增长的惩罚
-
ALiBi 为每个注意力头分配不同的线性斜率(H 是注意力头个数):
- 低序号头 (h 小):衰减快,偏向捕捉局部依赖
- 高序号头 (h 大):衰减慢,偏向捕捉长距离依赖
- 这种设计使多头注意力在序列长度上天然分工,提高模型对不同范围依赖的建模能力
-
-
RoPE 编码的原理?为什么能编码相对位置?
-
在正余弦位置编码中提到
-
由于 是一个表示顺时针旋转的正交矩阵(不改变向量的模长,只改变方向)
-
则 其实就是以 为基础,顺时针旋转 角度而来,因此有
-
固定某个 不变,慢慢增大 时,上式变小,因此相距较远的两个位置编码的内积越小,即内积可以用于反馈两个位置向量在绝对位置上的远近
-
RoPE(Rotary Position Embedding)把每个 token 的表示按维度两两分组,当成复数:
-
对第 个位置,引入一个角度 ,做旋转:
-
展开成实数就是:
-
关键在 attention 的内积:
-
代入旋转:
-
内积变成:
-
attention 的结果只依赖相对位置差 ,而不是绝对位置 —— 这就是 RoPE 能编码相对位置的本质
-
-
RoPE 和正余弦位置编码有什么不同
-
传统 sinusoidal PE:
-
问题是位置是 “加进去” 的(additive),attention 内积变成:
-
会混杂内容和位置,无法干净表达相对位置
-
而 RoPE 位置是 “乘进去”(旋转),attention 内积天然变成下式,更干净、更结构化
-
-
RoPE 的代码实现
import torch import torch.nn as nn def rotate_half(x): # 拆分偶数/奇数维度,构造旋转 x1, x2 = x[..., ::2], x[..., 1::2] return torch.cat([-x2, x1], dim=-1) def apply_rotary_pos_emb(q, k, cos, sin): # 核心:旋转公式 (a*cos - b*sin, a*sin + b*cos) q = (q * cos) + (rotate_half(q) * sin) k = (k * cos) + (rotate_half(k) * sin) return q, k class RotaryEmbedding(nn.Module): def __init__(self, dim, base=10000): super().__init__() self.dim = dim self.base = base # 预计算 theta = 10000^(-2i/d) inv_freq = 1.0 / (base**(torch.arange(0, dim, 2).float() / dim)) self.register_buffer("inv_freq", inv_freq) def forward(self, seq_len): # 生成位置序列 0,1,2...seq_len-1 t = torch.arange(seq_len, device=self.inv_freq.device) # 外积得到 m*theta freqs = torch.einsum("i,j->ij", t, self.inv_freq) # 拼接成 [cos,cos,...] [sin,sin,...] emb = torch.cat((freqs, freqs), dim=-1) return emb.cos(), emb.sin() # ========== 使用示例 ========== if __name__ == "__main__": head_dim = 64 # 每个头的维度 rope = RotaryEmbedding(head_dim) q = torch.randn(1, 10, 128) # [batch, seq, dim] k = torch.randn(1, 10, 128) cos, sin = rope(10) q_rot, k_rot = apply_rotary_pos_emb(q, k, cos, sin) print("RoPE 编码完成")- 其中,cos/sin 是预先根据位置算好的:
rotate_half:将向量拆分为偶数 / 奇数维度,构造旋转分量apply_rotary_pos_emb:实现复数旋转的实数形式运算- 预计算
cos/sin表,推理时直接查表,速度极快
-
RoPE 为什么能外推(extrapolation)?
-
模型训练时用 2k 序列长度,推理时直接输入 4k/8k 长度,这就是外推
-
RoPE 不是 learned embedding,而是一个函数:
-
所以即使训练只见过 ,推理也可以用 ,理论上函数是连续的,可以外推
-
-
为什么 RoPE 在长序列时外推又会崩溃?
-
为什么还要 NTK scaling / Yarn?RoPE 的线性 scaling 和 NTK scaling 的不同?线性 scaling vs NTK scaling 本质区别?
-
上述改进的本质目标都是让 RoPE 在长序列下 “频率变慢”,避免:
-
最简单方法是线性 scaling,拉伸旋转角度,让模型把长序列当成短序列看
-
相当于:
-
其效果是所有频率统一变慢,简单粗暴;问题在于破坏了绝对位置精度,远距离能区分了,但近距离位置编码变粗糙,长文本效果一般
-
NTK scaling 的核心思想是不同频率缩放不同:
-
NTK 既拉伸低频维度(保证远距离区分),又保留高频维度(保证近距离精度),利用神经网络的 NTK 无限宽特性,实现无训练外推
-
线性 scaling 压缩位置坐标,而 NTK scaling 重新映射频率空间
-
-
RoPE 的改进版本 Yarn-RoPE 的原理?为什么更稳定?
-
NTK Scaling 仍有问题,长序列下向量范数失衡(旋转导致向量模长变化)、注意力分数分布偏移、极端长度(8k+)效果下降
-
YaRN(Yet another RoPE extension)核心思想是分段控制频率 + 插值,而不是整体缩放,其同时解决两个问题
- 频率外推(用 NTK 思路)
- 向量范数校正(新增衰减因子,保持向量长度稳定)
-
核心公式
-
其中,g (m) 是位置相关的衰减因子,保证长距离下向量范数不爆炸、不消失
-
低频保持,高频压缩:类似 NTK scaling,但更平滑
-
位置插值(position interpolation):把长序列映射回训练区间
-
Yarn 保留 NTK 的频率外推能力,并新增范数约束,让注意力分布和训练时一致
-
支持无微调直接扩展到 32k+ 序列,是目前长文本大模型的最优方案
-
-
总结
- RoPE 的本质是用复数旋转把位置编码进向量,使 attention 内积自然变成相对位置函数
- 但它的频率是指数分布的,在长序列下高频维度会发生 alias,导致外推失败
- NTK scaling 和 YaRN 的核心目标都是 “减慢高频旋转”,区别在于线性 scaling 直接缩位置,而 NTK/YaRN 通过调整频率分布来更好地保持原有 attention kernel,因此更稳定
MoE
-
介绍什么是 MoE 模型?稀疏模型与稠密模型的对比和优缺点?
- MoE 也即 Mixture of Experts,混合专家模型
- 核心思想是一个 Transformer 层里不只用一个 FFN,而是设置多个 “专家网络”(Expert),每个 token 只被部分专家处理
- 用稀疏激活的方式,实现在不显著增加单步计算量的前提下,大幅扩大模型总参数量
- 工作流程
- 每个 token 经过一个门控网络(Router/Gating Network)
- 门控为每个专家打分,选择分数最高的 k 个专家(通常 k=1 或 k=2)
- 该 token 只被这 k 个专家进行前向计算
- 对专家输出按门控分数加权求和,作为该层最终输出
- 不同 token 可以被分配到不同专家,实现负载分流
- 为什么会被广泛使用?
- scaling 效率极高:总参数量可轻松破万亿,但每步计算量接近稠密小模型
- 效果提升显著:更多专家对应更强的特征提取与知识存储能力
- 训练成本可控:同等参数量下,计算成本远低于全稠密大模型
- 适合多语言、多任务、长文本:不同专家可专门化学习不同领域 / 模式
-
MoE 怎么做负载均衡的?为什么会不均衡?
-
门控网络(gating)天然倾向于给少数高分专家发 token
-
模型为了 loss 下降快,会学会只激活 1~2 个 “超级专家”
- 其他专家永远收不到 token → 不更新 → 废掉
- 最终:专家利用率极低,性能崩塌
-
均衡辅助损失(Aux Loss):直接在门控输出上加损失,强制让每个专家分到的 token 数量接近,让所有专家的平均概率
-
Top-K 随机平滑:选专家时加一点噪声,避免模型永远只选固定专家
-
Expert Capacity(专家容量上限):强制每个专家最多收 N 个 token,溢出就丢给其他专家 / 共享专家
-
-
DeepSeek 的辅助损失是怎么做的?
-
计算公式
-
:第 i 个专家被选中的概率
-
:第 i 个专家实际收到的 token 占比
-
:平衡系数(一般 0.01~0.02)
-
让 “被选中概率高” 的专家,真的拿到 “对应数量的 token” → 防止门控乱打分,防止某些专家永远不工作
-
比普通均衡 loss 更稳定,让 MoE 训练不塌陷、专家利用率 >90%
-
-
MoE 激活参数量如何计算的?主流大模型的 MoE 命名是什么意思?
-
计算公式
激活参数量 = 专家数量 × 每个专家参数量 × 每个token选的专家数(K) -
总专家:16 个、每个专家:2048×5440(FFN)、每个 token 选 2 个专家、激活参数量 = 16 × FFN × 2 / 16 = 2×FFN
-
MoE 总参数大,但激活参数 = K 个稠密 FFN,推理速度 ≈ 稠密小模型
-
-
MoE 为什么难训练?MoE 为什么 MFU 低?
- 难训练主要因为专家负载不均、门控路由不稳定、梯度容易碎片化,且辅助损失与负载均衡约束难调,还容易出现部分专家闲置或过拟合,同时多专家并行还会依赖大量的 all2all 通信
- MFU 低是因为显卡在等通信,没在计算矩阵,MoE 并行会引入大量的 all-to-all 通信,开销巨大;MoE 算力利用率通常只有 20%~40%,稠密模型 50%~70%
-
为什么 MoE 适合大模型 scaling?
- 能在不显著增加单步计算量的前提下大幅扩大参数量,用更低算力成本实现能力提升
- 稠密模型:参数翻倍 → 训练 / 推理成本翻倍
- MoE:总参数翻倍,但激活参数不变 → 成本几乎不涨
- 能轻松做到 70B/140B/280B 规模,推理却像 7B/13B 一样快
-
为什么有的模型会设置一个共享专家?
- 在 MoE 模型里,每一层除了自己的 N 个本地专家(Local Experts),还共享一个全局共享的 FFN 层,所有层都能调用它
- 主要负责承接 overflow 溢出的 token(专家满了就丢这里,不丢信息),提升模型稳定性,防止专家塌陷,让模型基础语义能力更强
- 解决 Expert Capacity Overflow
- 解决 MoE 训练塌陷:本地专家可能躺平,但共享专家永远被激活,保证基础表达能力
- 提升泛化性:共享专家学习通用语言模式,而本地专家学习细分领域 / 模式
-
MoE 是 compute-bound 还是 communication-bound?
- 现代 MoE 100% 是 Communication-bound(通信受限)
- 矩阵计算很快,但 All-to-all 通信极慢,通信占比 50%~70%,因此优化 MoE 性能 = 优化通信
-
expert capacity overflow 怎么处理?
- 直接丢弃(效果差)
- 送到共享专家(shared expert)(最常用)
- 送到本轮分数第二的专家
- batch 内排队 / 累积到下一个 token
- 主流方案:所有溢出 token → 共享 FFN 专家,不影响速度,不损失精度,最稳定
-
如果你的框架里要支持 MoE,怎么设计并行,并且怎么 overlap all-to-all?
- MoE 的核心问题在于稀疏计算和专家分布,每个 token 只经过少数几个专家,而不同专家可能在不同 GPU 上
- 为了充分利用显存和计算资源,框架设计通常需要将 MoE 并行拆分成几个层次
- 数据并行(DP)负责整体 batch 分割和梯度同步
- 专家并行(EP)负责每个专家在不同 GPU 上的计算分布
- 张量并行(TP)仍然用于每个专家内部的矩阵计算加速
- 在实现上,最关键的性能瓶颈是 All-to-All 通信,因为每个 GPU 上的 token 需要发送到对应专家所在的 GPU
- 为了减轻 All-to-All 的阻塞,可以通过通信 - 计算重叠来优化:在发送数据的同时先对本地 token 进行前向计算或部分后向计算,使用异步通信(比如 NCCL 的 non-blocking send/recv)和流水线式的 tensor chunk 分块传输,将通信时间和计算时间尽量重叠,从而减少 GPU 空闲等待
- 总之,MoE 的并行设计不仅要考虑计算负载平衡,还要精细调度 All-to-All,确保通信不会成为瓶颈
-
MoE + pipeline 怎么调度?
- MoE 模型往往非常深,因此经常和流水线并行(PP)结合
- 调度的关键在于 token 在 pipeline stage 和专家之间的流动
- 在标准 pipeline 并行中,每个微批次在不同 stage 上按顺序流动,而 MoE 会在某些 layer 内产生 All-to-All 分布,这会打乱原本流水线的顺序
- 解决方法是采用 “微批次拆分 + 动态调度”:将每个微批次分成若干小 chunk,使得一部分 token 在 stage 1 前向计算时可以异步发送到专家所在 GPU,而 stage 2 的 GPU 可以同时处理上一批次的其他 token
- 这样,pipeline stage 之间不会因为 MoE 的 All-to-All 而完全阻塞,同时可以通过 1F1B 或 Interleaving 等调度策略进一步减少 pipeline bubble
- 设计时还需要考虑专家数量和容量,保证每个 pipeline stage 的负载均衡,否则某个 stage 等待 All-to-All 过慢会拖慢整体流水线
-
expert parallel 和 TP/DP 怎么组合?
- 在大规模 MoE 系统中,专家并行(EP)和张量并行(TP)、数据并行(DP)需要合理组合
- 一般逻辑是,DP 先切分 batch,把不同微批次分给不同 GPU 节点;EP 切分专家,把同一 layer 的不同专家分布在不同 GPU 上;TP 则用于每个专家内部的矩阵计算加速
- 组合时的关键原则是 “通信最小化”:DP 主要做梯度同步,EP 主要做 All-to-All token 分发,TP 只在每个专家内部做张量拆分计算
- 为了保证效率,需要在计算图中明确依赖关系,将 TP 计算和 EP 的 All-to-All 尽量重叠,同时在 DP 维度做梯度通信的重叠
- 这样可以在保持高 MFU 的同时充分利用 GPU 显存,避免单一维度成为瓶颈
- 最终设计通常是 “DP × EP × TP” 的三维并行结构,每个维度负责不同层次的并行优化,确保 MoE 层既能稀疏高效计算,又能和整体模型训练流水线无缝衔接
Multi-Modal
ViT
-
简单介绍 Vision Transformer(ViT)的整体结构
- ViT 是 Encoder-only 结构,和 BERT 架构高度相似,核心流程:
- 图像分 Patch:把 2D 图像切成固定大小的小 Patch,作为视觉 Token
- 线性投影 + 加入 Class Token:将每个 Patch 映射为隐向量,并额外添加一个可学习的 class token
- 加入位置编码:给序列注入空间位置信息
- 堆叠 Transformer Encoder:多层 Pre-LN + MSA + MLP + 残差连接
- 分类输出:取 class token 对应的最终特征,经过线性层 + Softmax 完成分类
-
ViT 是如何把图像转换成序列输入 Transformer 的?
- 切 Patch:输入图像 H×W×C,按 P×P 大小切分成不重叠 Patch,共 个 Patch
- 展平 + 线性投影:每个 Patch 展平为 维向量,再通过可学习矩阵 E 投影到 D 维隐空间,得到 N 个 D 维 Token
- 添加 Class Token:在序列最前面拼接一个可学习的 class token,序列长度变为 N+1
- 加入位置编码:加上可学习 1D 位置编码,最终得到 (N+1, D) 的序列,送入 Transformer Encoder
- 实际实现常用卷积等价实现:用 P×P、stride=P 的卷积核直接得到 Patch Embedding
-
ViT 中的 class token 有什么作用?可以去掉吗?
- 类比 BERT 的 class token,作为全局特征聚合器,在自注意力中与所有 Patch Token 交互,最终用它代表整张图的全局语义
- 方便直接接分类头,结构简洁统一
- 去掉 class token 后,可以对所有 Patch Token 做平均池化 / 最大池化得到全局特征,但原始 ViT 设计保留 class token,训练更稳定,效果更易对齐
-
ViT 的位置编码有哪些方式?可学习位置编码和正弦位置编码区别是什么?
- 常见编码方式
- 无位置编码:性能大幅下降
- 1D 可学习位置编码:ViT 原生方案,与 BERT 一致
- 2D 可学习位置编码:分别学习行、列位置再拼接
- 相对位置编码 RPE:在 Attention 里加相对距离偏置
- ViT 选择可学习 1D 位置编码
- 常见编码方式
-
ViT 相比 CNN 有哪些优势和劣势?
- 优势
- 全局感受野:自注意力直接建模全局依赖,远超 CNN 局部卷积
- 更强表达能力:无手工归纳偏置,大数据下拟合能力更强
- 灵活架构:易于扩展到多模态、大模型、检测分割等任务
- 动态权重:注意力权重随内容自适应,而非固定卷积核
- 劣势
- 计算量大:自注意力 ,高分辨率代价极高
- 缺乏天然归纳偏置:无局部性、平移等变性,小数据易过拟合
- 对位置编码敏感:分辨率变化需要插值处理
- 训练更不稳定:依赖更强优化、更大 Batch、更长训练
- 优势
-
ViT 在小数据集上表现为什么不如 CNN?
- CNN 自带强图像归纳偏置,而 ViT 没有
- CNN 天然满足空间局部性 + 平移等变性,先验与图像高度匹配
- ViT 完全靠数据学习结构,小数据下无法学到合理的空间关系与局部模式
- 注意力容易学到无意义的全局关联,泛化远差于 CNN
-
为什么 ViT 需要大量数据训练?
- ViT 缺少图像先验,所有结构信息(局部、边缘、纹理、全局关系)都必须从数据中学习
- Transformer 参数量大、表达能力强,小数据极易过拟合
- 只有在大规模数据下,才能让注意力学到合理的空间关联与语义依赖,弥补归纳偏置不足
-
ViT 的计算复杂度是多少?和图像分辨率、patch 大小的关系?
-
自注意力复杂度
-
N 是序列长度,D 是隐层维度,与图像分辨率 H×W 成正比
-
与 Patch 大小 成反比:P 越大,N 越小,计算量急剧下降
-
-
ViT 的多头注意力在视觉任务上有什么特点?
- 不同头会学到不同粒度的依赖:有的关注局部纹理,有的关注全局结构
- 注意力矩阵呈现结构化模式:对角附近强(局部),远距离弱
- 相比 CNN,能动态建模长距离依赖,比如跨区域物体关联
- 早期层关注局部,深层关注全局语义,类似 CNN 层级特征
-
介绍 DeiT、Swin Transformer 相对于 ViT 的改进点
- DeiT(Data-efficient Image Transformer)
- 解决 ViT 数据低效问题,不用 JFT 也能在 ImageNet 训好
- 引入蒸馏 token,用 CNN 教师模型监督训练
- 更强训练策略:增强、优化器、正则化更精细
- 更小模型更快,更适合落地
- Swin Transformer
- 窗口注意力 + 移位窗口,把复杂度从 降到
- 层级特征金字塔:类似 CNN 下采样,多尺度特征,适合检测 / 分割
- 天然具备局部性先验,小数据表现远好于 ViT
- 成为视觉 Transformer 落地主流 backbone
- DeiT(Data-efficient Image Transformer)
-
Swin Transformer 的窗口注意力、移位窗口是怎么实现的?
- 窗口注意力(Window Attention)
- 将特征图划分为不重叠窗口,只在窗口内算注意力
- 复杂度从全局 → 窗口内 ,大幅降低
- 移位窗口(Shifted Window)
- 下一层将窗口平移半窗,让相邻窗口信息交叉
- 用 mask 注意力避免无效区域计算
- 交替使用普通窗口 + 移位窗口,实现跨窗口信息流动
- 窗口注意力(Window Attention)
-
ViT 为什么能更好地建模长距离依赖?
- CNN 靠堆叠卷积 + 池化扩大感受野,是间接、渐进式的长距离建模
- ViT 自注意力每一层都能直接连接任意两个 Patch,是真正全局建模
- 无论物体在图中距离多远,注意力都能直接建模相关性,尤其适合大目标、稀疏目标、跨区域语义关联
-
ViT 做分类、检测、分割分别需要怎么修改结构?
- 分类(原生):加 class token → 取 class token → 线性层分类
- 检测
- 去掉 class token,使用所有 Patch Token 作为特征点
- 接入 FPN / RetinaNet 式检测头或用 DETR 式端到端检测,直接用 Transformer 输出预测框
- 分割
- 对所有 Patch Token 上采样恢复分辨率
- 接逐像素分类头(如 UPerNet、FCN 头)
- 结合层级特征(如 Swin)效果更好
CLIP
-
简单介绍 CLIP 的训练流程和核心思想
- CLIP 是 OpenAI 提出的双塔对比学习多模态模型,通过海量弱监督 <图像,文本> 数据,把图像和文本映射到同一个语义特征空间,实现跨模态对齐,从而支持零样本图像分类和图文检索
- 训练流程
- 构建双塔:图像编码器 + 文本编码器,分别提取特征
- 投影 + L2 归一化,把两种特征映射到统一空间
- 计算一个 batch 内所有图像 - 文本对的相似度矩阵
- 使用对称对比损失,让对角线上的正样本对相似度更高,非对角线负样本更低
- 预训练完成后,无需微调即可做零样本分类和检索
-
CLIP 的预训练任务是什么?对比学习目标是什么?
- 预训练任务
- 任务:图像 - 文本对比匹配任务
- 输入:一个 batch 内 N 对 <图像,文本>
- 目标:对任意图像,找出其对应的正确文本;对任意文本,找出对应的正确图像
- 对比学习目标
- 拉近匹配对(正样本)的特征距离,推远不匹配对(负样本)的特征距离
- 最终学到一个共享语义空间,语义相似的图文在空间中相近
- 预训练任务
-
CLIP 中图像编码器和文本编码器分别用了什么结构?
- Text:采用 GPT-2 结构(Transformer Decoder),取 [EOS] 位置的输出作为文本全局特征
- Image:支持 ResNet 和 ViT,通常取
token输出作为图像全局特征
-
CLIP 的损失函数是什么?为什么要用对称对比学习?
- 对称双向交叉熵损失(对称 InfoNCE)
- 按行:图像检索文本的交叉熵,按列:文本检索图像的交叉熵,两者平均作为总损失
- 通过对称对比学习,保证图文双向对齐 —— 图像能找到文本,文本也能找到图像,避免某一模态特征主导,让两个编码器学习更均衡
-
InfoNCE loss 和交叉熵损失的区别
- InfoNCE:专门用于对比学习,本质就是在一个包含正样本 + 大量负样本的集合上做交叉熵,目标是让正样本概率最大,负样本被抑制
- 交叉熵:更通用的分类损失,不一定带对比学习的负样本构造逻辑
- CLIP 的损失 等价于对称的 InfoNCE,只是在实现上直接用标准交叉熵表达
-
CLIP 的 temperature 参数有什么作用?
-
相似度 logits 计算:
-
缩放相似度分布,控制 “锐度”
-
越大,相似度被放大,分布更陡峭,正样本更突出
-
越小,分布越平滑,梯度更稳定
-
是可学习参数,自动优化正负样本区分度
-
-
CLIP 是如何实现零样本分类(Zero-shot Classification)的?
- 构造类别文本:对每个类别用 prompt 模板,如
A photo of a {class}.,输入文本编码器得到类别文本特征 - 图像编码:输入图片 → 图像编码器 → 图像特征
- 相似度匹配:计算图像特征与所有类别文本特征的余弦相似度,最高的即为预测类别
- 构造类别文本:对每个类别用 prompt 模板,如
-
CLIP 的相似度是怎么计算的?余弦相似度还是点积?
- 本质是余弦相似度,但实现上用点积
- 图像、文本特征都做了 L2 归一化,归一化后的向量点积 = 余弦相似度
-
CLIP 为什么能具备很强的泛化能力?
- 训练数据极其广泛:4 亿 <图像,文本> 对,覆盖海量场景
- 学习的是通用语义对齐,不是固定类别分类边界
- 无人工标注类别,避免过拟合到特定数据集标签体系
- 文本侧是自然语言,自带丰富语义先验,能泛化到未知类别与分布偏移场景
-
CLIP 的优缺点分别是什么?
- 优点
- 支持零样本图像分类,泛化强、鲁棒性好
- 弱监督训练,不需要精细标注
- 架构简单双塔,易扩展、易复用
- 成为视觉生成模型、多模态检索的基础基座
- 缺点
- 零样本 ImageNet 精度不如有监督 SOTA
- 模型规模大,训练成本极高
- 缺乏逻辑推理(计数、复杂纹理弱)
- 对极端分布偏移泛化有限(如 MNIST 表现一般)
- 只能判别匹配,不具备生成能力
- 存在数据偏见与刻板印象
- 优点
-
CLIP 训练时的 batch size 对效果有什么影响?
- batch 越大,负样本越多,对比学习信号越强
- 负样本更丰富,模型更难 “偷懒”,学到更精细的语义对齐
- CLIP 本身就是大 batch 友好型模型,大 batch 显著提升性能
-
CLIP 存在哪些 bias 或局限性?
- 数据偏见:从互联网爬取数据,带有人群、性别、文化刻板印象
- 泛化上限有限:极端分布偏移(如手绘、简笔画)效果下降明显
- 不支持开放词汇生成:只能从给定标签里选,不能自由描述
- 无推理能力:不会计数、不会复杂逻辑理解
- 零样本精度不如有监督模型
- 训练成本极高,难以复现
-
介绍几个基于 CLIP 的改进工作(如 BLIP、ALIGN、FLAVA 等)
-
CLIP 能不能直接用于生成任务?为什么?
- 不能直接用于生成,CLIP 是判别式模型,只做图文特征对齐与相似度计算
- 没有解码器、没有生成式架构,无法从文本生成图像,也无法从图像生成描述
- 视觉生成模型(Stable Diffusion、DALL・E)是用 CLIP 做文本编码器,但自身另有生成网络
VLM
-
多模态模型的几种范式
阶段 代表模型 核心结构 训练方式 优势 第一代 CLIP、BLIP、FLAVA、SigLIP 双编码器(图像 + 文本) 对比学习 / 掩码重建 / 多目标预训练 简单、零样本强、检索效果好 第二代 LLaVA、GPT-4V、BLIP2、Qwen-VL 视觉编码器 + Projector + LLM 冻结主干 + 轻量适配器微调(PEFT 等) 推理强、指令遵循好、易落地 第三代 Emu3、LLaMA 4、CM3leon、Chameleon 统一 Token + 单 Transformer 端到端自回归生成式预训练 对齐好、生成强、多任务统一 -
什么是多模态对齐?CLIP 是怎么做模态对齐的?
-
对比学习和监督学习在多模态预训练中的区别?
-
多模态模型常见的预训练任务有哪些?
-
图文检索的评价指标有哪些?
-
为什么 CLIP 这类模型不适合做细粒度识别?
-
多模态融合有哪些方式?
-
RL 如何与多模态模型结合(如多模态 Agent 的决策优化)
Visual Generation
- 视觉生成模型的一般流程
- 文本编码器:CLIP/T5 text encoder 把 prompt 变成条件特征
- VAE(变分自编码器):负责把图像压缩到低维隐空间
- UNet / DiT(核心生成网络):接收噪声隐变量 + 时间步 + 文本条件,预测噪声
- 扩散过程:前向给图像逐步加高斯噪声,反向从噪声逐步去噪生成图像
- 视觉生成模型的理论基础演变
- DDPM:离散马尔可夫链
- Score-SDE:连续随机微分方程
- Probability Flow ODE:SDE 的确定性等价(去随机)
- Flow Matching:直接 ODE + 最优传输 + 闭式目标
- Rectified Flow:拉直路径 → 超快采样
- 视觉生成模型的训练难点
- 模态对齐困难,文本条件控制(prompt 跟随)较弱
- 计算量巨大、显存爆炸:图像是高维数据(哪怕 latent 依然很大),时序扩散要走几十上百步
- 视觉生成模型训练 vs LLM 训练
- 数据空间不同:LLM 是 1D 离散 token 序列,视觉生成模型是连续稠密像素 / 隐变量(2D/3D / 时空)
- 目标函数不同:LLM 是下一个 token 的分类交叉熵损失,视觉生成模型是扩散去噪损失(预测噪声)/ MSE 为主
- 结构归纳偏置不同:LLM 是纯 Transformer,依靠自回归和注意力建模序列依赖;视觉生成模型早期依靠 UNet 的强图像先验,现在 DiT 仍需要位置、时间、条件编码
- 显存与计算压力不同:LLM 以矩阵乘法为主,视觉生成模型参数量不一定大,但是特征图巨大、时空维度高,显存更紧张
- 并行策略不同:LLM 以 TP/DP/PP 为主,而视觉生成模型更依赖空间并行、模型并行、微批次,对通信优化要求极高
- 视觉生成模型训练 vs LLM 的强化学习训练
- LLM
- 让模型输出更符合人类意图或偏好,或者提升模型的推理能力
- LLM 的 RL 是序列决策问题:一步步生成 token,每一步都影响最终结果,靠策略梯度调整分布
- 视觉生成模型 / 扩散模型
- 让图更好看、更清晰、细节更足,更遵循文本提示(prompt alignment),构图、人体、手部、脸部更合理,减少畸形、扭曲、崩坏
- 典型做法
- Reward 引导扩散(CLIP reward、美学 reward、人脸检测 reward)
- Diffusion RL / DreamBooth + RL / 可控性优化
- 直接在去噪过程中梯度上升提升奖励分数
- 主要特点
- 动作空间:连续的隐变量 z / 噪声预测
- 奖励:CLIP score、FID、美学模型、人脸检测器、手部检测器
- 优化方式:引导去噪方向,而不是更新整个策略分布
- 训练比 LLM 的 RL 稳定得多
- 扩散模型的 RL 不是 “序列决策”,而是连续优化 + 引导式去噪,每一步去噪都可以注入奖励梯度,把图往 “更好看、更对齐” 的方向拉
- LLM
- 了解过视觉生成模型的 RL 训练吗
- DDPM 和 DDIM 的区别
- DDPM:Denoising Diffusion Probabilistic Models
- 扩散模型基础框架,基于马尔可夫链
- 正向、反向都是随机过程(SDE)
- DDIM:Denoising Diffusion Implicit Models
- DDPM 的改进 / 加速变体
- 把反向过程变成确定性 ODE,可跳步
- DDIM 不需要重新训练,直接用 DDPM 训练好的权重
- DDPM:Denoising Diffusion Probabilistic Models