想象一间后厨:川菜师傅刚炒完麻辣豆腐,随手涮两下锅,就开始做粤菜清蒸鲈鱼。端上桌,鱼肉带着辣意,客人当场差评。这家餐厅为省灶位,让所有菜共用一口锅、一位师傅——省了成本,砸了招牌。多任务学习(Multi-Task Learning,MTL)的初心和这家餐厅一样:让多个任务共享一个模型,互相借力。但共享过头,就会出现“串味”——这就是负迁移(Negative Transfer)。任务A学到的东西把任务B带偏,联合训练的效果反而不如各自单练。 PLE(Progressive Layered Extraction,渐进式分层提取)就是这位“后厨改造设计师”:它不再让所有任务抢一口锅,而是把后厨分成两层——公用备菜组(共享专家)只做洗切焯水这类通用工序,每道菜再配上自己的专属主厨(任务专属专家),由调度员(门控网络)按订单决定每道菜用多少共享备料、多少独家手艺。双层门控逐层调配,串味被物理隔离,每道菜都能上得了台面。这篇文章,我们就从一间餐厅的后厨讲起,把PLE这套架构拆给你看。

岗位关联

掌握PLE机制,你就能在多任务模型训练中精准定位负迁移的根源,用“共享+专属+门控”的组合拳提升多目标模型的整体表现——这是推荐、搜索、NLP多任务场景中算法工程师的核心竞争力。

目录
  1. 可视化演示
  2. 多任务学习困境
  3. 架构演进路线
  4. 双层专家分离
  5. 门控机制原理
  6. 训练机理分析
  7. 工程实践要点
  8. 同类方案对比
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示PLE四大核心:架构演进路线、双层专家分离结构、负迁移缓解对比、推荐系统多目标应用。

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

多任务架构演进路线 Shared-Bottom共享底层→MMoE多专家→CGC定制门控→PLE渐进分层 演进核心:逐步分离任务特定专家,减少任务间干扰 SB → MMoE → CGC → PLE: progressive separation PLE通过渐进式专家分离实现多任务性能最优

多任务学习困境

被客人骂了之后,后厨开始改革。第一版方案:公用备菜区和灶台保留,但每道菜请了一位专属掌勺——这叫“硬参数共享”。底层大家一起用,输出层分开。

硬共享公式:

这个公式是所有多任务学习的“总考核表”——每个任务都有自己的打分标准,最后加权合并成一张总分单。

问题在于:共用灶台还是会让菜串味。任务A和任务B共用 $\theta$,任务A的更新会把 $\theta$ 往A的方向推,任务B的更新又往B的方向拽。两个方向不一致时,模型就骑虎难下。负迁移就是那口“万用锅”——要解决串味,后厨得重新装修。

LMTL(θ)=∑t=1Tλt Lt(ft(x;θ))\displaystyle \mathcal{L}_{\mathrm{MTL}}(\theta) = \sum_{t=1}^{T} \lambda_t \, \mathcal{L}_t\big(f_t(x;\theta)\big)
通俗来说:后厨老板把川菜和粤菜的客人评分汇总,按权重算一个综合分,作为整个后厨的KPI。
  1. 任务损失$\mathcal{L}_t$ 表示第t个任务的损失函数,比如二分类用交叉熵、回归用均方误差,相当于每道菜的“客人评分表”。
    Lt\mathcal{L}_t
  2. 损失求和$\sum_{t=1}^{T}$ 把所有任务的损失累加起来,T是任务总数,相当于把每桌客人的评价汇总到总台账上。
    ∑t=1T\sum_{t=1}^{T}
  3. 任务权重$\lambda_t$ 控制第t个任务在总体损失中的重要性,好比老板给“招牌菜”更高的话语权。
    λt\lambda_t
  4. 共享模型$f_t(x;\theta)$ 表示所有任务共用参数 $\theta$ 的模型函数,正是“一口锅炒所有菜”的数学化身。
    ft(x;θ)f_t(x;\theta)

架构演进路线

