街角新开了家小餐馆,老板发现一个奇怪的现象:很多顾客站在门口对着菜单看了半天(点击),掏出手机把几道菜记进“想吃清单”(收藏),最后真正坐下点单的却没几个(购买)。他翻着三本互不相通的笔记本,越看越糊涂——这三个动作明明来自同一个顾客,为什么不能放在一起分析? 推荐系统里的多任务推荐(Multi-task Recommendation),正是为了解决老板的烦恼而生:点击、收藏、购买是同一个用户对同一件商品在不同阶段的反馈。与其为每个行为各训练一个模型、各记一本账,不如训练一个共享底层、多任务输出的模型,让三本账互相印证、彼此补全。购买数据太稀疏?用点击和收藏来补。点击噪音太大?用购买来纠偏。 这篇文章会从餐厅老板的三本账出发,讲清楚多任务推荐的模型结构(共享底层 + 任务塔)、损失设计(权重与梯度)、业界经典方案(ESMM 全域建模、MMOE 专家融合),以及如何评估调优,让你从“只懂单目标排序”进阶到“一套模型服务多个业务目标”。

岗位关联

学会多任务推荐,意味着你能用一套模型同时服务点击、收藏、购买等多个业务目标,这是推荐算法从“单点优化”走向“系统优化”的必修课,也是算法工程师突破业务瓶颈、走向高级岗位的常见能力分水岭。

目录
  1. 可视化演示
  2. 多任务基础:三本账为什么必须合起来看
  3. 共享底层结构:一个共用的口味库
  4. 任务专属塔:各岗位的独立判断
  5. 损失与梯度:三本账怎么权衡才不打架
  6. ESMM全域建模:把目光从店内挪到整条街
  7. MMOE专家融合:请几位顾问,让门控决定听谁的
  8. 评估与调优:三本账的综合体检
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

模拟Shared-Bottom多任务架构的共享特征提取与任务塔分流,展示损失加权与任务相关性对推荐效果的影响。

本节配有交互动效(进入视口后自动加载,约 3KB)。

模式1:Shared-Bottom架构 共享层提取通用特征表示 三任务塔独立预测CTR/CVR/收藏 y_task = Tower_task(Shared(x)) 共享减少参数但任务冲突时受限。

多任务基础:三本账为什么必须合起来看

街角新开的小餐馆,老板同时记三本账:一本记“谁在门口看过菜单”,一本记“谁把菜记进了想吃清单”,一本记“谁真的付了钱”。他很快发现,第三本账总是很薄——十个人看菜单,只有一两个下单;可前两本账又太吵,路过看热闹的人也记在里面。

推荐系统面对的是同样的世界:用户对商品的反馈天然分成三层漏斗——曝光后点击(click)、点击后收藏(favorite)、收藏后购买(purchase)。点击数据量大但噪音多,购买信号最干净却极其稀疏。多任务推荐(Multi-task Recommendation)的思路,就是让一个模型同时预测这三个目标,用高频行为为低频行为“搭桥”,就像老板用“看菜单的人很多”去解释“为什么下单的人少”。

既然要同时学会三件事,第一件事就是定义“总成绩”。每个任务都有自己的损失函数,通常是交叉熵(Cross Entropy),衡量该任务预测概率和真实标签的差距;把三个损失按权重相加,就得到联合损失:

老板把三本账钉在一起,让“看菜单的人多”这个高频信息去喂养共享经验,“下单的人少”这个低频信号校正方向——这就是多任务推荐最朴素的起点。

