知识地图查漏补缺
11 min read
·…
tl;dr:
由于最近手上的产品暂停了,一时间有点闲,所以花了点时间做一下知识回顾。让gpt根据我写过的东西,出了下测试题,这才发现两三年前看的不少东西现在都忘的差不多了,所以打算把遗忘的内容重新整理一下。
先是一些基础问题
gpt先给我出了几个问题,我回答的很差:
- 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。
- RMSNorm
你博客里提到 LLaMA 使用 RMSNorm,而不是传统 LayerNorm。 不要求背公式:RMSNorm 和 LayerNorm 到底少做了什么?为什么少做这件事依然可能正常训练?
我完全忘了,rmsnorm对比layernorm,不减mean,只根据 RMS 调整 magnitude:LayerNorm 同时校正中心和尺度;RMSNorm 只校正尺度。原因是对于训练稳定性,更重要的是保证activation的scale稳定,不是必须移动中心到0,去掉这一步还能简化计算。
- RoPE
不要回答「RoPE 是旋转位置编码」。尝试解释:为什么把 Q/K 按位置进行旋转之后,Q_i · K_j能包含 i 和 j 的相对位置信息?这是我认为比较能判断 Transformer 是否真正理解的一题。
我只记得理论是旋转后依旧不影响相对位置,但是忘了具体的原因是什么。答案是根据旋转矩阵的性质,可以将位置编码的计算进行简化。
- Scaling Law
你当时总结 LLaMA 的一个核心思想是:与其单纯扩大参数量,不如让相对较小的模型训练更多 token。 那么现在假设:
A:70B,训练 300B tokens;
B:13B,训练 2T tokens。
为什么 B 有可能是商业部署中更好的模型?不只考虑模型效果,至少说出 三个维度。
我的回答:13b从工业部署上负载更小,信息压缩密度更好,推理效率也更好,tokens更多意味着可学习知识也越多。这个没啥问题。
- MMoE
两个任务:CTR 和 CVR有 4 个 Expert。请你不用公式,用数据流描述:
user/item features → ? → ? → CTR
user/item features → ? → ? → CVR
然后回答一个关键问题:两个任务看到的是不是同样的 Expert?如果是,那它们为什么还能学到不同的信息?
我记成了mmoe有共享expert,回答两个任务看到的不是同样的expert,然而这个概念是在cgc网络内引入的,mmoe共享所有expert。门控网络决定了不同任务从不同expert中学习不同信息。
- CGC vs MMoE
这恰好是你写 PLE 时自己反复纠结的地方。 你现在重新回答:“CGC 不还是 gate 对 expert hidden state 加权吗?那它和 MMoE 到底有什么本质区别?”
- 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的表达能力。
- 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的区别在于,前者是内存上让多个位置指向原数据,后者是实际上进行数据复制。
- 推荐系统业务
假设同时优化:
- CTR
- Watch Time
- Completion Rate
线上发现:
CTR ↑ 4%
Completion Rate ↑ 2%
Watch Time ↓ 7%
你认为模型发生了什么?如果让你定位问题,你会先看什么数据?
我回答是跷跷板问题,打算从任务权重上排查。这个不符合业务逻辑,实际上应该先发现问题:用户更容易点,而且更容易看完,但是总观看时长下降。然后怀疑推荐的视频是不是整体变短了?
随后应该看一下相关数据再做后续判断:
- 视频时长 distribution
- 平均观看时长
- 观看比例
- session watch time
- 每 session 播放数量
- 不同 duration bucket CTR
- 不同 duration bucket completion
这题答的也很差,应该先从业务角度分析的。
- 系统设计题
假设现在让你从零做一个类似 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架构的作用等等,但在具体实现上忘了很多。
简单的温习一下后,我又进行了第二轮测试:
- 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能重构交互矩阵。
- CF → Swing → Embedding
ItemCF、Swing、MF 三者分别在利用什么信息?
为什么 Swing 能缓解“两个热门 Item 因为很多用户都点过,所以被错误认为相似”的问题?
我对swing不记得了,只记得做了降低权重的工作。实际上swing根据共同用户之间的重合程度,对用户 pair 降权。如果两个人行为几乎完全一样,就会被降权。
- FM / FFM / Deep Crossing
LR 无法自动学习二阶特征交叉,FM 是怎么解决的?FFM 相比 FM 到底多了什么?代价是什么?Deep Crossing 又为什么可以认为是从“人工交叉”走向“神经网络学习交叉”?
这题我答的很差,把fm记成了mf。fm核心是给每个feature做embedding后内积,来实现两两组合的特征交互。ffm是加了特征域,deep crossing则是让网络自己学高阶交互。
- 多任务学习
Shared-bottom → MMOE → PLE → AdaTT 这一条演化路线,本质上分别在解决什么问题?如果 CTR 和 CVR 两个任务梯度方向经常冲突,你觉得 MMOE 一定能解决吗?
我的回答:都在解决多任务中跷跷板和偏移的问题。总结对,但答的不好:需要从演化发展线上来看。share bottom由于所有任务共享底层网络,导致不同任务需要的底层representation不一样,有时会出现梯度冲突。于是mmoe通过加入gate,让每个任务自己决定需要哪些expert。由于mmoe里所有expert都被共享,还是可能区分不够,所以ple才采用share expert+task spectific expert的设计。
- GradNorm
假设:loss = 0.9 * loss_ctr + 0.1 * loss_cvr
为什么手工设置 0.9/0.1 不一定意味着 CTR 对共享层的影响就是 CVR 的 9 倍?GradNorm 真正控制的是什么?
我记得gradnorm控制的是对不同任务的梯度权重比例,考虑哪个任务学得快、哪个任务学得慢,这题没问题。
- AUC
为什么 AUC 可以解释为:随机抽一个正样本和一个负样本,模型把正样本排在负样本前面的概率?如果把模型所有 score 乘 100,AUC 会不会变?
我把auc记成roc面积了,不过auc只关系排序,不关心score尺度,因此乘100不影响。
- Decision Tree → GBDT
Bagging 和 Boosting 最大区别是什么?Random Forest 属于哪一种?GBDT 每棵新树到底是在拟合 label、error,还是 gradient?
这题也答的还行:bagging boosting应该一个串联一个并联,rf属于bagging。gbdt拟合的是loss对预测的负梯度,也就是所谓残差。
- BPE
给定字符级 vocabulary 后,BPE 每轮到底做什么?为什么不断 merge 高频 pair 最终可以产生 subword?encode 一个新单词时又是怎么使用这些 merge rules 的?
我的回答:bpe应该是每轮合并高频pair直到终止条件,大体是对的。推理逻辑忘了,实际是训练完后保存merge rules,然后推理时根据rules优先级重复应用。
- 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 保留更好的模型能力。
- MoE
Mixtral 8×7B 为什么不能简单理解成“每个 token 都经过一个 56B 模型”?Router、Top-K expert、load balancing 分别在干什么?
我的回答:moe是每个token过选中的专家模型,router就是门控分配专家网络,负载均衡是工程上的优化,同时避免其他专家始终学不到东西。这个没问题
- LLM 显存
一个 7B FP16 模型,仅参数大约占多少显存?为什么训练显存远远不止 7B × 2 bytes?Adam、gradient、activation 分别增加了什么?
这个我也忘了,fp16的话,模型权重会占用14g,训练中除了权重,还有梯度,adam参数,激活值等要保存。
- DDP / ZeRO
DDP 为什么能加速训练,却基本不能解决“单卡放不下模型”的问题?ZeRO-1、2、3 分别切分什么?
我把zero的不同阶段忘了,zero1/2/3分别是优化器-梯度-模型参数的切分。
- RQ-VAE / Generative Recommendation
为什么生成式推荐不直接让 Transformer 输出 Item ID,而要先把 Item 转成 Semantic ID?RQ-VAE 的 residual quantization 在这里起什么作用?
答案:生成式推荐希望把 item 变成语义id。RQ 的核心是 Residual Quantization,为了逐层更精确的表示信息。
- Word2Vec / Node2Vec
Word2Vec 的 Skip-Gram 本质在学习什么概率关系?Node2Vec 为什么只需要把“句子”换成 random walk,就可以复用 Word2Vec 思想?
我的回答:学的是词之间的上下文关系,节点和词关系差不多,没啥问题。
- Python 并发
Python threading 和 multiprocessing 的核心区别是什么?为什么 CPU-bound 通常倾向 multiprocessing,而 IO-bound 可以 threading?GIL 在这里到底限制了什么?
我的回答:一个多线程一个多进程。低cpu用多线程,高cpu多进程。gil是python process里,一个时刻只有一个线程。
- Docker
Image 和 Container 的关系是什么?Dockerfile 每条 RUN 为什么和 layer 有关?Compose 解决的又是什么问题?Volume 为什么不会随着 container 删除而自然消失?
我的回答:镜像用于建容器,dockerfile每个run都是在建layer,compose是一键启动多个关联容器,volume是内容文件,不会直接删。没啥问题。
- 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 于苏州