第一轮改革后,后厨还是不满意。于是有了“专家混合”(Mixture of Experts,MoE):不再是一个大网络,而是一群“专家子网”,每次按需激活少数专家。这就像餐厅请了几位各有绝活的老师傅,客人点什么菜,就请相关老师傅上手。紧接着,多任务专家混合(MMoE)更进一层:每个任务配一个调度员,自己学着怎么组合这些共享专家。

硬共享的数学表达:

这个式子刻画的是“底层共享、塔层隔离”的老后厨结构。

MMoE(Multi-gate Mixture-of-Experts)比硬共享灵活:每个任务有自己的门控,可以从K个共享专家里按权重挑选组合。但注意,所有专家仍然是共享的——每道菜的掌勺还是从同一批厨师里挑,没有一个人真正属于一道菜。PLE的变革思路由此而来:与其让所有主厨在公共灶台上抢锅,不如把后厨分成“共享备菜组”和“专属主厨组”两层,各司其职。

yt=Towert(Shared(x;θs);θt)\displaystyle y_t = \mathrm{Tower}_t\big( \mathrm{Shared}(x; \theta_s); \theta_t \big)
通俗来说:所有菜共用同一位备菜师傅,但每道菜的掌勺和摆盘各自独立。
  1. 底层共享$\mathrm{Shared}(x; \theta_s)$ 是底层的共享特征提取器,所有任务复用同一组参数 $\theta_s$,相当于公用的备菜台。
    Shared(x;θs)\mathrm{Shared}(x; \theta_s)
  2. 专属塔层$\mathrm{Tower}_t$ 是第t个任务自己的输出头,只吃共享特征,相当于每道菜的摆盘师傅。
    Towert\mathrm{Tower}_t
  3. 专属参数$\theta_t$ 是塔里面的参数,只被任务t的梯度更新,摆盘风格不会串到别的菜上。
    θt\theta_t
  4. 硬共享根源所有任务都经过同一个 $\theta_s$,任务A的更新会直接影响任务B的输出——共用备菜台还是难免沾上彼此的“锅气”。
    θs\theta_s

双层专家分离

最终装修方案出炉:后厨分成两层。第一层是通用备菜组——洗菜、切菜、配高汤,任何菜都需要;第二层是专属主厨组——川菜主厨只管麻辣,粤菜主厨只管清鲜。每一层都各司其职,这就是PLE名字里"Progressive Layered Extraction"渐进式分层提取的直观画面。

PLE中,这两层分别对应两类专家网络:共享专家(Shared Experts)和任务专属专家(Task-Specific Experts)。共享专家被所有任务共同使用,负责提取通用特征;专属专家只服务自己的任务,负责捕捉任务独有的模式。每个任务在同一层的输入特征是两者的加权组合:

这个公式是PLE的核心心法——共享部分做“通识教育”,专属部分做“专才培养”。

注意:每个任务可以有不同数量的专属专家。任务越复杂、独特性越强,就可以配置越多的专属专家。这一层一层的“备菜→掌勺”分工逐层递进:底层处理通用细节,越往上越贴近任务本身的语义,每一层都有自己的共享与专属分工。

g(t)(x)=∑i=1msws,i(t) Ei(x)+∑j=1mtwt,j(t) Ej(t)(x)\displaystyle g^{(t)}(x) = \sum_{i=1}^{m_s} w_{s,i}^{(t)} \, E_i(x) + \sum_{j=1}^{m_t} w_{t,j}^{(t)} \, E_j^{(t)}(x)
通俗来说:一盘麻婆豆腐 = 备菜组切好的豆腐和肉末(共享部分)+ 川菜主厨的独门豆瓣酱火候(专属部分)。
  1. 共享专家项$\sum_{i=1}^{m_s} w_{s,i}^{(t)} E_i(x)$ 是任务t在 $m_s$ 个共享专家上的加权组合,相当于从备菜组取来的通用底料。
    ∑i=1msws,i(t) Ei(x)\sum_{i=1}^{m_s} w_{s,i}^{(t)} \, E_i(x)
  2. 专属专家项$\sum_{j=1}^{m_t} w_{t,j}^{(t)} E_j^{(t)}(x)$ 是任务t在自己 $m_t$ 个专属专家上的加权组合,相当于川菜主厨的私房工序。
    ∑j=1mtwt,j(t) Ej(t)(x)\sum_{j=1}^{m_t} w_{t,j}^{(t)} \, E_j^{(t)}(x)
  3. 门控权重$w_{s,i}^{(t)}$ 和 $w_{t,j}^{(t)}$ 分别是共享专家和专属专家的分配权重,由门控网络输出,相当于调度员在订单上标注“这桌用多少底料、多少独家手艺”。
    ws,i(t),  wt,j(t)w_{s,i}^{(t)}, \; w_{t,j}^{(t)}
  4. 双层融合共享项提取通用模式、专属项保留任务个性,两者相加构成任务t在该层的输入特征——备菜与掌勺的完美合流。
    g(t)(x)g^{(t)}(x)

