homewritingsthoughts
EN

知识地图查漏补缺

Sep 4, 2026

·

11 min read

·

…

tl;dr:

由于最近手上的产品暂停了,一时间有点闲,所以花了点时间做一下知识回顾。让gpt根据我写过的东西,出了下测试题,这才发现两三年前看的不少东西现在都忘的差不多了,所以打算把遗忘的内容重新整理一下。

先是一些基础问题

gpt先给我出了几个问题,我回答的很差:

  1. Transformer

假设输入 X shape 是 [B, L, D],Multi-Head Attention 有 H 个 head。 从 X 开始,一直到 Attention 输出重新变成 [B,L,D],中间 Q/K/V 的 shape 分别怎么变化? 顺便解释:为什么 attention 的 score 要除以 sqrt(d_k)?

我把转置的位置记错了。除以 √d 是为了数值稳定这个答对了。答案是:qkv的初始shape都一致,然后拆成h个head:[B, L, D] → [B, L, H, D/H] → transpose[B, H, L, D/H]。之后Q * K^T,就得到了[B,H,L,L],也就是batch内第i个token对第j个token的attention score。


  1. RMSNorm

你博客里提到 LLaMA 使用 RMSNorm,而不是传统 LayerNorm。 不要求背公式:RMSNorm 和 LayerNorm 到底少做了什么?为什么少做这件事依然可能正常训练?

我完全忘了,rmsnorm对比layernorm,不减mean,只根据 RMS 调整 magnitude:LayerNorm 同时校正中心和尺度;RMSNorm 只校正尺度。原因是对于训练稳定性,更重要的是保证activation的scale稳定,不是必须移动中心到0,去掉这一步还能简化计算。


  1. RoPE

不要回答「RoPE 是旋转位置编码」。尝试解释:为什么把 Q/K 按位置进行旋转之后,Q_i · K_j能包含 i 和 j 的相对位置信息?这是我认为比较能判断 Transformer 是否真正理解的一题。

我只记得理论是旋转后依旧不影响相对位置,但是忘了具体的原因是什么。答案是根据旋转矩阵的性质,可以将位置编码的计算进行简化。


  1. Scaling Law

你当时总结 LLaMA 的一个核心思想是:与其单纯扩大参数量,不如让相对较小的模型训练更多 token。 那么现在假设:

A:70B,训练 300B tokens;

B:13B,训练 2T tokens。

为什么 B 有可能是商业部署中更好的模型?不只考虑模型效果,至少说出 三个维度。

我的回答:13b从工业部署上负载更小,信息压缩密度更好,推理效率也更好,tokens更多意味着可学习知识也越多。这个没啥问题。


  1. MMoE

两个任务:CTR 和 CVR有 4 个 Expert。请你不用公式,用数据流描述:

user/item features → ? → ? → CTR

user/item features → ? → ? → CVR

然后回答一个关键问题:两个任务看到的是不是同样的 Expert?如果是,那它们为什么还能学到不同的信息?

我记成了mmoe有共享expert,回答两个任务看到的不是同样的expert,然而这个概念是在cgc网络内引入的,mmoe共享所有expert。门控网络决定了不同任务从不同expert中学习不同信息。


  1. CGC vs MMoE

这恰好是你写 PLE 时自己反复纠结的地方。 你现在重新回答:“CGC 不还是 gate 对 expert hidden state 加权吗?那它和 MMoE 到底有什么本质区别?”

  1. PLE

如果只有一层 extraction network,PLE 会退化成什么?

更重要的是为什么 PLE 要堆多层 extraction,而不是把 Expert MLP 直接加深?这两个“深”有什么区别?

mmoe - cgc - ple的发展过程我已经有点遗忘了。CGC和mmoe的区别主要在于:MMoE 的 expert pool 全共享;CGC 显式拆成 shared expert + task-specific expert。单层ple就是cgc,之所以不是加深mlp,是因为叠加多层cgc网络目的是增强task-specific information,而不是增强单个expert的表达能力。


  1. PyTorch / Tensor

这是你文章里实际 debug 过的代码:

x.shape
# [256, 128]

x = x.unsqueeze(1)
x = x.expand(-1, 8, -1)

最终 shape 是什么?然后更难一点:expand 和 repeat 有什么区别?为什么这里更适合 expand?

tensor我忘了很多。x.unsqueeze(1)是在index=1插入维度,即[256,128] → [256,1,128]。然后x.expand(-1, 8, -1)会把[256,1,128]拉伸到[256,8,128]。expand和repeat的区别在于,前者是内存上让多个位置指向原数据,后者是实际上进行数据复制。


  1. 推荐系统业务

