从梯度下降到 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 - 学习率 * 梯度
学习率 (Learning Rate)

每一步迈多大。太大会跨过最低点反复震荡;太小会走得极慢,可能困在局部低谷。这是模型训练中最重要的超参数之一。

后面你会看到 RQ-VAE 训练中”限制 Tokenizer 的学习率”来防止漂移——就是利用了这个原理:学习率小 = 参数变化小 = 稳定。

Batch 训练:为什么不是一个一个样本学

如果每看一个样本就更新一次参数(SGD),方向会很不稳定——一个噪声样本可能把参数带偏。

Mini-Batch 训练:每次看一批样本(比如 256 个),计算这批的平均梯度,再更新。好处:

  1. 方向更稳定(多个样本的梯度互相平均)
  2. 利用 GPU 并行计算(GPU 擅长矩阵运算,一批数据刚好是矩阵)
  3. 可以做正则化效果(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 向量在空间中距离近。这就是”表征学习”的核心——把离散符号映射到连续语义空间。

Embedding 的核心局限

每个 ID 的 Embedding 是独立参数。新 item 的 Embedding 初始化为随机向量,必须通过大量数据训练才能有用。这就是”冷启动问题”——新 item 没有足够的行为数据,Embedding 没训好,推荐系统就推不动它。

Semantic ID 试图解决的就是这个问题:不用独立参数表示每个 item,而是用有限码字的组合——新 item 只要内容相似,自动得到相似的 SID。


Part 2:深度学习——让模型自动发现复杂模式

从线性模型到神经网络

线性模型:y = w1*x1 + w2*x2 + ... + b。只能拟合线性关系。

但真实世界中,“用户是否点击广告”取决于特征之间的复杂交互——年龄 * 兴趣 * 时间 * 上下文的非线性组合。

神经网络:多层线性变换 + 非线性激活函数的堆叠,能拟合任意复杂函数。

输入 → [线性变换 → 激活函数] × N层 → 输出

每一层做两件事:

  1. 线性变换z = W * x + b(矩阵乘法,就是加权求和)
  2. 非线性激活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 让模型学会”给不同位置分配不同权重”:

  1. 对每个历史 item 计算一个”相关性分数”
  2. 用 softmax 归一化为概率
  3. 按概率加权聚合历史信息

这就是”注意力”的含义——不是平等看待所有信息,而是聚焦在最相关的部分。


Part 3:Transformer——现代深度学习的基础架构

TRANSFORMER 核心机制
Self-Attention 让序列中的每个位置都能直接关注其他所有位置
Self-Attention 让序列中的每个位置都能直接关注其他所有位置

为什么 Transformer 取代了 RNN

RNN 的致命缺陷:必须顺序处理。处理第 100 个 token 之前必须先处理前 99 个。这意味着:

  • 无法并行化训练(GPU 利用率低)
  • 长序列中早期信息会衰减丢失

Transformer 的解决方案:Self-Attention——每个位置可以直接关注序列中的任何其他位置,不需要顺序传递。

特性RNNTransformer
并行度低(必须顺序)高(所有位置同时计算)
长距离依赖衰减严重任意距离直接连接
计算复杂度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。

自回归 = 逐步生成

生成 “我想买鞋” 的过程:

  1. 输入 [开始] → 预测 → “我” (概率最大)
  2. 输入 [开始, 我] → 预测 → “想”
  3. 输入 [开始, 我, 想] → 预测 → “买”
  4. 输入 [开始, 我, 想, 买] → 预测 → “鞋”
  5. 输入 [开始, 我, 想, 买, 鞋] → 预测 → [结束]

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。

关键约束:词表必须是有限的、固定的。无限词表意味着无限参数,无法训练。

Scaling Law 的数学前提

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,再解码。

为什么用分布?因为我们想让潜在空间是”连续的、有结构的”——相似的输入在潜在空间中距离近,而且空间中任何一个点都能解码出有意义的输出。

重参数化技巧 (Reparameterization Trick)

“从分布中采样”是随机操作,无法反向传播。重参数化技巧的解决方案:

z = mu + sigma * epsilon  (epsilon ~ N(0,1) 是固定噪声)

梯度可以穿过 mu 和 sigma(它们是 Encoder 的输出),而 epsilon 是外部随机数,不需要梯度。

这个思想和 Straight-Through Estimator 异曲同工——都是想办法让”不可微的操作”变得可以训练。

VAE 的损失函数

VAE 的损失有两项:

  1. 重建损失:x_hat 和 x 的差异(让编码保留足够信息)
  2. 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-2014LR (逻辑回归)线性加权简单可解释
2014-2016GBDT + LR树模型做特征交叉非线性交互
2016FM (因子分解机)隐向量内积做二阶交叉稀疏特征交叉
2017Deep & Wide / DeepFMDNN + 浅层交叉并行自动特征交叉
2018DIN (阿里)Attention 加权用户历史用户兴趣多样性
2019DIEN (阿里)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, ...]  (独立参数)