门控机制原理

后厨有了共享组和专属组,怎么决定每道菜用多少共享备菜、多少专属手艺?这就要靠调度员。餐厅的调度员看一眼订单,迅速拍板:“这桌川菜,用备菜台的二荆条,但豆瓣酱必须用主厨的私藏。”

PLE里的调度员就是门控网络(Gate)。每个任务在每一层都有一个自己的门控。门控读入当前层的输入特征,给所有专家(共享+专属)打一个原始分,然后用softmax归一化成权重:

这是门控的“点菜公式”——输入特征决定每个专家的分配比例。

softmax把任意实数分数变成一组非负、和为1的权重,权重越大,该专家对任务t的贡献越大。同一个共享专家在不同任务眼里价值不同:任务1可能给它打了0.6,任务2可能只给它0.2。调度员不是瞎指挥的——门控的权重是训练中学出来的:哪个专家对任务t的预测贡献大,梯度就把它顶上去,贡献小的自然被压下去。这就是“动态组合策略”:每一层都在重新分配角色,像换季调整菜单一样自然。

w(t,k)=softmax(Wg(t,k) x(k))\displaystyle w^{(t,k)} = \mathrm{softmax}\big( W_g^{(t,k)} \, x^{(k)} \big)
通俗来说:调度员看一眼客人点的菜(输入特征),心里快速盘算:这桌川菜,共享备菜给30%,川菜主厨给70%。
  1. 线性打分$W_g^{(t,k)} x^{(k)}$ 用可学习矩阵对第k层输入打分,得到每个专家的原始分数,相当于调度员根据订单给每位师傅的适配度打分。
    Wg(t,k) x(k)W_g^{(t,k)} \, x^{(k)}
  2. softmax归一化$\mathrm{softmax}$ 把分数变成非负且和为1的权重,保证分配比例不会出现负数或溢出。
    softmax\mathrm{softmax}
  3. 任务独立每个任务t有独立的 $W_g^{(t,k)}$,所以能学出自己的侧重——川菜调度员和粤菜调度员的判断标准天然不同。
    Wg(t,k)W_g^{(t,k)}
  4. 分层门控上标k说明每一层都有一组门控,高层的输入是上一层的结果——后厨每一层都有调度员,层层流转。
    x(k)x^{(k)}

训练机理分析

后厨排班表上写着硬规矩:专属主厨只听自己那道菜的客人评价。川菜师傅不看粤菜点评,粤菜师傅也不看川菜点评。只有备菜组的人,才综合看所有订单的反馈来调整备菜节奏。

这在PLE中就是“梯度流动分离”(Gradient Isolation)。任务t的专属专家,在反向传播时只接收来自任务t的损失梯度;共享专家则接收所有任务的梯度。前者保证任务个性不被其他任务干扰,后者保留多任务之间的信息互助。专属参数的更新式:

这是专属主厨的“排班表”——他只被自己这道菜的评分驱动。

训练时还要给不同任务分配损失权重 $\lambda$——相当于餐厅给每道菜定不同的考核权重:招牌菜占比高,就多分派人手盯它的出品。PLE的稳定性正来自这种“专属隔离+共享协作”的双通道设计:共享参数接受全局反馈,学习任务间的共性;专属参数只接受自家梯度,守住任务的个性。两个通道互不干扰,任何单一任务的剧烈波动都不会把整个模型带崩。

