推荐系统中 Q 值的设计:从训练目标到推理信号

推荐系统中 Q 值的设计:从训练目标到推理信号

一、为什么要聊这个话题

做推荐系统的人,每天都在和 Q 值打交道。粗排要输出 Q 值,精排要融合多个 Q 值,线上打分公式里全是 Q 值。但如果你问"这个 Q 值到底代表什么,为什么可以用它来排序",很多人的回答是"模型输出的分数呗"------这个回答没有错,但也没有说到点子上。

我自己在刚接触这块的时候,也有一堆搅在一起的困惑。loss 是用来训练模型的,Q 值是用来推理排序的,那它们的关系是什么?二分类任务用交叉熵,回归任务用 MSE,loss 的形式不同,Q 值是不是也应该不同?内积为什么能直接当 Q 值,sigmoid 之后的概率不是更直观吗?

这篇文章就是为了把这些问题一次性想清楚。我会以双塔模型为主线,从最简单的情况讲到更复杂的情况,最后拓展到其他模型结构。核心思路只有一条:先想清楚 Q 值应该代表什么,再去理解 loss 和 Q 值之间的关系

二、Q 值的本质------先把目标定清楚

在讨论任何模型结构和公式之前,我想先把一件事说清楚:Q 值的语义是业务目标决定的,它在模型设计之前就应该想清楚

推荐系统的根本任务是什么?是把用户极有可能产生正向互动的资源推送给他。这里的"正向互动"包括点击、完播、评论、分享、收藏、长时间消费等等。因此,一个资源的 Q 值,天然应该反映"这个用户对这个资源产生正向互动的可能性或程度"。Q 值越高,代表这个资源越值得推荐给这个用户。

这个定义听起来很简单,但它有一个重要的推论:Q 值是推理时的排序信号,loss 是训练预测器的工具,两者服务于同一个业务目标,但不是同一个东西

具体来说,loss 衡量的是模型在整个训练集上的预测精度------它告诉我们模型学得好不好。而 Q 值是模型对某个特定(用户,资源)对输出的预测值------它告诉我们这个资源有多适合推荐给这个用户。把 loss 和 Q 值混为一谈是一个很常见的认知错位,后面我还会专门回来说这个问题。

想清楚了这个区分,后面所有的分析都会变得清晰很多。

三、双塔模型的结构选择------为什么用内积

双塔模型的结构很简单:用户塔接收用户特征,输出一个用户向量 \(\mathbf{u}\);物品塔接收物品特征,输出一个物品向量 \(\mathbf{v}\);两个向量做内积 \(\mathbf{u}^\top \mathbf{v}\),得到最终得分。

这里有一个问题值得细想:内积只是一个数学运算,为什么它可以代表用户和物品的匹配程度?

答案是:在模型训练之前,内积什么都代表不了,它只是两个随机向量的点乘,是一个随机数。是 loss 的优化过程,把"匹配程度"这个语义写进了用户向量和物品向量的方向关系里。训练结束后,"用户越可能对某内容产生正向互动,对应向量的内积就越大"这个几何关系被编码进了模型参数里。内积的语义不是天然的,是训练赋予的。

这一点非常关键。它说明 Q 值的合理性不来自"内积"这个操作本身,而来自 loss 优化之后模型所学到的向量空间结构。理解了这一点,我们才能在不同任务下正确判断"什么应该作为 Q 值"。

四、二分类任务的 Q 值------以点击为例

点击任务是最经典的情况,我们以它为起点把逻辑链条建立起来。

标签 \(y \in \{0, 1\}\),1 表示用户点击了,0 表示没有点击。模型的预测值是 \(\hat{y} = \sigma(\mathbf{u}^\top \mathbf{v})\),即对内积做一个 sigmoid 变换,把它压缩到 \((0,1)\) 区间,表示预测的点击概率。loss 是二元交叉熵:

\[\mathcal{L}_{\text{BCE}} = -\left[ y \log \hat{y} + (1-y) \log(1-\hat{y}) \right] \]