假设同时优化:

  • CTR
  • Watch Time
  • Completion Rate

线上发现:

CTR ↑ 4%

Completion Rate ↑ 2%

Watch Time ↓ 7%

你认为模型发生了什么?如果让你定位问题,你会先看什么数据?

我回答是跷跷板问题,打算从任务权重上排查。这个不符合业务逻辑,实际上应该先发现问题:用户更容易点,而且更容易看完,但是总观看时长下降。然后怀疑推荐的视频是不是整体变短了?

随后应该看一下相关数据再做后续判断:

  • 视频时长 distribution
  • 平均观看时长
  • 观看比例
  • session watch time
  • 每 session 播放数量
  • 不同 duration bucket CTR
  • 不同 duration bucket completion

这题答的也很差,应该先从业务角度分析的。


  1. 系统设计题

假设现在让你从零做一个类似 RummiMatch 的推荐系统:

100万用户
10万 items
每天500万 interaction
要求实时推荐 Top 20

不考虑具体云服务。从:interaction log → feature → training → candidate generation → ranking → online serving把整个链路讲一遍。然后告诉我哪些东西应该离线算,哪些必须在线算?

架构题我答的还算正常,因为整个推荐系统流就那么几个组件,流程上如下:

用户交互记录 -> 数据库 -> 特征处理pipeline -> 准备训练数据 -> 训练模型

item/user embedding -> ann recall召回 -> ranking模型 -> reranking模型。item embedding持久化,user embedding可以定期更新or实时计算。

第一轮测试完,大概的评价是:抽象的架构记忆被长期保留了,像moe架构的作用等等,但在具体实现上忘了很多。

简单的温习一下后,我又进行了第二轮测试:

  1. MF / Embedding

Matrix Factorization 为什么可以理解成学习 User Embedding 和 Item Embedding?

如果用户 A 喜欢 X、不喜欢 Y,训练过程中 A、X、Y 三个 embedding 分别会发生什么?

我的回答:mf用交互数据和矩阵分解隐式拆分成user和item的表示,相似的user和item vector的更相似。训练中a会更靠近x,更远离y。

答案大体对,不过mf并不是直接要求相似 user/item embedding 相似,而是要求embedding能重构交互矩阵。


  1. CF → Swing → Embedding

ItemCF、Swing、MF 三者分别在利用什么信息?

为什么 Swing 能缓解“两个热门 Item 因为很多用户都点过,所以被错误认为相似”的问题?

我对swing不记得了,只记得做了降低权重的工作。实际上swing根据共同用户之间的重合程度,对用户 pair 降权。如果两个人行为几乎完全一样,就会被降权。


  1. FM / FFM / Deep Crossing

LR 无法自动学习二阶特征交叉,FM 是怎么解决的?FFM 相比 FM 到底多了什么?代价是什么?Deep Crossing 又为什么可以认为是从“人工交叉”走向“神经网络学习交叉”?

这题我答的很差,把fm记成了mf。fm核心是给每个feature做embedding后内积,来实现两两组合的特征交互。ffm是加了特征域,deep crossing则是让网络自己学高阶交互。


  1. 多任务学习

Shared-bottom → MMOE → PLE → AdaTT 这一条演化路线,本质上分别在解决什么问题?如果 CTR 和 CVR 两个任务梯度方向经常冲突,你觉得 MMOE 一定能解决吗?

我的回答:都在解决多任务中跷跷板和偏移的问题。总结对,但答的不好:需要从演化发展线上来看。share bottom由于所有任务共享底层网络,导致不同任务需要的底层representation不一样,有时会出现梯度冲突。于是mmoe通过加入gate,让每个任务自己决定需要哪些expert。由于mmoe里所有expert都被共享,还是可能区分不够,所以ple才采用share expert+task spectific expert的设计。


  1. GradNorm

假设:loss = 0.9 * loss_ctr + 0.1 * loss_cvr

为什么手工设置 0.9/0.1 不一定意味着 CTR 对共享层的影响就是 CVR 的 9 倍?GradNorm 真正控制的是什么?

我记得gradnorm控制的是对不同任务的梯度权重比例,考虑哪个任务学得快、哪个任务学得慢,这题没问题。


  1. AUC

为什么 AUC 可以解释为:随机抽一个正样本和一个负样本,模型把正样本排在负样本前面的概率?如果把模型所有 score 乘 100,AUC 会不会变?

我把auc记成roc面积了,不过auc只关系排序,不关心score尺度,因此乘100不影响。


  1. Decision Tree → GBDT

Bagging 和 Boosting 最大区别是什么?Random Forest 属于哪一种?GBDT 每棵新树到底是在拟合 label、error,还是 gradient?