θtnew=θtold−η ∇θtLt\displaystyle \theta_t^{\mathrm{new}} = \theta_t^{\mathrm{old}} - \eta \, \nabla_{\theta_t} \mathcal{L}_t
通俗来说:川菜师傅的刀工和火候,只根据川菜客人的评价来调整,粤菜客人骂街他听不到。
  1. 专属参数$\theta_t$ 是任务t专属专家的参数,只被任务t的损失影响——专属主厨只认自家菜单。
    θt\theta_t
  2. 梯度$\nabla_{\theta_t} \mathcal{L}_t$ 是损失对专属参数的偏导,代表“任务t想把参数往哪推”——客人今天的口味方向。
    ∇θtLt\nabla_{\theta_t} \mathcal{L}_t
  3. 学习率$\eta$ 控制每次更新的步长——师傅每次试菜调整配方的幅度。
    η\eta
  4. 解耦效果任务t'的损失 $\mathcal{L}_{t'}$ 不出现,所以专属参数不会被其他任务推走,串味被物理隔离。
    θtnew=θtold−η ∇θtLt\theta_t^{\mathrm{new}} = \theta_t^{\mathrm{old}} - \eta \, \nabla_{\theta_t} \mathcal{L}_t

工程实践要点

这间后厨模式在连锁店(推荐系统)里特别吃香。短视频App的后厨要同时出三道菜:点击率、完播率、点赞率。过去MMoE只有共享厨师,经常出现“点击率高但观众秒划走”——标题党赢了点击,输了完播。换成PLE之后,点击诱因和内容粘性各有一位专属主厨,冲突自然化解。

工程落地的四个要点:第一,共享专家与专属专家的数量比例要视任务冲突程度而定,一般共享2-4个、每任务专属1-2个起步;第二,各任务塔要保持精简,避免过拟合;第三,为不同任务设置合理的损失权重 $\lambda$,权重过大会让模型只顾一个任务;第四,评估多任务模型要综合看各任务指标,不能只看单一AUC。AUC的定义是正样本得分高于负样本的概率:

这是推荐排序模型的“声望值”——随机抽一个正样本,它排在随机负样本前面的概率。

AUC越接近1,排序能力越强。多目标场景下,通常要上报每个任务的AUC或GAUC,再用加权或帕累托前沿比较模型。调参就像调后厨排班:共享备菜组太多,人力浪费;专属主厨太少,招牌菜没人管。经验是先跑一版MMoE作为基线,再逐步引入专属专家,观察每个任务的指标曲线,让数据说话。

AUC=∑i∈P∑j∈N1(si>sj)∣P∣×∣N∣\displaystyle \mathrm{AUC} = \frac{\sum_{i \in P} \sum_{j \in N} \mathbb{1}\big( s_i > s_j \big)}{|P| \times |N|}
通俗来说:老板随机抽查一桌“好菜”和一桌“差菜”,好菜风评比差菜好的概率就是AUC。
  1. 正负样本集合$P$ 是正样本集,$N$ 是负样本集——好菜桌和差菜桌。
    P,  NP, \; N
  2. 指示函数$\mathbb{1}(s_i > s_j)$ 当正样本得分 $s_i$ 高于负样本得分 $s_j$ 时记1,否则记0——好菜确实比差菜强,就记一分。
    1(si>sj)\mathbb{1}\big( s_i > s_j \big)
  3. 穷举配对$\sum_{i \in P} \sum_{j \in N}$ 枚举所有正负样本对——把所有好菜差菜两两PK一遍。
    ∑i∈P∑j∈N\sum_{i \in P} \sum_{j \in N}
  4. 归一化$|P| \times |N|$ 是总对数,把得分变成概率——胜场数除以总场数。
    ∣P∣×∣N∣|P| \times |N|

同类方案对比

回头看看市面上其他后厨方案:硬共享就像一锅多用,最省钱但串味最凶;MoE像备了几组专家轮岗,但调度复杂、没有任务归属感;MMoE给每道菜配了指挥手,但指挥手只能从共享厨师里挑人——还是没有人专属负责一道菜。PLE把MMoE升级成了“共享+专属”双层结构:

这是PLE与MMoE的“家族对比照”——共享部分保留了MMoE的协作能力,专属部分是PLE新增的“隔离墙”。