训练的过程是:对于正样本(用户确实点击了,\(y=1\)),交叉熵的梯度会把 \(\hat{y}\) 往 1 的方向推,即把内积 \(\mathbf{u}^\top \mathbf{v}\) 往正方向推;对于负样本(用户没有点击,\(y=0\)),梯度把内积往负方向推。经过大量样本的迭代之后,模型学到的向量空间里,"用户会点击的内容"对应的内积就系统性地偏大,"不会点击的内容"内积系统性地偏小。

所以推理时,我们用内积 \(\mathbf{u}^\top \mathbf{v}\) 直接作为点击任务的 Q 值,而不是用 \(\hat{y} = \sigma(\mathbf{u}^\top \mathbf{v})\)。原因是 sigmoid 函数在两端会压缩差异------比如内积从 5 变到 10,对应的 sigmoid 输出从 0.9933 变到 0.99995,差异几乎看不出来;但内积本身保留了从 5 到 10 的完整差异,对于排序来说分辨能力更强。Q 值的核心作用是排序,所以我们需要保留尽可能大的分辨空间,用内积而非概率是更合理的选择。

现在我想回头说一个容易产生的错误想法。有人会觉得:"loss 越小,说明这个资源越好,越应该推给用户。"这个想法是错的,而且错得很有代表性。loss 是衡量模型在整个训练数据集上预测精度的全局指标,它描述的是模型的质量,不是某个具体资源的推荐价值

举个例子:假设某个模型训练完之后 loss=0.3,另一个模型 loss=0.5,那前者比后者预测得更准。但对于一个具体的(用户 A,资源 X)对,正确的问题不是"这个 loss 是多少",而是"模型对这个对输出的 Q 值是多少"。模型训练好之后,它对每个(用户,资源)对都会输出一个内积值,这个内积值才是我们在推理时关心的排序信号。

五、回归任务的 Q 值------以时长为例

时长任务是让很多人困惑的地方,值得专门拆解。

困惑的来源是这样的:MSE 的 loss 最小化条件是"预测值尽量接近标签",而不是"内积越大越好"。那内积还能直接作为 Q 值吗?它代表什么语义?

要回答这个问题,需要分两步走。

第一步:理解标签的预处理。 原始时长是秒数,可能从 0 到几千秒不等,直接用来训练回归模型会有量纲和数值稳定性的问题。工业上通常把时长归一化到 \([0,1]\),比如除以一个饱和值(如 1440 秒,即 24 分钟)并 clip:

\[y = \text{clip}\left(\frac{\text{duration}}{1440}, 0, 1\right) \]

这个归一化的效果是:"标签越接近 1"等价于"用户消费时长越长"。标签本身就编码了"越长越好"这个业务语义。

第二步:理解训练结束后的状态。 模型的预测值是 \(\hat{y} = \sigma(\mathbf{u}^\top \mathbf{v})\),loss 是:

\[\mathcal{L}_{\text{MSE}} = \left( \sigma(\mathbf{u}^\top \mathbf{v}) - y \right)^2 \]

对于时长长的(用户,资源)对(\(y\) 接近 1),MSE 的梯度会把 \(\hat{y}\) 往 1 的方向推,即把内积 \(\mathbf{u}^\top \mathbf{v}\) 往正方向推;对于时长短的对(\(y\) 接近 0),内积被往负方向推。训练结束后,内积的大小依然是时长长短的单调信号。

所以,时长任务推理时仍然可以用内积作为 Q 值,语义是"这个用户在这个内容上的预期消费时长越长,内积越大,Q 值越高"。这和点击任务的逻辑本质上是一样的------只是"正向互动"的定义从"点击"换成了"消费时长长",内积都因为 loss 的优化而具备了排序所需的单调性。

当然,工程上完全可以不做归一化,直接用原始秒数作为标签,同时去掉 sigmoid,让内积直接回归原始时长,这在数学上是成立的。选择归一化到 [0,1][0,1]