问题:

  1. 冷启动:新 item 的 Embedding 是随机初始化的,需要大量曝光才能训好
  2. 无泛化:两个内容几乎相同的 item(比如同款鞋的不同颜色),它们的 ID Embedding 完全独立,无法互相借力
  3. 词表爆炸:百万级 item × 64 维 Embedding = 2.56 亿参数,只用于 item ID 一个特征
  4. 无 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:向量量化——从连续到离散的桥梁

向量量化的核心机制
VQ 在连续表征和离散符号之间架桥——这是 Semantic ID 的数学基础
VQ 在连续表征和离散符号之间架桥——这是 Semantic ID 的数学基础

为什么需要离散化

连续 Embedding 好用,为什么还要费劲把它变成离散的?

需求连续表征的问题离散编码的优势
自回归生成无法直接用语言模型生成连续向量离散 token 可以逐步生成
有限词表连续空间无限大离散码字有限,可以建词表
压缩存储64 维 float = 256 bytes/item4 个码字索引 = 8 bytes/item
可解释性连续向量人看不懂码字可以关联到语义簇
Scaling Law无限 ID 不共享信息码字共享 → 组合泛化

K-Means 聚类:量化的原型

向量量化的思想来源于聚类。K-Means 把 N 个数据点分成 K 个簇:

  1. 随机初始化 K 个中心点
  2. 每个数据点分配到最近的中心
  3. 每个中心更新为其簇内所有点的平均
  4. 重复 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 的代价

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 均衡码本崩塌的原因 + 分配问题
RQOPQPQ 乘积量化 + Batch 训练
FSQSTE 的代价 + 去掉码本的思路
端到端 vs FreezeVAE 训练 + CTR/CVR 系统的稳定性需求
Scaling LawToken/词表 + 自回归生成 + 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 维度的实验
  • → 进入目标文章:《码本利用率的骗局》

留给你的思考题

Open Questions
  1. Embedding 表 vs SID 码本——二者都是”从离散到连续”的映射。本质区别在哪?如果给 Embedding 表加一个正交正则化(让所有向量均匀分布在超球面上),它会退化成某种形式的 VQ 吗?

  2. Transformer 的 Attention 和 VQ 的最近邻搜索——前者用 softmax(QK^T) 做软分配,后者用 argmin 做硬分配。如果把 VQ 的 argmin 换成 Gumbel-Softmax 做可微的”软量化”,训练会更好还是更差?为什么?

  3. 推荐系统的”位置编码”是什么? LLM 用位置编码区分 token 顺序。在 SID 的自回归生成中,前两层的码字和后两层在语义上有什么结构化的差异(粗粒度 vs 细粒度)?这种层次结构本身就是一种”位置信息”吗?

  4. 如果 CTR 模型本身也用自回归架构(输入特征序列逐步生成预测),那 SID 就不需要额外的 Tokenizer——直接让 CTR 模型内部学习码字分配。这条路可行吗?障碍在哪?

  5. 为什么广告系统不能像 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 + 自回归生成推荐