从结构上可以看出,PLE是MMoE的“解耦增强版”:多出了专属专家项,代价是参数更多、训练更长。所以适用场景有边界:任务间可共享的信息较少、冲突较大时,PLE优势明显;任务本来就高度相似,硬共享或MMoE就够用。选择方案就像给餐厅做定位:如果客人只点同一道菜,共享后厨性价比最高;如果菜系跨度大、口味迥异,就得用PLE的分层后厨——成本高一些,但每道菜都能上得了台面。

gPLE(t)(x)=∑i=1msws,i(t) Ei(x)⏟共享部分+∑j=1mtwt,j(t) Ej(t)(x)⏟专属部分\displaystyle g^{(t)}_{\mathrm{PLE}}(x) = \underbrace{\sum_{i=1}^{m_s} w_{s,i}^{(t)} \, E_i(x)}_{\text{共享部分}} + \underbrace{\sum_{j=1}^{m_t} w_{t,j}^{(t)} \, E_j^{(t)}(x)}_{\text{专属部分}}
通俗来说:MMoE的菜全是“团体操”——所有主厨轮番上场;PLE的菜是“领舞+群舞”——群舞烘托气氛,领舞独挑大梁。
  1. 共享部分$\sum_{i=1}^{m_s} w_{s,i}^{(t)} E_i(x)$ 是所有任务共同使用的基础专家组合,对应餐厅的公用备菜团队。
    ∑i=1msws,i(t) Ei(x)\sum_{i=1}^{m_s} w_{s,i}^{(t)} \, E_i(x)
  2. 专属部分$\sum_{j=1}^{m_t} w_{t,j}^{(t)} E_j^{(t)}(x)$ 是任务t独享的专家组合,对应川菜馆自己的主厨组。
    ∑j=1mtwt,j(t) Ej(t)(x)\sum_{j=1}^{m_t} w_{t,j}^{(t)} \, E_j^{(t)}(x)
  3. 对照MMoEMMoE只有共享部分($m_t=0$),没有专属概念——所有专家对所有任务开放。
    mt=0m_t = 0
  4. 核心优势专属部分把任务特有模式隔离出来,共享部分专注通用模式,负迁移被“分流”而非硬扛。
    gPLE(t)(x)g^{(t)}_{\mathrm{PLE}}(x)

AI 应用场景

短视频推荐多目标优化

阶段:模型训练与多目标建模

解决的问题:短视频推荐需要同时预估点击率、完播率、点赞率。传统MMoE只有共享专家,模型容易被“点击诱因”带偏——学出一堆标题党,点击高但秒划走。PLE让点击诱因交给点击专属专家、内容粘性交给完播专属专家,共享专家只学用户通用兴趣,三路输出互不拆台。

具体案例:某短视频平台把MMoE升级为PLE后,点击率持平的情况下完播率提升4.2%,点赞率提升2.8%;离线评估时各任务AUC普遍提升1-3个点,线上AB实验整体时长收益正向。

电商搜索排序多目标建模

阶段:特征工程与排序模型架构

解决的问题:电商搜索要同时优化点击率(CTR)和成交转化率(GMV)。两个目标天然冲突——低价爆款点击高但GMV低,高客单价商品GMV高但点击少。PLE把“点击偏好”和“购买力识别”分别放进两个专属专家,共享专家学习品牌、类目等通用表征,避免一个目标压制另一个。

具体案例:某电商平台在搜索结果页排序模型引入PLE,CTR和GMV两个指标同时提升,GMV提升3.1%且CTR无损;相比共享硬参数模型,负迁移导致的“重点击轻转化”现象明显缓解。

智能客服多任务语义理解

阶段:多任务模型微调与部署

解决的问题:智能客服一个模型需要同时做意图识别、情感分析、领域分类。三个任务在共享BERT层上联合微调时,情感分析强烈依赖语气词特征,意图识别更依赖动词短语,两者在共享层互相拉扯。PLE在共享BERT之上设置专属专家分流,各任务F1均获提升。

具体案例:某金融客服系统用PLE架构替代硬共享微调,意图识别F1提升2.5%、情感分析F1提升1.9%、领域分类F1提升1.2%,且训练收敛更稳定,不再出现“训好一个忘了另一个”的跷跷板现象。