0,1\] 再配合 sigmoid,主要是出于训练稳定性的考虑:sigmoid 把内积的输出范围压缩在一个有界区间内,梯度不会因为预测值和标签之间的巨大数值差距而在早期训练阶段出现爆炸或消失的问题。此外,归一化后的标签让不同资源类型(短视频几秒、长视频几百秒)的时长可以在同一个尺度下比较,模型不需要去拟合跨越多个数量级的目标值,收敛更快也更稳定。至于 sigmoid 是否必须保留、归一化的饱和值选多少,这些都是可以根据实际数据分布调整的工程决策,没有唯一答案。 ## 六、当 loss 更复杂时------以 EGMN 为例 前面两节的逻辑都有一个共同点:模型最终输出的是一个标量(内积),Q 值就是这个标量。但当我们对时长分布的建模要求更高时,这个简单的框架就不够用了。 真实的用户消费时长分布不是一个简单的单峰分布。它有一个典型的多峰形态:大量用户快速划走(几秒),少量用户深度消费(几分钟甚至更长),中间还有各种不同程度的消费模式。如果用一个点估计来拟合这种分布,会丢失大量信息。 EGMN(指数-高斯混合网络)的解决思路是:不再让模型输出一个数,而是输出一个完整的概率分布,用来描述"这个用户在这个内容上,消费时长为 \\(t\\) 秒的概率有多大"。这个分布是一个混合分布: \\\[p(t) = \\pi_0 \\cdot \\lambda e\^{-\\lambda t} + \\sum_{k=1}\^{K} \\pi_k \\cdot \\mathcal{N}\^+(t; \\mu_k, \\sigma_k\^2) \\

其中指数分量负责建模"快速划走"这个峰,\(K\) 个截断高斯分量负责建模各种"中等到深度消费"的峰,\(\pi_k\) 是每个分量的混合权重。

训练这个模型使用三项 loss 的组合:

\[\mathcal{L} = \mathcal{L}{\text{NLL}} + \alpha \mathcal{L}{\text{entropy}} + \beta \mathcal{L}_{\text{reg}} \]

\(\mathcal{L}{\text{NLL}}\) 是负对数似然,推动分布的形状在真实时长处概率密度高;\(\mathcal{L}{\text{reg}} = |\mathbb{E}[t] - y|\) 是 L1 回归损失,推动分布的期望值在数值上接近真实时长;\(\mathcal{L}_{\text{entropy}}\) 是熵正则项,防止所有权重塌缩到单一分量。

在这个框架下,"内积"的概念已经不再适用------模型输出的是分布参数 \((\pi_k, \lambda, \mu_k, \sigma_k)\),没有一个单独的内积可以作为 Q 值。因此 Q 值应该用混合分布的期望来表达:

\[Q_{\text{dur}} = \mathbb{E}[t] = \frac{\pi_0}{\lambda} + \sum_{k=1}^{K} \pi_k \mu_k \]

这个期望值为什么可以作为 Q 值?因为三项 loss 的共同作用保证了单调性:对于真正深度消费的(用户,资源)对,三项 loss 合力推动 \(\pi_0\) 减小、\(\lambda\) 减小(\(1/\lambda\) 增大)、高斯分量权重 \(\pi_k\) 增大、均值 \(\mu_k\) 右移,最终使 \(\mathbb{E}[t]\) 增大。对于快速划走的对,方向完全相反,\(\mathbb{E}[t]\) 减小。因此"用户消费越久,\(\mathbb{E}[t]\) 越大,Q 值越高"这条单调链是成立的。

EGMN 这个例子给了我们一个重要的启示:Q 值的表达方式必须跟 loss 的设计保持一致,不能脱离训练目标去定义推理信号。当模型从"输出一个数"变成"输出一个分布"时,Q 值也必须从"内积"变成"分布的期望",背后的逻辑是一样的,只是具体形式跟着训练目标走。

七、不只是双塔------其他模型结构的 Q 值设计思路

双塔模型只是推荐系统中的一种典型结构,它的特殊性在于用户和物品特征在最后才通过内积交汇。其他模型结构的 Q 值设计思路不完全相同,但背后的逻辑是统一的。

交叉特征模型(如 DCN、DIN) 的特点是用户和物品特征在网络内部就发生了深度交叉,经过多层 MLP 后直接输出一个标量 logit,再经过 sigmoid 得到预测概率。这类模型没有独立的用户向量和物品向量,因此也没有"内积"的概念。Q 值直接取输出的 logit(sigmoid 之前的值)或预测概率,语义上与双塔模型的内积完全对应------都是"该(用户,资源)对发生正向互动的可能性"的单调信号,只是计算路径不同。

