从梯度下降到 Semantic ID:理解 RQ-VAE 所需的全部前序知识
一篇文章补齐从机器学习基础、深度学习、Transformer/LLM、搜广推系统架构到向量量化的全部知识链——读完后直接进入 RQ-VAE Semantic ID 训练那篇文章,不会有任何理解断裂。
你想读懂”码本利用率的骗局”那篇文章,但发现里面的概念一个接一个冒出来——Embedding、梯度下降、Transformer、自回归、CTR 预估、VAE、码本崩塌……每个都好像需要另一篇文章来解释。
这就是那另一篇文章。
本文覆盖从最基础的机器学习到向量量化的完整知识链。它不是教科书式的面面俱到,而是只讲你理解 RQ-VAE Semantic ID 所需要的那些概念,按依赖顺序排列,保证你读完之后能无缝衔接到目标文章。
Part 1:机器学习基础——让机器从数据中学规律
什么是机器学习
传统编程:人写规则,计算机执行。
机器学习:人提供数据和目标,计算机自己找规则。
传统:输入 + 规则 → 输出
ML:输入 + 输出 → 规则(模型)
这个”找规则”的过程就是训练 (Training)。找到的规则存储在模型 (Model) 中。用找到的规则处理新数据叫推理 (Inference)。
监督学习:最常见的学习范式
监督学习的核心:给机器看大量”输入-正确答案”的配对,让它学会从输入预测正确答案。
| 任务类型 | 输入 | 输出 | 例子 |
|---|---|---|---|
| 分类 | 特征向量 | 离散类别 | 这个广告会不会被点击?(是/否) |
| 回归 | 特征向量 | 连续数值 | 这个广告的点击率是多少?(0.03) |
推荐/广告系统中,CTR 预估就是一个典型的分类(或回归)问题:给定用户特征 + 广告特征 + 上下文特征,预测”这个用户会不会点击这个广告”。
损失函数:衡量”学得好不好”
模型预测一个值 y_hat,真实值是 y。损失函数 (Loss Function) 衡量两者的差距。
| 损失函数 | 公式含义 | 用途 |
|---|---|---|
| MSE | 预测值与真实值差的平方的平均 | 回归任务 |
| 交叉熵 | 衡量预测概率分布与真实分布的差异 | 分类任务 (CTR 预估) |
| 重建损失 | 输入 x 与重建 x_hat 的差异 | 自编码器 / VQ-VAE |
损失越小 = 模型预测越准。训练的目标就是最小化损失函数。
梯度下降:如何让损失变小
想象你站在一座山上(当前损失值),蒙着眼(不知道全局地形),想走到最低谷(最小损失)。
梯度告诉你”当前脚下哪个方向是上坡的”。梯度下降就是”朝梯度反方向迈一步”——永远朝下坡方向走。
参数_new = 参数_old - 学习率 * 梯度
每一步迈多大。太大会跨过最低点反复震荡;太小会走得极慢,可能困在局部低谷。这是模型训练中最重要的超参数之一。
后面你会看到 RQ-VAE 训练中”限制 Tokenizer 的学习率”来防止漂移——就是利用了这个原理:学习率小 = 参数变化小 = 稳定。
Batch 训练:为什么不是一个一个样本学
如果每看一个样本就更新一次参数(SGD),方向会很不稳定——一个噪声样本可能把参数带偏。
Mini-Batch 训练:每次看一批样本(比如 256 个),计算这批的平均梯度,再更新。好处:
- 方向更稳定(多个样本的梯度互相平均)
- 利用 GPU 并行计算(GPU 擅长矩阵运算,一批数据刚好是矩阵)
- 可以做正则化效果(batch 内的随机性本身就是噪声)
后面 RQOPQ 的核心优势”可以 Batch 训练”,就是说它不需要把全部数据一次性加载做 K-means,而是可以用小批量逐步训练。
过拟合与正则化
过拟合:模型在训练集上表现完美,但在新数据上很差。就像一个学生把所有考题答案都背下来了,但遇到新题完全不会。
对策:
- Dropout:训练时随机关闭一些神经元,迫使模型不能依赖单一路径
- L2 正则化:惩罚参数值过大,鼓励模型用”简单”的规则
- Early Stopping:验证集性能不再提升时停止训练
- 数据增强:人为制造更多训练样本
Embedding:把离散 ID 变成连续向量
这是整个推荐系统的基石概念。
假设你有 100 万个用户,每个用户有一个 ID(1 到 1,000,000)。你不能直接把 ID 数字喂给模型——“用户 999,999”不比”用户 1”大 999,998 倍。
Embedding:为每个 ID 分配一个可学习的向量(比如 64 维),让模型自己学出每个用户的”语义表示”。
用户 12345 → [0.23, -0.45, 0.87, ..., 0.12] (64维向量)
用户 67890 → [-0.11, 0.56, 0.34, ..., -0.78] (64维向量)
相似的用户,Embedding 向量在空间中距离近。这就是”表征学习”的核心——把离散符号映射到连续语义空间。
每个 ID 的 Embedding 是独立参数。新 item 的 Embedding 初始化为随机向量,必须通过大量数据训练才能有用。这就是”冷启动问题”——新 item 没有足够的行为数据,Embedding 没训好,推荐系统就推不动它。
Semantic ID 试图解决的就是这个问题:不用独立参数表示每个 item,而是用有限码字的组合——新 item 只要内容相似,自动得到相似的 SID。
Part 2:深度学习——让模型自动发现复杂模式
从线性模型到神经网络
线性模型:y = w1*x1 + w2*x2 + ... + b。只能拟合线性关系。
但真实世界中,“用户是否点击广告”取决于特征之间的复杂交互——年龄 * 兴趣 * 时间 * 上下文的非线性组合。
神经网络:多层线性变换 + 非线性激活函数的堆叠,能拟合任意复杂函数。
输入 → [线性变换 → 激活函数] × N层 → 输出
每一层做两件事:
- 线性变换:
z = W * x + b(矩阵乘法,就是加权求和) - 非线性激活:
a = ReLU(z)或sigmoid(z)(让模型能拟合曲线,不只是直线)
反向传播:深度学习的训练算法
有了损失函数和多层网络,怎么知道每一层的参数该怎么调?
反向传播 (Backpropagation):从最后一层的损失开始,利用链式法则,逐层往回计算每个参数对损失的贡献度(梯度)。
Loss → ∂Loss/∂最后一层参数 → ∂Loss/∂倒数第二层参数 → ... → ∂Loss/∂第一层参数
本质就是高中数学的链式求导法则在多层函数复合中的应用。
VQ-VAE 中的核心难题”argmin 不可微”就是反向传播的问题——量化操作是离散选择,导数为零,梯度无法回传。Straight-Through Estimator 本质上就是”骗”反向传播,让它以为量化层是恒等映射。
CNN:空间特征提取
卷积神经网络 (CNN):专门处理有空间结构的数据(图像、视频帧)。核心思想:
- 局部感受野:每次只看图像的一小块区域
- 权重共享:同一个滤波器扫描整个图像
- 层次结构:浅层检测边缘,深层检测物体
在推荐/广告系统中,广告素材(图片/视频)的特征提取通常用预训练 CNN(如 ResNet)。这些特征再输入 RQ-VAE 做量化编码。
RNN/LSTM:序列建模
循环神经网络 (RNN):处理序列数据(用户行为序列、浏览历史)。核心:有”记忆”,能把前面的信息传给后面。
LSTM (长短期记忆):解决 RNN 的”长期遗忘”问题。通过门控机制选择性地记住和遗忘。
在推荐系统中,用户的点击历史 [item1, item2, item3, …] 就是序列。LSTM 或 GRU 可以捕获序列中的模式。但 2017 年之后,Transformer 基本取代了 LSTM。
Attention 机制:让模型学会”看哪里”
传统序列模型(RNN)对所有历史信息一视同仁地压缩。但实际上,预测”用户下一个点什么”时,最近点击的几个 item 远比半年前的重要。
Attention 让模型学会”给不同位置分配不同权重”:
- 对每个历史 item 计算一个”相关性分数”
- 用 softmax 归一化为概率
- 按概率加权聚合历史信息
这就是”注意力”的含义——不是平等看待所有信息,而是聚焦在最相关的部分。
Part 3:Transformer——现代深度学习的基础架构
为什么 Transformer 取代了 RNN
RNN 的致命缺陷:必须顺序处理。处理第 100 个 token 之前必须先处理前 99 个。这意味着:
- 无法并行化训练(GPU 利用率低)
- 长序列中早期信息会衰减丢失
Transformer 的解决方案:Self-Attention——每个位置可以直接关注序列中的任何其他位置,不需要顺序传递。
| 特性 | RNN | Transformer |
|---|---|---|
| 并行度 | 低(必须顺序) | 高(所有位置同时计算) |
| 长距离依赖 | 衰减严重 | 任意距离直接连接 |
| 计算复杂度 | O(n) 顺序 | O(n^2) 但全并行 |
| 训练效率 | 低 | 高(GPU 友好) |
Self-Attention 详解
给定一个序列(比如用户点击的 4 个 item),Self-Attention 的工作流程:
第一步:生成 Q、K、V
每个 token(item)通过三个不同的线性投影,生成三个向量:
- Query (Q):我在找什么信息?
- Key (K):我能提供什么信息?
- Value (V):我的实际内容是什么?
第二步:计算注意力分数
用 Q 和所有 K 做点积(内积),得到”相关性分数”。点积越大 = 越相关。
第三步:归一化 + 加权
把分数除以 sqrt(d_k)(防止值太大导致 softmax 饱和),再过 softmax 变成概率,最后用概率加权 V。
# Self-Attention 核心计算
scores = Q @ K.T / sqrt(d_k) # [seq_len, seq_len] 的分数矩阵
weights = softmax(scores, dim=-1) # 归一化为概率
output = weights @ V # 加权聚合 Value
Multi-Head Attention
不是做一次 Attention,而是并行做 h 次(h=8、12、16 等),每次用不同的投影矩阵。
为什么?一次 Attention 只能关注一种”关系模式”。多个 head 让模型同时捕获多种关系(语义相似性、时间接近性、类目相关性等)。
位置编码
Self-Attention 本身不区分位置——它只看内容的相关性,不知道哪个 token 在前哪个在后。
位置编码 (Positional Encoding):给每个位置加一个固定或可学习的向量,让模型知道顺序信息。
最终输入 = Token Embedding + Position Encoding
在 SID 的自回归生成中,位置编码让模型知道”我现在在生成第几层码字”。
LayerNorm 和残差连接
Transformer 的每一层都有两个关键组件:
- 残差连接:
output = x + Attention(x)。让梯度可以”跳过”某一层直接传播,解决深层网络的梯度消失问题。 - LayerNorm:归一化每个样本的特征,稳定训练过程。
这些看似细节,但它们是深度 Transformer 能稳定训练的关键。
Part 4:LLM 与生成模型——从理解到创造
自回归语言模型
GPT 系列模型的核心思想极其简单:预测下一个 token。
给定已有的 token 序列 [x1, x2, …, xt],模型预测下一个 token xt+1 的概率分布。
P(下一个token | 已有序列) = Transformer(已有序列) → softmax → 概率分布
训练时,用真实的下一个 token 计算交叉熵损失。推理时,从概率分布中采样或取最大概率的 token。
生成 “我想买鞋” 的过程:
- 输入 [开始] → 预测 → “我” (概率最大)
- 输入 [开始, 我] → 预测 → “想”
- 输入 [开始, 我, 想] → 预测 → “买”
- 输入 [开始, 我, 想, 买] → 预测 → “鞋”
- 输入 [开始, 我, 想, 买, 鞋] → 预测 → [结束]
SID 生成式推荐的工作方式完全一样:输入用户历史行为序列,逐层预测码字索引 [k1, k2, k3],每一层的预测条件化于前面所有层的结果。
Token 和词表 (Vocabulary)
LLM 不直接处理文字,而是先把文字切成token——比 word 小、比 character 大的单元。
"unhappiness" → ["un", "happiness"] (2 tokens)
"RQ-VAE" → ["RQ", "-", "VA", "E"] (4 tokens)
词表 (Vocabulary):所有可能的 token 组成的集合。GPT-4 的词表大小约 100K。
关键约束:词表必须是有限的、固定的。无限词表意味着无限参数,无法训练。
LLM 的 Scaling Law(模型越大性能越好)依赖于一个前提:有限词表。
- 有限词表 → 参数增加意味着每个 token 的表征更丰富
- 语义组合性 → 模型可以泛化到从未见过的 token 组合
推荐系统的 Hash ID 破坏了这个前提——每个 item 一个独立 ID,词表随 item 数量线性增长(可达数亿),每个 ID 的参数不共享信息。所以 Hash ID 不存在 Scaling Law。
SID 的本质目的就是给推荐系统装上”有限词表”:用有限数量的码字(比如 1024 个),通过组合([k1, k2, k3])表示无限多的 item。
VAE:变分自编码器
自编码器 (Autoencoder):输入 → 压缩为低维向量 → 从低维向量重建输入。
输入 x → Encoder → 潜在表示 z → Decoder → 重建 x_hat
目标:让 x_hat 尽可能接近 x
VAE (Variational Autoencoder):不是编码为一个确定的向量,而是编码为一个分布(均值 + 方差)。然后从这个分布中采样一个 z,再解码。
为什么用分布?因为我们想让潜在空间是”连续的、有结构的”——相似的输入在潜在空间中距离近,而且空间中任何一个点都能解码出有意义的输出。
“从分布中采样”是随机操作,无法反向传播。重参数化技巧的解决方案:
z = mu + sigma * epsilon (epsilon ~ N(0,1) 是固定噪声)梯度可以穿过 mu 和 sigma(它们是 Encoder 的输出),而 epsilon 是外部随机数,不需要梯度。
这个思想和 Straight-Through Estimator 异曲同工——都是想办法让”不可微的操作”变得可以训练。
VAE 的损失函数
VAE 的损失有两项:
- 重建损失:x_hat 和 x 的差异(让编码保留足够信息)
- KL 散度:让编码的分布接近标准正态分布(让潜在空间有结构)
Loss = 重建损失 + beta * KL散度
这两项天然矛盾:重建损失想让每个 item 的编码尽可能不同(高信息量),KL 散度想让所有编码接近标准正态(低信息量)。这就是 “rate-distortion tradeoff”——在 VQ-VAE 里表现为”重建 loss 和 commitment loss 此消彼长”。
Part 5:搜广推系统——推荐和广告的工业实践
搜索、推荐、广告的区别
| 系统 | 用户意图 | 商业模式 | 核心挑战 |
|---|---|---|---|
| 搜索 | 明确(关键词) | 竞价广告 | 理解查询意图 |
| 推荐 | 模糊(无明确需求) | 信息流广告/会员 | 发现用户潜在兴趣 |
| 广告 | 无(被动接收) | CPM/CPC/CPA | 在用户体验和商业价值间平衡 |
三者的技术栈高度重叠——都需要”从海量候选中挑出最合适的内容呈现给用户”。核心差异在于优化目标不同:
- 推荐优化用户满意度(停留时长、点击率)
- 广告优化 eCPM = pCTR * pCVR * Bid(同时满足平台收入和用户体验)
多阶段 Pipeline
一个典型的广告系统需要从数百万广告中选出展示给用户的那 1-3 个。不可能对每个广告都用最复杂的模型打分(太慢太贵),所以分成多个阶段逐步精细化:
第一阶段:召回 (Recall)
任务:从千万级候选中快速筛出几百个可能相关的。
技术:倒排索引、双塔模型(用户塔 + 物料塔,向量内积近似相关性)、图神经网络。
关键:速度第一,允许粗糙。但一旦在这步丢了,后面永远找不回来。
第二阶段:粗排 (Pre-ranking)
任务:从几百个中选出几十个进入精排。
技术:轻量 DNN、蒸馏模型(用精排的”大模型”训一个”小模型”近似其排序)。
关键:平衡精度和效率。
第三阶段:精排 (Ranking)
任务:对几十个候选精确打分。
技术:Deep CTR 模型(DIN、DIEN、DCN、AutoInt 等)。使用全量特征交叉,计算 pCTR 和 pCVR。
关键:精度第一,可以用复杂模型。
第四阶段:重排 (Reranking)
任务:在精排结果上做最终调整。
技术:多样性控制、频次控制、价格平滑、上下文相关性。
第五阶段:竞价 (Auction)(广告特有)
任务:基于 eCPM 排序,决定最终展示哪个广告、收多少钱。
eCPM = pCTR × pCVR × Bid
传统 pipeline 的每一级各自优化,信息逐级丢失。生成式推荐用一个自回归模型直接从用户历史生成最优 item 的 Semantic ID——跳过了召回/粗排/精排的分层结构,理论上能找到被传统 pipeline 在早期阶段丢掉的高价值 item。
CTR 预估模型的演进
CTR(Click-Through Rate)预估是精排阶段的核心任务:预测用户点击某个广告的概率。
| 时代 | 模型 | 核心思想 | 解决的问题 |
|---|---|---|---|
| 2010-2014 | LR (逻辑回归) | 线性加权 | 简单可解释 |
| 2014-2016 | GBDT + LR | 树模型做特征交叉 | 非线性交互 |
| 2016 | FM (因子分解机) | 隐向量内积做二阶交叉 | 稀疏特征交叉 |
| 2017 | Deep & Wide / DeepFM | DNN + 浅层交叉并行 | 自动特征交叉 |
| 2018 | DIN (阿里) | Attention 加权用户历史 | 用户兴趣多样性 |
| 2019 | DIEN (阿里) | GRU 建模兴趣演化 | 兴趣动态变化 |
| 2020+ | DCN v2 / AutoInt | 显式高阶交叉 + Attention | 更深层特征交互 |
所有这些模型都依赖 Embedding 表来表示离散 ID 特征(用户 ID、物料 ID、类目 ID 等)。每个 ID 是一行独立参数。
Item ID 的本质局限
在传统推荐系统中,每个 item 有一个唯一 ID,对应 Embedding 表中的一行向量:
item_42 → Embedding[42] = [0.3, -0.1, 0.8, ...] (可学习参数)
item_43 → Embedding[43] = [-0.2, 0.5, 0.1, ...] (独立参数)
问题:
- 冷启动:新 item 的 Embedding 是随机初始化的,需要大量曝光才能训好
- 无泛化:两个内容几乎相同的 item(比如同款鞋的不同颜色),它们的 ID Embedding 完全独立,无法互相借力
- 词表爆炸:百万级 item × 64 维 Embedding = 2.56 亿参数,只用于 item ID 一个特征
- 无 Scaling Law:增加模型参数不能让 item ID 的表征质量提升——因为每个 ID 的参数已经是独立的了
CVR 预估与多目标优化
广告系统不只预测点击率,还需要预测转化率 (CVR)——用户点击广告后是否会购买/注册/下载。
eCPM = pCTR × pCVR × Bid
CVR 预估的难点:
- 样本选择偏差:只有点击了的用户才有转化标签,未点击的是缺失数据
- 数据稀疏:转化率通常 < 5%,正样本极少
- 延迟反馈:用户可能点击后几天才转化
这解释了为什么”端到端训 CVR 模型最后没敢推全”——CVR 模型对 ID 稳定性极度敏感。SID 漂移 → CVR 模型输入突变 → 预测不准 → 出价系统异常 → 广告主资金波动。
协同过滤与 Embedding 的关系
协同过滤 (Collaborative Filtering):利用用户行为的相似性做推荐。“和你相似的人也喜欢X”。
矩阵分解(MF)是经典的协同过滤方法:
评分矩阵 R ≈ U × V^T
U: 用户 Embedding 矩阵 (每行是一个用户的向量)
V: 物品 Embedding 矩阵 (每行是一个物品的向量)
用户 u 对物品 v 的预测评分 = u 向量和 v 向量的内积。
本质上,深度推荐模型中的 Embedding 表就是矩阵分解的推广。 Embedding 向量承载了用户/物品的”协同信息”——通过大量行为数据训练出来的隐式偏好。
这就是为什么 RQ-VAE 的目标文章中会区分”多模态语义信号”和”协同信号”——Embedding 里学到的是行为关联(谁点了谁),多模态模型给出的是内容相似性(图片/文字/视频特征)。
Part 6:向量量化——从连续到离散的桥梁
为什么需要离散化
连续 Embedding 好用,为什么还要费劲把它变成离散的?
| 需求 | 连续表征的问题 | 离散编码的优势 |
|---|---|---|
| 自回归生成 | 无法直接用语言模型生成连续向量 | 离散 token 可以逐步生成 |
| 有限词表 | 连续空间无限大 | 离散码字有限,可以建词表 |
| 压缩存储 | 64 维 float = 256 bytes/item | 4 个码字索引 = 8 bytes/item |
| 可解释性 | 连续向量人看不懂 | 码字可以关联到语义簇 |
| Scaling Law | 无限 ID 不共享信息 | 码字共享 → 组合泛化 |
K-Means 聚类:量化的原型
向量量化的思想来源于聚类。K-Means 把 N 个数据点分成 K 个簇:
- 随机初始化 K 个中心点
- 每个数据点分配到最近的中心
- 每个中心更新为其簇内所有点的平均
- 重复 2-3 直到收敛
聚类后,每个数据点可以用其中心点的索引来表示——这就是最基本的向量量化。
数据点 [0.23, 0.87, -0.45] → 离它最近的中心是 第 7 个 → 编码为 "7"
K-Means 的问题:必须用全部数据一次性算。数据量大了(上亿 item)不现实。
乘积量化 (Product Quantization, PQ)
把高维向量切成多个子空间,每个子空间独立做 K-Means。
64维向量 → 切成 8 个 8维子向量
每个子向量用 256 个中心做聚类
总编码 = [子空间1的中心索引, 子空间2的, ..., 子空间8的]
容量 = 256^8 ≈ 1.8 × 10^19 种组合
只用 8 个 byte(每个子空间一个 byte 表示 256 个中心之一)就能表示近乎无限的 item。
PQ 是 RQ-VAE 的思想前身。 RQ-VAE 的”残差”概念进一步改进了 PQ——不是切子空间,而是逐层编码残差。
VQ-VAE:可学习的向量量化
VQ-VAE (Vector Quantized VAE):把 VAE 中的连续隐空间替换为离散码本。
输入 x → Encoder → 连续向量 z_e → 找最近码字 → 离散编码 z_q → Decoder → 重建 x_hat
与普通 K-Means 的区别:码本和 Encoder/Decoder 一起端到端训练——Encoder 学习如何把输入编码成容易量化的表征,Decoder 学习如何从码字重建输入,码本学习最优的代表性位置。
Straight-Through Estimator (STE)
VQ-VAE 的核心难题:argmin 操作不可微。
z_q = e_k where k = argmin_i ||z_e - e_i||_2
这个”找最近的”操作是离散选择,梯度为零。Decoder 的梯度无法传回 Encoder。
STE 的解决方案:
- 前向传播:正常使用 z_q(离散选择的码字)
- 反向传播:假装 z_q = z_e(把梯度直接复制给 Encoder)
# STE 的实现(一行代码)
z_q = z_e + (z_q - z_e).detach()
# 前向:z_q 的值是量化后的码字
# 反向:梯度穿过 z_q 直达 z_e(因为 .detach() 把差值的梯度截断了)
STE 引入了梯度偏差——Encoder 收到的梯度信号和它实际产生的离散选择不完全一致。这是 VQ-VAE 训练中很多奇怪现象(梯度震荡、训练不稳定)的根源之一。FSQ 通过取消码本彻底绕过了这个问题。
VQ-VAE 的三项损失
VQ-VAE 的总损失由三项组成:
L = L_reconstruct + L_VQ + beta * L_commit
| 损失项 | 公式含义 | 作用 |
|---|---|---|
| 重建损失 | ||x - x_hat||^2 | 让编码保留足够信息以重建输入 |
| VQ 损失 | ||sg[z_e] - e_k||^2 | 让码字移向 Encoder 输出 (更新码本) |
| Commitment 损失 | ||z_e - sg[e_k]||^2 | 让 Encoder 输出靠近码字 (防止 z_e 漂移太快) |
sg[·] 是 stop gradient——只更新一侧,固定另一侧。
这三项损失之间存在天然矛盾(目标文章中的”损失拉扯”失败模式)。实践中通常用 EMA(指数移动平均)更新码本来替代 VQ 损失。
码本崩塌:VQ-VAE 的头号问题
训练 VQ-VAE 时最常见的问题:大量码字”饿死”,只有少数码字被使用。
为什么会崩塌?
想象 K-Means 的初始化:如果某些中心一开始离数据很远,就永远不会有数据点分配过去。缺少数据分配 → 不被更新 → 永远远离数据 → 恶性循环。
在 VQ-VAE 中这个问题更严重:
- Encoder 输出会动态变化(不像静态数据)
- EMA 更新依赖”有数据分配过来”
- 高维空间加剧了距离退化
对策(也是目标文章的核心主题):
- Sinkhorn 强制均匀分配
- 定期重初始化死码字
- 降低码本维度
- FSQ 彻底取消码本
EMA 更新 vs 梯度更新
更新码本有两种方式:
梯度更新:用 VQ 损失的梯度直接更新码字向量。问题是需要很大的 batch 才能给每个码字足够的梯度信号。
EMA (指数移动平均) 更新:
# 对于码字 e_k
N_k = decay * N_k + (1-decay) * 被分配到 e_k 的样本数
m_k = decay * m_k + (1-decay) * 被分配到 e_k 的样本平均
e_k = m_k / N_k
EMA 相当于一个”在线版的 K-Means”——不用全量数据,每个 batch 都渐进更新。但它有一个问题:如果某个码字突然没有数据分配了,它的 EMA 计数 N_k 会指数衰减趋近于零,数值不稳定。
Part 7:从 VQ-VAE 到 RQ-VAE——进入目标文章
VQ-VAE 的容量瓶颈
单层 VQ-VAE:码本大小为 K,那么最多只能区分 K 个不同的 item。
如果你有 1000 万个 item,需要 K = 10,000,000。但一次前向传播要计算输入与所有 1000 万个码字的距离——计算量爆炸。
RQ-VAE:残差量化的指数容量
核心思想:用多层码本逐层编码残差。
第1层:z_e 量化为 e_k1,残差 r1 = z_e - e_k1
第2层:r1 量化为 e_k2,残差 r2 = r1 - e_k2
第3层:r2 量化为 e_k3,残差 r3 = r2 - e_k3
...
每层码本大小为 K,L 层的总容量 = K^L。
K=1024, L=4 → 容量 = 1024^4 ≈ 1.1 × 10^12 (万亿级)
每个 item 的 Semantic ID 就是各层码字索引的序列:[k1, k2, k3, k4]。
类比邮政地址:
- 第 1 层编码 “中国”(粗粒度位置)
- 残差 = 你的精确位置 - 中国中心点
- 第 2 层编码残差为 “北京”
- 残差 = 你的位置 - 北京中心点
- 第 3 层编码残差为 “海淀区”
- 第 4 层编码残差为 “中关村某号”
每一层编码上一层没覆盖到的”误差”,逐步逼近真实位置。
SID 如何用于生成式推荐
有了 RQ-VAE,每个 item 变成了一串离散码字 [k1, k2, k3, k4]。这串码字就是 Semantic ID (SID)。
然后训练一个自回归模型(Transformer),给定用户历史行为,逐层预测下一个 item 的 SID:
用户历史 [itemA_SID, itemB_SID, itemC_SID] → 预测 → [k1]
用户历史 + [k1] → 预测 → [k2]
用户历史 + [k1, k2] → 预测 → [k3]
用户历史 + [k1, k2, k3] → 预测 → [k4]
→ SID [k1, k2, k3, k4] → 查表 → 具体 item
这就是生成式推荐——不是从候选集里”选”,而是直接”生成”出最优 item 的 ID。
你现在可以读目标文章了
到这里,你已经具备了理解 RQ-VAE SID 训练文章所需的全部前置知识:
| 目标文章中的概念 | 你在本文中学到的基础 |
|---|---|
| 码本利用率 | K-Means + VQ-VAE 码本崩塌 |
| 碰撞率 | Embedding 的离散映射 + 容量限制 |
| Sinkhorn 均衡 | 码本崩塌的原因 + 分配问题 |
| RQOPQ | PQ 乘积量化 + Batch 训练 |
| FSQ | STE 的代价 + 去掉码本的思路 |
| 端到端 vs Freeze | VAE 训练 + CTR/CVR 系统的稳定性需求 |
| Scaling Law | Token/词表 + 自回归生成 + Embedding 的局限 |
| 头部/尾部策略 | 冷启动问题 + 协同信号 vs 语义信号 |
| 离在线一致性 | argmin 不可微 + STE + 浮点精度 |
Part 8:学习路径
Level 1:基础建模感知(3 天)
- 用 scikit-learn 跑一个逻辑回归 + GBDT 分类任务,理解 train/val/test 划分和过拟合
- 用 PyTorch 从零实现一个 2 层 MLP 做 MNIST 分类,体会梯度下降和 Batch 训练
- 读 3Blue1Brown 的 “Neural Networks” 系列视频(3 集共 1 小时),建立几何直觉
Level 2:深度学习核心(1 周)
- 实现一个简单的 Self-Attention 层(30 行 PyTorch),输入 4 个向量看 attention weight 矩阵
- 读 “The Illustrated Transformer”(Jay Alammar 博客),理解完整的 Transformer 架构
- 用 Hugging Face 跑一个 GPT-2 small 的文本生成,体感自回归生成过程
- 读推荐系统综述:王喆《深度学习推荐系统》第 1-4 章
Level 3:搜广推实战(2 周)
- 实现 DeepFM 模型做 CTR 预估(Criteo 数据集),理解 Embedding + 特征交叉
- 实现一个简单的双塔召回模型,理解 user tower / item tower 的分离训练
- 读 DIN 论文(阿里 2018),理解 Attention 在推荐中的应用
- 跑一个 VQ-VAE 在 MNIST 上的实验,观察码本崩塌现象
Level 4:前沿接入(持续)
- 读 Google DSI (2022) + TIGER (2023):生成式推荐的原始思路
- 读快手 OneRec / OneSearch:工业级 SID 部署
- 实现 RQ-VAE 并复现码本利用率 vs 维度的实验
- → 进入目标文章:《码本利用率的骗局》
留给你的思考题
-
Embedding 表 vs SID 码本——二者都是”从离散到连续”的映射。本质区别在哪?如果给 Embedding 表加一个正交正则化(让所有向量均匀分布在超球面上),它会退化成某种形式的 VQ 吗?
-
Transformer 的 Attention 和 VQ 的最近邻搜索——前者用 softmax(QK^T) 做软分配,后者用 argmin 做硬分配。如果把 VQ 的 argmin 换成 Gumbel-Softmax 做可微的”软量化”,训练会更好还是更差?为什么?
-
推荐系统的”位置编码”是什么? LLM 用位置编码区分 token 顺序。在 SID 的自回归生成中,前两层的码字和后两层在语义上有什么结构化的差异(粗粒度 vs 细粒度)?这种层次结构本身就是一种”位置信息”吗?
-
如果 CTR 模型本身也用自回归架构(输入特征序列逐步生成预测),那 SID 就不需要额外的 Tokenizer——直接让 CTR 模型内部学习码字分配。这条路可行吗?障碍在哪?
-
为什么广告系统不能像 LLM 一样”全部 token 化”? 出价是数字、预算是数字、定向条件是枚举——这些看起来也能离散化。真正的障碍是技术问题(量化损失),还是业务问题(广告主不信任黑盒),还是组织问题(团队边界)?
参考资料
| 资源 | 类型 | 推荐理由 |
|---|---|---|
| 3Blue1Brown - Neural Networks | 视频 | 最直观的神经网络几何理解 |
| The Illustrated Transformer (Jay Alammar) | 博客 | Transformer 最佳图解 |
| Attention Is All You Need (2017) | 论文 | Transformer 原始论文 |
| Neural Discrete Representation Learning (VQ-VAE, 2017) | 论文 | VQ-VAE 开山之作 |
| Deep Interest Network (DIN, 2018) | 论文 | Attention 在推荐中的首次大规模应用 |
| 王喆《深度学习推荐系统》 | 书籍 | 中文最全面的搜广推技术书 |
| Google DSI (2022) | 论文 | 生成式检索的开创性工作 |
| TIGER (2023) | 论文 | SID + 自回归生成推荐 |