Python 演示

python107 行
import torchimport torch.nn as nnimport torch.optim as optim torch.manual_seed(42)  class PLE(nn.Module):    def __init__(self, input_size, hidden_size, num_shared, num_task):        super().__init__()        self.num_task = num_task        self.num_shared = num_shared        self.shared_experts = nn.ModuleList([            nn.Sequential(nn.Linear(input_size, hidden_size), nn.ReLU())            for _ in range(num_shared)        ])        self.task_experts = nn.ModuleList()        for _ in range(num_task):            experts = nn.ModuleList([                nn.Sequential(nn.Linear(input_size, hidden_size), nn.ReLU())                for _ in range(num_shared)            ])            self.task_experts.append(experts)        self.gates = nn.ModuleList([            nn.Linear(input_size, num_shared * 2)            for _ in range(num_task)        ])        self.towers = nn.ModuleList([            nn.Linear(hidden_size, 1)            for _ in range(num_task)        ])     def forward(self, x):        shared_outs = [e(x) for e in self.shared_experts]        results = []        for t in range(self.num_task):            task_outs = [e(x) for e in self.task_experts[t]]            all_outs = shared_outs + task_outs            w = torch.softmax(self.gates[t](x), dim=-1)            combined = torch.stack(                [w[:, i:i + 1] * all_outs[i] for i in range(len(all_outs))]            ).sum(dim=0)            results.append(self.towers[t](combined))        return results  class MMoE(nn.Module):    def __init__(self, input_size, hidden_size, num_experts, num_task):        super().__init__()        self.num_task = num_task        self.experts = nn.ModuleList([            nn.Sequential(nn.Linear(input_size, hidden_size), nn.ReLU())            for _ in range(num_experts)        ])        self.gates = nn.ModuleList([            nn.Linear(input_size, num_experts)            for _ in range(num_task)        ])        self.towers = nn.ModuleList([            nn.Linear(hidden_size, 1)            for _ in range(num_task)        ])     def forward(self, x):        expert_outs = [e(x) for e in self.experts]        results = []        for t in range(self.num_task):            w = torch.softmax(self.gates[t](x), dim=-1)            combined = torch.stack(                [w[:, i:i + 1] * expert_outs[i] for i in range(len(expert_outs))]            ).sum(dim=0)            results.append(self.towers[t](combined))        return results  def train_model(model, epochs=800):    optimizer = optim.Adam(model.parameters(), lr=0.01)    final_loss = None    for _ in range(epochs):        x = torch.randn(64, 12)        y1 = torch.sin(x[:, 0]) + 0.2 * x[:, 1] + 0.5 * torch.tanh(x[:, 2])        y2 = torch.cos(x[:, 3]) + 0.2 * x[:, 4] + 0.5 * torch.tanh(x[:, 2])        out1, out2 = model(x)        loss = nn.functional.mse_loss(out1.squeeze(), y1) + \            nn.functional.mse_loss(out2.squeeze(), y2)        optimizer.zero_grad()        loss.backward()        optimizer.step()        final_loss = loss.item()    return final_loss  def main():    ple = PLE(input_size=12, hidden_size=16, num_shared=2, num_task=2)    mmoe = MMoE(input_size=12, hidden_size=16, num_experts=4, num_task=2)    loss_ple = train_model(ple)    loss_mmoe = train_model(mmoe)    print("PLE final loss: %.4f" % loss_ple)    print("MMoE final loss: %.4f" % loss_mmoe)    if loss_ple < loss_mmoe:        print("结果: PLE 通过专属专家隔离,缓解了负迁移")    else:        print("结果: 此随机种子下 MMoE 略优,可调整超参复现")  if __name__ == "__main__":    main()
目的:训练一个迷你PLE和一个迷你MMoE,在同一组易冲突任务上对比最终损失,直观验证“专属专家隔离负迁移”的效果。
  1. self.task_experts.append(experts)为每个任务额外创建一组专属专家,这是PLE区别于MMoE的核心结构。
  2. nn.Linear(input_size, num_shared * 2)门控输出维度等于共享专家数加专属专家数,让调度员给所有专家打分。
  3. w = torch.softmax(self.gates[t](x), dim=-1)softmax将原始分数归一化为和为1的权重,对应调度员的“分配比例”。
  4. torch.stack([w[:, i:i + 1] * all_outs[i] ...]).sum(dim=0)把专家输出按门控权重加权求和,即“共享底料+专属手艺”的合流。
  5. y1 = torch.sin(x[:, 0]) + ...构造两个共享第3维特征、又有独立特征且目标差异大的任务,制造负迁移环境。
  6. loss = mse(out1, y1) + mse(out2, y2)两个任务损失直接相加,模拟多任务联合训练的总目标。