Ltotal=λ1Lclick+λ2Lfavorite+λ3Lpurchase\displaystyle \mathcal{L}_{total}=\lambda_{1}\mathcal{L}_{click}+\lambda_{2}\mathcal{L}_{favorite}+\lambda_{3}\mathcal{L}_{purchase}
这个公式说明:多任务推荐的总损失不是三个任务损失的简单相加,而是乘上各自的权重再求和。权重越大,该任务在训练中的“话语权”越大。
  1. 任务损失项$\mathcal{L}_{click}$、$\mathcal{L}_{favorite}$、$\mathcal{L}_{purchase}$ 分别是点击、收藏、购买三个任务的损失值,衡量各自预测概率和真实标签的差距,值越小代表该任务预测越准。
    Lk=−1N∑i=1N[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\mathcal{L}_{k}=-\frac{1}{N}\sum_{i=1}^{N}\left[y_{i}\log\hat{y}_{i}+(1-y_{i})\log(1-\hat{y}_{i})\right]
  2. 权重系数$\lambda_{1}$、$\lambda_{2}$、$\lambda_{3}$ 调节三个任务在总损失中的话语权。购买是最终商业目标,通常权重会调得更高。
    λ1:λ2:λ3=1:1.5:2.5\lambda_{1}:\lambda_{2}:\lambda_{3}=1:1.5:2.5
  3. 加权求和总损失 $\mathcal{L}_{total}$ 是三者加权之和,模型训练的全部目标就是让这个总和不断下降,三个任务一起变好。
    Ltotal=λ1Lclick+λ2Lfavorite+λ3Lpurchase\mathcal{L}_{total}=\lambda_{1}\mathcal{L}_{click}+\lambda_{2}\mathcal{L}_{favorite}+\lambda_{3}\mathcal{L}_{purchase}

共享底层结构:一个共用的口味库

老板慢慢发现,三个岗位其实共用同一个直觉:这位顾客是偏辣还是偏甜,喜欢实惠还是追求精致。如果每个岗位各记一套“口味档案”,不仅重复劳动,三份档案还会互相矛盾。

共享底层(Shared Bottom)结构就是这个“公共口味库”:模型把所有输入特征——用户画像、商品属性、时间上下文——先送入底部几层共享网络,提取一份通用的特征表示。它不区分任务,只回答“这个用户和这个商品到底有没有缘分”。

数学上,共享底层做的事就是一次带激活函数的非线性变换:

一个口味库,三份岗位共用。参数少了不容易过拟合;某个菜品买的人少,也能从“看过的人很多”里学到经验——共享底层正是多任务推荐对抗数据稀疏的底气。

h=ReLU(Wsx+bs)\displaystyle h=\mathrm{ReLU}(W_{s}x+b_{s})
$x$ 是原始特征,$W_{s}$ 和 $b_{s}$ 是所有任务共用的参数,$h$ 是提炼出的通用表示。三个任务塔后续都从这份“口味报告”出发做判断。
  1. 输入特征$x$ 是拼接好的特征向量,包含用户特征、物品特征、上下文特征,这是所有任务的共同原料。
    x=[xuser;xitem;xcontext]x=[x_{user};x_{item};x_{context}]
  2. 共享权重$W_{s}$ 是共享层的权重矩阵,$b_{s}$ 是偏置,所有任务共用这一套参数,被三个任务的梯度一起更新。
    z=Wsx+bsz=W_{s}x+b_{s}
  3. 激活函数$\mathrm{ReLU}$ 把线性结果做非线性映射,让网络有能力表达“只有某些特征同时出现才相关”这类复杂模式。
    ReLU(z)=max⁡(0,z)\mathrm{ReLU}(z)=\max(0,z)
  4. 共享表示$h$ 是输出的通用向量,后续每个任务塔都从它出发做自己的专业判断。
    h=ReLU(Wsx+bs)h=\mathrm{ReLU}(W_{s}x+b_{s})

任务专属塔:各岗位的独立判断

口味库再准,也不能直接回答“这位顾客会不会下单”。同样是爱吃辣的顾客,有人看完菜单就下单,有人只是进来吹吹空调再走。迎宾、收藏簿管理员、后厨下单员,必须在同一个口味库之上做各自的专业判断。

于是,模型在每个任务头上加一个“任务专属塔”(Task-specific Tower)。塔通常是一个小型神经网络,参数只属于该任务,负责从共享表示 $h$ 中提炼出“本任务关心”的信号,并输出一个概率。这样的设计让底层“求同”、顶层“存异”,互不干扰又共享知识。

任务塔的计算可以写成一次线性变换加 Sigmoid 激活:

底层共享是“求同”,顶层分离是“存异”。老板的直觉和各岗位的专业判断互不干扰,又共享同一套顾客理解——这份“求同存异”的架构,构成了几乎所有多任务推荐模型的基本盘。

y^k=σ(WkTh+bk)\displaystyle \hat{y}_{k}=\sigma(W_{k}^{T}h+b_{k})
$h$ 是共享底层的输出,$W_{k}$、$b_{k}$ 是第 $k$ 个任务塔自己的参数,$\sigma$ 把分数压成 (0,1) 区间的概率。
  1. 任务索引$k$ 表示第几个任务,比如 $k=1$ 是点击、$k=2$ 是收藏、$k=3$ 是购买。
    k∈{1,2,3}k\in\{1,2,3\}
  2. 共享输入$h$ 是共享底层输出的通用表示,三个塔拿到的是同一份“口味报告”,保证各任务站在同一起跑线上。
    h∈Rdh\in\mathbb{R}^{d}
  3. 专属参数$W_{k}$ 和 $b_{k}$ 是第 $k$ 个塔自己的权重与偏置,只由该任务的损失梯度更新,其他任务无权改动。
    zk=WkTh+bkz_{k}=W_{k}^{T}h+b_{k}
  4. 概率输出$\sigma$ 是 Sigmoid 函数,把任意实数压到 0 到 1 之间,作为该任务的预测概率。
    y^k=11+e−zk\hat{y}_{k}=\frac{1}{1+e^{-z_{k}}}

损失与梯度:三本账怎么权衡才不打架

权重怎么定?老板一开始给三本账同样的重视,结果发现购买账太薄、噪声大,梯度像醉汉走路;把购买权重拉满,又会被少数极端样本带偏。更麻烦的是,点击和购买两个任务的更新方向经常“打架”——一个想让参数往左,一个想往右,这就是多任务里的梯度冲突。

解决梯度冲突,除了手工调权重,还有一种更优雅的思路——不确定性加权(Uncertainty Weighting)。它把每个任务的权重和学习过程挂钩,让模型自己在训练中学出“这个任务我有多大把握”:把握大的信得多,把握小的信得少。

其损失形式如下(源自 Kendall 等人的经典工作):

老板学会了看账本的信噪比:越混乱的账本越少采信,越可靠的账本越重视。梯度冲突不再靠拍脑袋调权,而是被写进了损失函数的自我调节机制里。

L=∑k(12σk2Lk+log⁡σk)\displaystyle \mathcal{L}=\sum_{k}\left(\frac{1}{2\sigma_{k}^{2}}\mathcal{L}_{k}+\log\sigma_{k}\right)
每个任务的权重不再是人工预设的常数,而是由可学习的“不确定性” $\sigma_k$ 自动推导:任务越吵(不确定性大),权重自动变小。
  1. 不确定性参数$\sigma_{k}$ 是第 $k$ 个任务可学习的不确定性,相当于模型对“这个任务难不难、吵不吵”的自我评估。
    σk>0\sigma_{k}>0
  2. 自适应权重$\frac{1}{2\sigma_{k}^{2}}$ 作为第 $k$ 个任务的权重——不确定性越大压得越轻,任务越干净放得越重。
    wk=12σk2w_{k}=\frac{1}{2\sigma_{k}^{2}}
  3. 正则项$\log\sigma_{k}$ 是保险丝,防止 $\sigma_{k}$ 无限变大把损失压成零,让权重不会失去意义。
    Ltotal=∑k(wkLk+log⁡σk)\mathcal{L}_{total}=\sum_{k}\left(w_{k}\mathcal{L}_{k}+\log\sigma_{k}\right)

ESMM全域建模:把目光从店内挪到整条街

老板一直在琢磨“进店顾客为什么不买”,直到有一天他意识到:最大的问题在店外——绝大多数人路过根本没进来。对这些人,他的三本账一片空白。只看进店的人,永远学不会“为什么有人不进门”。

这正是传统 CVR(购买转化率)模型的致命伤:它只在“点击过”的样本上训练,天然看不见没点击的曝光样本,造成样本选择偏差(Sample Selection Bias);而点击样本又远少于曝光样本,数据稀疏雪上加霜。阿里提出的 ESMM(Entire Space Multi-task Model,全空间多任务模型)把建模范围扩到全部曝光样本,同时学习 pCTR 和 pCVR,再用概率链把两者串起来。

ESMM 的核心是一个链式分解公式:

老板终于把目光从店内挪到整条街:每个路过的人都是宝贵的样本。点击多而购买少、点击少却购买多的商品,在全空间里互相补充,CVR 数据稀疏的难题由此大大缓解。

pCTCVR=p(click=1∣x)×p(purchase=1∣click=1,x)=pCTR×pCVR\displaystyle pCTCVR=p(click=1\mid x)\times p(purchase=1\mid click=1,x)=pCTR\times pCVR
这个公式把“曝光后既点击又购买”的联合概率,拆成“曝光→点击”和“点击→购买”两步概率的乘积,让 CVR 塔在全空间被间接训练。
  1. 全域目标$pCTCVR$ 是“曝光后既点击又购买”的联合概率,它的真实标签在全部曝光样本上都存在,可以直接监督训练。
    pCTCVR=p(click=1,purchase=1∣x)pCTCVR=p(click=1,purchase=1\mid x)
  2. 点击率$pCTR=p(click=1\mid x)$ 表示曝光后点击的概率,数据丰富,训练充分,由点击塔输出。
    pCTR=p(click=1∣x)pCTR=p(click=1\mid x)
  3. 点击后转化$pCVR=p(purchase=1\mid click=1,x)$ 表示点击后购买的概率,它不直接用自己的标签在点击空间训练,而是通过乘法链在全空间被间接学习。
    pCVR=p(purchase=1∣click=1,x)pCVR=p(purchase=1\mid click=1,x)
  4. 链式分解行为是先点击后购买的先后过程,联合概率等于两步概率相乘,全空间标签通过乘积约束同时喂养两个子网络。
    pCTCVR=pCTR×pCVRpCTCVR=pCTR\times pCVR

MMOE专家融合:请几位顾问,让门控决定听谁的

店做大了,老板请来三位顾问:一位懂口味搭配,一位懂价格敏感度,一位懂季节时令。三位顾问各有所长,但同一个顾客进门,到底该听谁的?老板让领班根据顾客特征现场判断——这次主要听口味顾问的,下次多听价格顾问的。

MMOE(Multi-gate Mixture-of-Experts,多门控专家混合)把这种“临时择人”变成网络结构:底层不再是单一网络,而是 $n$ 个并行的“专家网络”,每个专家擅长一种模式;每个任务配一个“门控网络”,输出对这个顾客最合适的专家权重组合,加权混合后送入任务塔。

用公式描述这个“听谁的”过程:

老板发现,“什么时候听谁”比“永远听谁”更重要。MMOE 让每个任务都能灵活挑选专家组合,即使点击和购买两个目标相关性不高,也能各取所需、减少互踩,这是它相比单一共享底层的核心优势。

hk=∑i=1ngik(x)fi(x),gk(x)=Softmax(Wgkx)\displaystyle h^{k}=\sum_{i=1}^{n}g_{i}^{k}(x)f_{i}(x), \qquad g^{k}(x)=\mathrm{Softmax}(W_{g}^{k}x)
左边是任务层的输入:把 $n$ 个专家输出按门控权重加权求和;右边是门控网络:把打分变成和为 1 的权重分布。
  1. 专家网络$f_{i}(x)$ 是第 $i$ 个专家对输入 $x$ 的变换结果,每个专家相当于一种“口味模型”,擅长捕捉一种模式。
    fi(x)=ReLU(Wix+bi)f_{i}(x)=\mathrm{ReLU}(W_{i}x+b_{i})
  2. 门控权重$g_{i}^{k}(x)$ 是任务 $k$ 分给第 $i$ 个专家的权重,表示“这个任务这次该听谁多少”。
    ∑i=1ngik(x)=1\sum_{i=1}^{n}g_{i}^{k}(x)=1
  3. 门控网络$g^{k}(x)=\mathrm{Softmax}(W_{g}^{k}x)$ 用 Softmax 把门控分数归一化成总和为 1 的权重分布。
    gik(x)=ewiTx∑j=1newjTxg_{i}^{k}(x)=\frac{e^{w_{i}^{T}x}}{\sum_{j=1}^{n}e^{w_{j}^{T}x}}
  4. 加权融合$h^{k}$ 是任务 $k$ 专属的混合表示,再喂给该任务塔做最终预测。
    hk=∑i=1ngik(x)fi(x)h^{k}=\sum_{i=1}^{n}g_{i}^{k}(x)f_{i}(x)

评估与调优:三本账的综合体检

三本账改进了没有?老板不再单看某一本,而是定期做综合体检:每本账分别看“记录质量”(AUC),再按每位熟客到店的次数加权平均,算一个总满意度(GAUC);最后再挑几家分店做小范围试运营(A/B 实验)验证。

多任务推荐的评估,最容易犯的错是只看一个指标。正确做法是:对点击、收藏、购买分别计算 AUC,观察有没有任务被“牺牲”;再用 GAUC 从用户维度衡量排序整体质量,因为不同用户的曝光量差异巨大,直接把所有样本混在一起算 AUC 会被头部用户主导。

GAUC 的计算公式:

体检之后是调优:观察各任务损失是否同步下降、用早停防止某个任务过拟合、调整任务权重,再到线上用小流量 A/B 灰度验证。老板的三本账,终于从“记流水账”升级成了“经营仪表盘”。

GAUC=∑u∈UAUCu⋅nu∑u∈Unu\displaystyle GAUC=\frac{\sum_{u\in U}AUC_{u}\cdot n_{u}}{\sum_{u\in U}n_{u}}
把所有用户按人分组,先算出每个人的 AUC,再按曝光次数加权平均。曝光多的用户对总指标贡献大,这更贴近真实业务感受。
  1. 用户分组$u$ 遍历用户集合 $U$,把同一个用户的样本视为一组,每组单独计算 $AUC_{u}$。
    AUCu=1MuNu∑i∈Pu∑j∈Nu1[si>sj]AUC_{u}=\frac{1}{M_{u}N_{u}}\sum_{i\in P_{u}}\sum_{j\in N_{u}}\mathbf{1}[s_{i}>s_{j}]
  2. 曝光权重$n_{u}$ 是用户 $u$ 的曝光次数,作为加权权重,曝光多的用户对整体指标影响更大。
    nu=用户 u 的曝光样本数n_{u}=\text{用户 }u\text{ 的曝光样本数}
  3. 加权平均分子是所有用户 $AUC_{u}\times n_{u}$ 之和,分母是总曝光数,结果就是全局的 GAUC。
    GAUC=∑uAUCu⋅nu∑unuGAUC=\frac{\sum_{u}AUC_{u}\cdot n_{u}}{\sum_{u}n_{u}}

AI 应用场景

电商信息流的多行为排序

阶段:离线模型训练 + 在线排序

解决的问题:传统排序模型只预测点击率,收藏和购买行为被单独建模或直接忽略,导致“标题党商品点击高、转化低”却排在前面。多任务推荐让一个模型同时输出点击、收藏、购买三个概率,再用业务加权的融合公式计算排序分,播放、收藏、成交一起优化。

具体案例:某电商 App 首页“猜你喜欢”信息流,用户行为日志含曝光、点击、收藏、下单。算法团队训练共享底层 + 三塔模型,购买塔权重最高,线上成交转化率提升 12%,人均收藏量也同步上涨,验证了“以点击补购买、以收藏做桥梁”的联动效果。

广告投放的 CVR 预估

阶段:广告召回与出价预估

解决的问题:广告转化率(CVR)数据稀疏且存在样本选择偏差——传统模型只在“点击后样本”上训练,对点击率低的商品完全是盲区。ESMM 在曝光全空间用 pCTR × pCVR 链式建模,让没点击的曝光样本也参与训练。

具体案例:某效果广告平台为新品投放训练 CVR 模型。改用 ESMM 后,点击率低但购买意愿强的长尾商品也能被准确预估,广告主以更低的出价拿到成交,平台整体广告消耗和 ROI 双升。

内容平台的互动多目标

阶段:召回与粗排模型

解决的问题:短视频场景里点赞、收藏、完播等多个反馈目标相关性复杂,单一模型难以兼顾。“点赞多完播差”和“完播高点赞低”的内容都需要照顾,MMOE 用门控动态组合专家,让每个互动目标挑自己需要的特征模式。

具体案例:某短视频 App 用 MMOE 同时预测点击、收藏、完播三个目标,相比 Shared Bottom,长视频内容的完播率预估 AUC 提升 2%,人均观看时长明显上升,评论区活跃度也随之改善。

Python 演示

python83 行
import numpy as np  def sigmoid(x):    return 1.0 / (1.0 + np.exp(-x))  def bce(y_true, y_pred):    eps = 1e-7    return -np.mean(y_true * np.log(y_pred + eps) +                    (1 - y_true) * np.log(1 - y_pred + eps))  class SharedBottomMTL:    def __init__(self, input_dim=8, hidden_dim=16):        self.Ws = np.random.randn(input_dim, hidden_dim) * 0.1        self.bs = np.zeros((1, hidden_dim))        self.towers = {}        for name in ('click', 'favorite', 'purchase'):            self.towers[name] = {                'W': np.random.randn(hidden_dim, 1) * 0.1,                'b': np.zeros((1, 1))            }     def forward(self, X):        self.h = np.maximum(0, X @ self.Ws + self.bs)        self.outs = {}        for name, p in self.towers.items():            self.outs[name] = sigmoid(self.h @ p['W'] + p['b'])        return self.outs     def train_step(self, X, labels, lr=0.2, weight=None):        if weight is None:            weight = {'click': 1.0, 'favorite': 1.5, 'purchase': 2.5}        m = X.shape[0]        self.forward(X)        d_h = np.zeros_like(self.h)        total_loss = 0.0        for name, p in self.towers.items():            y = labels[name]            y_hat = self.outs[name]            w = weight[name]            total_loss += w * bce(y, y_hat)            dy = (y_hat - y) / m * w            p['W'] -= lr * (self.h.T @ dy)            p['b'] -= lr * np.sum(dy, axis=0, keepdims=True)            d_h += dy @ p['W'].T        d_h *= (self.h > 0)        self.Ws -= lr * (X.T @ d_h)        self.bs -= lr * np.sum(d_h, axis=0, keepdims=True)        return total_loss  def make_data(n=2000):    rng = np.random.default_rng(7)    X = rng.standard_normal((n, 8))    p_click = sigmoid(0.8 * X[:, 0] + 0.5 * X[:, 1])    p_fav = sigmoid(0.6 * X[:, 2] + 0.4 * X[:, 3] + p_click)    p_buy = sigmoid(0.7 * X[:, 4] + 0.8 * p_click + 0.3 * p_fav)    labels = {        'click': (rng.random(n) < p_click).astype(float).reshape(-1, 1),        'favorite': (rng.random(n) < p_fav).astype(float).reshape(-1, 1),        'purchase': (rng.random(n) < p_buy).astype(float).reshape(-1, 1),    }    return X, labels  def main():    X, labels = make_data()    model = SharedBottomMTL(input_dim=8, hidden_dim=16)    for epoch in range(100):        idx = np.random.default_rng(epoch).permutation(2000)[:256]        batch = {k: v[idx] for k, v in labels.items()}        loss = model.train_step(X[idx], batch)        if epoch % 20 == 0:            print('epoch %3d loss %.4f' % (epoch, loss))    out = model.forward(X[:5])    for name in ('click', 'favorite', 'purchase'):        print(name, np.round(out[name].flatten(), 3))  if __name__ == '__main__':    main()
目的:用 NumPy 从零实现一个共享底层 + 三任务塔的多任务推荐模型,在模拟的点击/收藏/购买数据上训练,验证“加权联合损失 + 共享表示”的核心思想。
  1. self.Ws = np.random.randn(input_dim, hidden_dim) * 0.1随机初始化共享底层权重,乘 0.1 让初始输出贴近零,训练更稳定
  2. self.h = np.maximum(0, X @ self.Ws + self.bs)共享底层前向传播,ReLU 激活提取通用特征表示
  3. self.outs[name] = sigmoid(self.h @ p['W'] + p['b'])每个任务塔用专属参数把共享表示变成 0~1 概率
  4. total_loss += w * bce(y, y_hat)加权聚合三个任务的交叉熵损失
  5. dy = (y_hat - y) / m * w交叉熵对输出的梯度,再乘以任务权重
  6. d_h += dy @ p['W'].T把该任务的梯度回传到共享层,三个任务累加
  7. d_h *= (self.h > 0)ReLU 反传掩码,只有激活过的神经元才接收梯度
  8. X, labels = make_data()生成模拟数据,购买概率显式依赖点击和收藏

常见误区

误区点击、收藏、购买是三种不同的用户意图,放在一个模型里会互相干扰。分开训练三个独立模型,每个模型更专注,效果自然更好。

正解分开训练时,购买模型只能看到稀疏的购买标签,样本少、学不稳。共享底层让高频的点击行为训练出的通用表示,直接为低频的购买任务提供先验,工业界大量实践表明联合建模通常优于三个单模型。但要注意,如果任务梯度冲突严重,需要引入权重调节或门控结构,而不是退回单模型。

为何常见:“专人专事”是日常直觉,容易忽略推荐场景中的数据量差异——购买样本太少,单模型根本学不到足够泛化的规律。

误区既然购买是最终商业目标,把购买任务的损失权重设成最大值,模型就会最重视购买,效果最好。

正解损失权重不等于业务重要性。购买数据稀疏、噪声大,权重过大会放大梯度的方差,让共享层被少数样本带偏,训练震荡。合理的做法是用适中权重加更多轮次观察,或用不确定性加权让模型自适应决定任务权重,而不是把 λ 直接拉到最大。

为何常见:把“这个目标对我多重要”和“这个任务的梯度有多可靠”混为一谈,忽略了数据质量对梯度的影响。

误区ESMM 只是把点击和购买两个任务放进共享底层一起训练,多加一个损失项而已。

正解ESMM 的精髓在于“全空间”和“链式分解”:CVR 塔不在点击子空间上直接训练,而是在全部曝光样本上通过 pCTCVR = pCTR × pCVR 间接学习,从而消除样本选择偏差。去掉这个分解,就退化成普通 MTL,无法解决“只看点击样本”带来的盲区。

为何常见:只看到“多任务”三个字,没有深究它解决的核心问题——样本选择偏差,容易把 ESMM 和普通 MTL 划等号。

误区多任务推荐直接上 MMOE,专家数量越多、模型越复杂,效果就越好。

正解当任务高度相关时,单一共享底层的参数效率更高、更稳定;任务差异大时,MMOE 的门控融合才体现优势。专家过多还会过拟合,增加训练成本。好的实践是先跑 Shared Bottom 基线,再根据任务相关性和线上收益决定是否升级 MMOE。

为何常见:追求“新模型 = 效果更好”的直觉,缺乏对任务相关性、基线和复杂度收益的系统比较。

面试题

Q1. 多任务推荐中“行为漏斗”从浅到深的正确顺序是?

单选题 · easy

  • A.点击 → 购买 → 收藏
  • B.点击 → 收藏 → 购买← 正确答案
  • C.购买 → 收藏 → 点击
  • D.收藏 → 点击 → 购买

答案:B。行为漏斗遵循“曝光 → 点击 → 收藏 → 购买”的逐层递进。一个人不可能先购买再点击,收藏通常发生在点击之后、购买之前的意愿沉淀阶段,就像顾客先看菜单、再记进想吃清单、最后才下单。选项 C 把顺序完全颠倒,选项 D 把收藏放在点击之前,选项 A 跳过了收藏环节,故选 B。

Q2. 共享底层结构的主要作用是?

单选题 · easy

  • A.让任务各自独立训练
  • B.提取通用特征共享复用← 正确答案
  • C.增加模型参数总量
  • D.只优化购买一个目标

答案:B。共享底层让所有任务共用一套参数,提取通用特征表示,避免每个任务重复学习一套特征变换,同时少量参数缓解过拟合。A 是单任务思路、与共享相悖;C 与共享底层减少参数的事实相反;D 丢弃了多任务联合建模的意义,故选 B。

Q3. 为什么购买行为的训练数据通常比点击稀疏?

单选题 · easy

  • A.系统不采集购买数据
  • B.漏斗越深行为越少← 正确答案
  • C.购买行为没有标签
  • D.点击无需用户操作

答案:B。行为漏斗越靠底,发生的行为越少。十个曝光只有一个点击,一百个点击才有一两个购买,购买样本天然稀疏。A、C 与事实不符,D 描述的是点击行为本身的发生条件,不是购买稀疏的原因。故选 B。

Q4. 任务专属塔在模型中的作用是?

单选题 · mid

  • A.从共享表示中学习差异← 正确答案
  • B.替代共享底层网络
  • C.对原始特征直接打分
  • D.把输出统一成一个数

答案:A。任务塔的作用是从共享表示中提取本任务特有的信号,输出各自任务的概率。B 把塔和共享底层搞混;C 说成直接对原始特征打分,实际输入是共享表示 h;D 把三个输出混为一谈。故选 A。

Q5. ESMM 缓解样本选择偏差的关键做法是?

单选题 · mid

  • A.只用购买样本训练
  • B.曝光空间链式分解概率← 正确答案
  • C.提高点击样本的权重
  • D.直接删除收藏任务

答案:B。ESMM 在全部曝光样本上把 pCTCVR 分解为 pCTR × pCVR,让 CVR 塔在全空间被间接学习,从而消除“只在点击样本上训练”带来的样本选择偏差。A 正是偏差的来源;C 只是调权重不解决空间问题;D 与多任务思想无关。故选 B。

Q6. MMOE 中门控网络的作用是?

单选题 · mid

  • A.按任务动态组合专家输出← 正确答案
  • B.过滤掉不相关特征
  • C.直接输出最终推荐结果
  • D.固定所有专家权重

答案:A。门控网络根据输入特征为每个专家计算权重,再按权重动态组合专家输出,让每个任务挑选自己需要的模式。B 是特征筛选、C 是任务塔的职责、D 与“动态加权”的核心思想矛盾。故选 A。

Q7. 不确定性加权损失中 log σ_k 项的作用是?

单选题 · extreme

  • A.防止不确定性无限增大← 正确答案
  • B.让模型训练速度更快
  • C.直接决定任务权重
  • D.替代所有超参数调优

答案:A。log σ_k 是正则项,防止 σ_k 无限增大导致权重 1/(2σ²) 趋近于零、任务被完全忽略。B 说法笼统且不准确;C 决定权重的是 1/(2σ²) 而非 log 本身;D 中 σ 是可学习参数,但仍需学习率等超参数。故选 A。

Q8. 下列哪些方法可以缓解多任务训练中的梯度冲突?

多选题 · mid

  • A.使用不确定性加权← 正确答案
  • B.采用梯度投影方法← 正确答案
  • C.无限增大学习率
  • D.动态调整任务权重← 正确答案

答案:ABD。不确定性加权让噪声大的任务自动降权,梯度投影把冲突梯度投影到安全方向,动态调整任务权重也能平衡各任务更新幅度,三者都能缓解梯度冲突。C 无限增大学习率只会放大冲突和震荡,故选 A、B、D。

Q9. 关于 ESMM 的 pCTCVR = pCTR × pCVR,正确的理解有?

多选题 · hard

  • A.假设用户先点击再购买← 正确答案
  • B.把建模空间扩展到全曝光← 正确答案
  • C.完全不需要点击数据
  • D.缓解购买数据稀疏问题← 正确答案

答案:ABD。ESMM 假设行为是“先点击后购买”的先后过程,把建模空间从点击子空间扩展到全部曝光样本,并通过全空间标签缓解 CVR 稀疏。它恰恰依赖点击数据作为中间监督,C 说“完全不需要点击数据”是错的。故选 A、B、D。

Q10. 关于多任务推荐的评估与调优,说法正确的有?

多选题 · hard

  • A.各任务分别计算AUC← 正确答案
  • B.GAUC按曝光加权平均← 正确答案
  • C.只看点击率一个指标
  • D.线上需做A/B实验← 正确答案

答案:ABD。多任务评估要分别看每个任务的 AUC,防止某一任务被牺牲;GAUC 按用户曝光量加权平均,更贴近真实业务分布;最终还要线上 A/B 实验验证。C 只看点击会掩盖收藏和购买任务的退化,故选 A、B、D。