这题也答的还行:bagging boosting应该一个串联一个并联,rf属于bagging。gbdt拟合的是loss对预测的负梯度,也就是所谓残差。


  1. BPE

给定字符级 vocabulary 后,BPE 每轮到底做什么?为什么不断 merge 高频 pair 最终可以产生 subword?encode 一个新单词时又是怎么使用这些 merge rules 的?

我的回答:bpe应该是每轮合并高频pair直到终止条件,大体是对的。推理逻辑忘了,实际是训练完后保存merge rules,然后推理时根据rules优先级重复应用。


  1. Transformer / LLaMA

为什么现代 LLM 基本采用 Decoder-only,而不是 Encoder-only?RMSNorm、RoPE、SwiGLU、GQA 分别改了 Transformer 的哪个部分?

我的回答:

现代llm主要任务是生成任务,decoder天然适合输出生成。rms去掉了layernorm取均值,计算更简单。

rope答的不太好,答案应该是:rope通过对 Q/K 做与 position 有关的旋转,使 attention 内积自然携带相对位置信息。swiglu也忘了,实际上是增加了门控ffn。gqa是一组Q heads共用一组 K/V,目的是减少 KV Cache 和推理带宽,同时比 MQA 保留更好的模型能力。


  1. MoE

Mixtral 8×7B 为什么不能简单理解成“每个 token 都经过一个 56B 模型”?Router、Top-K expert、load balancing 分别在干什么?

我的回答:moe是每个token过选中的专家模型,router就是门控分配专家网络,负载均衡是工程上的优化,同时避免其他专家始终学不到东西。这个没问题


  1. LLM 显存

一个 7B FP16 模型,仅参数大约占多少显存?为什么训练显存远远不止 7B × 2 bytes?Adam、gradient、activation 分别增加了什么?

这个我也忘了,fp16的话,模型权重会占用14g,训练中除了权重,还有梯度,adam参数,激活值等要保存。


  1. DDP / ZeRO

DDP 为什么能加速训练,却基本不能解决“单卡放不下模型”的问题?ZeRO-1、2、3 分别切分什么?

我把zero的不同阶段忘了,zero1/2/3分别是优化器-梯度-模型参数的切分。


  1. RQ-VAE / Generative Recommendation

为什么生成式推荐不直接让 Transformer 输出 Item ID,而要先把 Item 转成 Semantic ID?RQ-VAE 的 residual quantization 在这里起什么作用?

答案:生成式推荐希望把 item 变成语义id。RQ 的核心是 Residual Quantization,为了逐层更精确的表示信息。


  1. Word2Vec / Node2Vec

Word2Vec 的 Skip-Gram 本质在学习什么概率关系?Node2Vec 为什么只需要把“句子”换成 random walk,就可以复用 Word2Vec 思想?

我的回答:学的是词之间的上下文关系,节点和词关系差不多,没啥问题。


  1. Python 并发

Python threading 和 multiprocessing 的核心区别是什么?为什么 CPU-bound 通常倾向 multiprocessing,而 IO-bound 可以 threading?GIL 在这里到底限制了什么?

我的回答:一个多线程一个多进程。低cpu用多线程,高cpu多进程。gil是python process里,一个时刻只有一个线程。


  1. Docker

Image 和 Container 的关系是什么?Dockerfile 每条 RUN 为什么和 layer 有关?Compose 解决的又是什么问题?Volume 为什么不会随着 container 删除而自然消失?

我的回答:镜像用于建容器,dockerfile每个run都是在建layer,compose是一键启动多个关联容器,volume是内容文件,不会直接删。没啥问题。


  1. Nginx / 反向代理

用户访问 zerolovesea.top 时,如果真正应用运行在服务器 localhost:4321,DNS、Nginx、应用服务器之间请求是怎么流转的?

我的回答:请求被dns解析后到nginx做负载均衡,然后到服务器的localhost 访问服务。不太准确,具体是浏览器 -> dns 解析域名 -> 服务器公网IP -> 服务器 443 / 80 -> nginx做反向代理 -> localhost:4321 -> 最后到应用


这轮的评价如下:


知识状态划成四层:

A. 仍然是活跃知识
────────────────
MF
GBDT
MoE
Docker
Word2Vec
推荐系统整体逻辑

B. 骨架还在,细节掉了
────────────────
Swing
MMOE / PLE
GradNorm
AUC
BPE
Spark
DDP / ZeRO

C. 写过,但已经明显退化
────────────────
FM / FFM
RQ-VAE
LLaMA architecture details
显存计算

D. 出现错误记忆
────────────────
Python threading / multiprocessing / GIL
SwiGLU
GQA

2026/9/7 于苏州