常见误区

误区初学者认为共享专家是“万金油”,数量越多提取的通用特征越丰富,于是把共享专家开到8个、16个,结果模型变大了,各任务指标反而下降。

正解共享专家过多会让参数严重冗余,而且所有任务的梯度都挤在共享参数上,竞争更激烈,负迁移反而加剧。PLE设计的精髓是共享与专属的“比例平衡”:共享专家负责共性,专属专家负责个性,通常共享2-4个、每任务专属1-2个起步,再根据验证集表现调。

为何常见:直觉上“多多益善”是普遍心理,忽略了共享专家本质还是共享参数——所有任务都在更新同一组参数,容量越大,任务间的拉扯面越大。

误区看了代码后觉得PLE就是把MMoE的共享专家多复制几份,再加几个专属专家,本质没区别,属于“堆参数”。

正解PLE的本质区别在于引入“任务专属专家”作为隔离层,并采用分层渐进式提取,每层门控分别组合共享与专属输出。它是结构上的解耦——专属专家物理上只接收自己任务的梯度,不是数量扩展,而是把“共享博弈”改造成了“共享协作+专属隔离”的双通道。

为何常见:PLE和MMoE结构图相似,看代码时只注意到专家数量差异,忽略了专属专家承担的“隔断负迁移”这一结构性角色。

误区有人认为只要不共享参数就不会负迁移,干脆把模型拆成完全独立的任务网络,结果任务间信息互助也没了,小任务数据不足时训练更差。

正解负迁移还可能来自数据分布重叠(两个任务的标签互相矛盾)、特征掩盖(一个任务需要的特征被另一个任务的任务头占用)、以及门控学习的次优均衡。PLE用共享加专属的折中方案,既保留信息互助又控制竞争,是对负迁移的“综合治理”而非一刀切。

为何常见:“负迁移”三个字里带“共享”的隐含前提,让人直觉归因到“共享参数”,忽略了多任务学习中更复杂的信息流交互。

误区以为PLE的门控只吃第一层输入特征,不理解分层门控的输入可以来自上层表示,觉得门控就是一次性的静态路由。

正解PLE的门控在每一层都存在,低层门控以原始特征为输入,高层门控以上一层的组合表示为输入。这样高层的路由可以感知更抽象的信息,实现真正的“渐进式提取”——越往后,路由越聪明,越知道该把特征交给谁。

为何常见:看PLE结构图时只注意到每层有门控框,没细看门控的输入箭头来源,误以为所有门控都并联在输入端。

误区学了PLE后觉得它是多任务学习的“终极方案”,所有任务都该无脑上PLE,不选PLE就是落伍。

正解PLE的优势建立在“任务差异大、冲突明显”的前提上。如果任务高度相似、可共享信息丰富,MMoE甚至硬共享就够用,上PLE只会引入更多参数量和训练开销。选型要看数据、看任务相关性、看成本预算,不能盲目追求架构复杂度。

为何常见:近期论文和工程博客对PLE的宣传放大了它的适用面,读者容易忽略论文中的实验条件与真实业务场景的差异。

面试题

Q1. 多任务学习中“负迁移”指的是什么?

单选题 · easy

  • A.任务间共享参数互相干扰,一损俱损← 正确答案
  • B.训练数据不足造成的欠拟合
  • C.模型损失函数输出为负值
  • D.梯度爆炸导致训练直接发散

答案:A。负迁移是任务A的训练损害任务B性能的现象,就像川菜和粤菜共用一口锅导致串味。选项B是欠拟合、C是无意义的数值概念、D是优化问题,都不是负迁移的本质定义。