序列推荐模型(如 SASRec、BERT4Rec) 通过 attention 机制对用户的历史行为序列建模,输出一个融合了时序信息的用户序列表示向量 \(\mathbf{h}\),然后与目标物品向量 \(\mathbf{v}\) 做内积打分。这个结构和双塔模型在推理阶段非常相似,Q 值同样是内积 \(\mathbf{h}^\top \mathbf{v}\),区别在于用户侧的向量来自序列建模而非简单的用户特征编码,因此携带了更丰富的行为序列信息。

生成式推荐(如基于 LLM 的推荐) 的推理方式完全不同,模型通过自回归生成候选资源的 ID 或描述,Q 值的概念退化为生成序列的概率或 beam search 的累积得分。虽然计算方式和双塔模型几乎没有共同点,但语义上仍然是一样的:生成概率越高,说明模型认为这个资源对这个用户越合适,排序分数越高。

三类模型放在一起看,可以得出一个统一的结论:不同模型结构下 Q 值的具体计算方式不同,但它们都是同一个业务语义的不同实现------"这个资源对这个用户的匹配程度"。换了模型结构,Q 值的表达形式随之变化,但它所代表的业务含义始终如一。

八、多目标融合------Q 值的组合使用

工业推荐系统中通常不止一个优化目标。点击、时长、互动(点赞、评论、分享)、完播等目标各有各的 Q 值,最终需要通过一个融合公式组合成一个综合排序分数。

最直接的融合方式是线性加权

\[\text{score} = w_1 \cdot q_{\text{click}} + w_2 \cdot q_{\text{dur}} + w_3 \cdot q_{\text{interact}} \]

这种方式直观,但有几个问题:不同 Q 值的量纲和分布范围差异很大,直接加权会导致某个目标因为数值偏大而主导排序;权重调参成本高,而且各目标之间没有业务逻辑上的优先级关系。

更常见的是乘法融合,比如:

\[\text{score} = q_{\text{click}} \cdot \left(1 + w_1 \cdot q_{\text{dur}} + w_2 \cdot q_{\text{interact}}\right) \]

这个公式的业务语义很清晰:"先保证点击,再在点击的基础上奖励时长和互动"。点击 Q 值作为乘法因子,让一个用户根本不会点击的内容无论时长 Q 值多高都得不了高分,符合推荐的业务逻辑------没有点击,时长和互动根本不会发生。

一些平台还会使用带非线性变换的加权融合

\[\text{score} = \sum_i w_i \cdot f_i(q_i) \]

其中 \(f_i\) 可以是对数变换 \(\log(1 + q_i)\)、分段线性函数或其他单调变换。对数变换的作用是压制极端大值,防止某条时长特别长的内容因为一个异常值而霸占排名。

在使用任何融合公式之前,有一件事必须处理:各个 Q 值的量纲和分布要先对齐 。点击 Q 值是一个 logit,通常在 \((-\infty, +\infty)\);时长 Q 值如果用内积,也是 logit;如果用 EGMN 的期望值,则是秒数,量级可能差了一两个数量级。不对齐就直接融合,权重设置会完全失去物理意义,调参也无从下手。常用的对齐方法是分别做 min-max 归一化或对数变换,把各 Q 值映射到相近的量级再融合。

九、总结

把全文的核心逻辑串一遍:推荐系统的目标是把用户极有可能产生正向互动的资源推送给他,这个目标在模型设计之前就应该想清楚,它决定了 Q 值应该代表什么。loss 是训练预测器的工具,它的作用是把业务目标编码进模型的参数里,使得训练结束后模型的输出(内积、期望值、输出 logit 等)具备了排序所需的单调性------用户越满意的资源,模型输出的值越大,Q 值越高。

不同的任务性质、不同的 loss 设计、不同的模型结构,会导致 Q 值的具体表达方式不同:二分类任务用内积,MSE 回归任务也用内积(因为标签归一化保证了语义一致),EGMN 这类分布建模任务用期望值,交叉特征模型用输出 logit,生成式模型用生成概率。形式不同,逻辑统一。

最后一句话记住:loss 告诉我们模型学得好不好,Q 值告诉我们这个资源值不值得推荐,两者是不同层面的概念,但都服务于同一个目标------帮用户找到他真正想要的内容。