Q2. 相比MMoE,PLE的核心新增结构是什么?

单选题 · easy

  • A.任务专属的专家网络← 正确答案
  • B.更多更深的共享层
  • C.更深的塔式输出结构
  • D.更强的权重正则化手段

答案:A。PLE的灵魂是任务专属专家——每道菜有自己的主厨。MMoE所有专家都是共享的,只是门控不同;PLE额外给每个任务分配专属专家,实现梯度隔离。

Q3. PLE中门控网络的输出是什么?

单选题 · mid

  • A.归一化的专家权重向量← 正确答案
  • B.专家的隐层输出结果
  • C.任务塔的最终预测值
  • D.输入特征的稠密表示

答案:A。门控读入输入特征后,对每个专家打分,再经softmax归一化成权重向量。它是“调度员的分配比例”,不是专家输出、不是预测值、也不是特征本身。

Q4. 关于PLE中任务t的专家组合方式,正确的是?

单选题 · mid

  • A.共享专家加自身专属专家← 正确答案
  • B.只使用自身的专属专家
  • C.所有任务共用全部专家
  • D.专家之间的相互级联

答案:A。PLE的任务t在每层都由两部分组成:所有共享专家加权 + 任务t自己的专属专家加权。B丢了共享协作,C退化成MMoE,D是错误的结构描述。

Q5. PLE训练时任务t的专属专家参数如何更新?

单选题 · hard

  • A.只接收任务t反向的梯度← 正确答案
  • B.接收所有任务反向梯度
  • C.不接收任何梯度的更新
  • D.共享与专属梯度都接收

答案:A。专属专家只被自己的任务损失更新,这是负迁移“物理隔离”的关键。如果接收所有任务梯度,专属专家就退化成半共享专家,隔离失去意义。

Q6. 下列哪项是缓解任务间负迁移的有效策略?

单选题 · mid

  • A.让两个任务的学习率不同
  • B.引入任务专属参数做隔离← 正确答案
  • C.直接删掉其中的一个任务
  • D.大幅缩小每批数据的尺寸

答案:B。任务专属参数把冲突梯度隔离开,是PLE针对负迁移的治本之策。改学习率、删任务、缩batch都属于绕道或回避,没有从结构上解决冲突。

Q7. PLE中的“渐进式分层提取”指的是什么?

单选题 · hard

  • A.每层逐渐抽象为更语义特征← 正确答案
  • B.每层都增大专家的数量
  • C.每层都缩小输入的特征
  • D.每层都增加任务的个数

答案:A。PLE每一层都做“共享+专属”的门控组合,底层提取通用细节,越往上越贴近任务语义。它强调的是特征的逐层抽象与路由细化,而非专家数、维度或任务数的机械变化。

Q8. 多任务学习中导致负迁移的原因有哪些?

多选题 · mid

  • A.任务梯度方向相互冲突← 正确答案
  • B.共享参数被多任务拉扯← 正确答案
  • C.任务间数据分布差异较大← 正确答案
  • D.损失函数输出数值为负

答案:ABC。梯度冲突、共享参数拉力不一是负迁移的两大直接推手,数据分布差异大则让共享层更难两全。D是无关干扰项——损失为正负不影响任务间的干扰。

Q9. PLE结构中,哪些组件属于任务t专属?

多选题 · hard

  • A.任务专属的专家子网络← 正确答案
  • B.任务t的门控网络单元← 正确答案
  • C.所有任务共用的专家网络
  • D.任务t的结果输出塔← 正确答案

答案:ABD。任务t专属专家的更新只接收自家梯度;任务t的门控负责调配该任务的专家组成;任务t的塔输出该任务预测。共享专家属于全体任务,不是专属组件。

Q10. 关于PLE门控机制的说法,正确的有?

多选题 · mid

  • A.每层每任务各有一个门控← 正确答案
  • B.门控输出经过softmax归一化← 正确答案
  • C.门控输入取自特征向量← 正确答案
  • D.各任务门控必须共享权重

答案:ABC。PLE的每个任务在每一层都有独立门控,输入是当前层特征,输出经softmax归一化成权重。各任务门控完全独立、参数不共享,D与设计相悖。