胡同口开了三十年的“梁记卤味店”面临一个甜蜜的烦恼:老师傅梁伯凭着一张泛黄的记忆卡,记得每一位老主顾的口味——张太太要辣不要蒜,王叔的鸭四件要拆骨,李姨的卤牛腱要多放一勺老汤。老主顾们离不开这份熟悉,新客人却嫌菜单太老套。梁伯想让留学回来的儿子小梁改良菜品,又怕伤了老客人的心。推荐系统也站在同样的十字路口:一边要记住用户过去的行为偏好(记忆),一边要挖掘用户可能喜欢的新事物(泛化)。2016 年 Google 团队提出的 Wide & Deep 模型,就是给这个难题开出了一剂“师徒合灶”的良方——让擅长记忆的线性模型与擅长泛化的深度网络在同一口锅里各展所长。

岗位关联

对 AI 从业者而言,Wide & Deep 是深度学习推荐系统承前启后的里程碑:吃透它的双通道协作思想,你就掌握了 CTR 预估、候选排序等一线场景中最常用的建模框架。

目录
  1. 可视化演示
  2. 模型缘起——推荐系统的记忆与泛化之争
  3. Wide 通道——老师傅的记忆卡
  4. Deep 通道——小学徒的规律册
  5. 联合训练——一口锅里的协同
  6. 特征工程——记忆卡的制作工艺
  7. 超参调优——火候与配比的艺术
  8. 应用落地——从 Google Play 出发
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

通过双路架构、记忆与泛化对比及训练AUC曲线三个模式,展示Wide&Deep如何融合线性记忆与深度泛化提升推荐效果。

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

'+captions.arch+'

模型缘起——推荐系统的记忆与泛化之争

梁伯翻着记忆卡发愁:要是全按老主顾的口味来,新客人只会觉得这家店固步自封;要是全听小梁的搞创新,老主顾又该骂街了。推荐系统同样卡在这个两难里——“记忆”是把用户历史行为中的共现模式(比如“装了美图秀秀的人通常会下载轻颜相机”)牢牢记住;“泛化”是面对从未见过的特征组合时,也能根据规律推断出用户可能喜欢什么。

传统逻辑回归(LR)是典型的“记忆型选手”:它能直接吃下稀疏的 ID 类特征,把“用户 A × 商品 B”这类交叉特征训练出很高的权重,但对没见过的组合完全无能为力。反向传播的多层神经网络则是“泛化型选手”:它借助嵌入向量把稀疏特征压缩成稠密表示,能泛化出高阶交互,可面对极度稀疏的用户行为时,又常常记不住那些具体而微的偏好。

2016 年,Google 团队提出 Wide & Deep 模型,把两条路线缝进同一个网络:左路 Wide 线性模型负责记忆,右路 Deep 深度网络负责泛化。两者共用同一个损失函数联合训练,像两位厨师在同一口锅里掌勺。这个统一模型在 Google Play 应用商店上线后,应用下载的点击率提升了 3.9%。

推荐模型的学习目标,通常是最小化所有样本的交叉熵损失:

梁伯最终决定:保留传统菜牌(Wide),同时放手让小梁开发新菜(Deep),两套菜式统一从后厨出菜。老主顾满意,新客人也愿意进门了。这就是 Wide & Deep 在一页架构图里讲完的故事。

L=−1N∑i=1N[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\displaystyle \mathcal{L} = -\frac{1}{N}\sum_{i=1}^{N}\left[ y_i \log \hat{y}_i + (1-y_i)\log(1-\hat{y}_i) \right]
通俗说:模型每次预测错得越离谱,这个损失值就越大;训练就是把“总损失”一点点压小。
  1. 样本编号\(i\) 从 1 到 \(N\),遍历训练集中每一条用户行为记录,比如一次“是否点击”的曝光样本。
    i∈{1,2,…,N}i \in \{1, 2, \ldots, N\}
  2. 预测与真值\(\hat{y}_i\) 是模型预测的点击概率,\(y_i\) 是用户真实点击标签(1 为点击,0 为未点击)。
    y^i=P(yi=1∣xi)\hat{y}_i = P(y_i = 1 \mid \mathbf{x}_i)
  3. 平均交叉熵对每条样本计算 \(y_i \log \hat{y}_i + (1-y_i)\log(1-\hat{y}_i)\) 后求和取平均,得到整个数据集上的损失。
    L=−1N∑i=1N[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\mathcal{L} = -\frac{1}{N}\sum_{i=1}^{N}\left[ y_i \log \hat{y}_i + (1-y_i)\log(1-\hat{y}_i) \right]

Wide 通道——老师傅的记忆卡

梁伯的记忆卡上,有一种用红绳把两个条件绑在一起的卡片。“张太太 = 辣 且 不要蒜”——单独记“辣”会翻车,单独记“不要蒜”也会翻车,只有把两者绑成一张卡,才万无一失。这种“两条件同时成立”的记录方式,正是特征交叉的雏形。

Wide 部分的输入,是“原始特征 + 交叉特征”拼接成的向量。交叉特征就是把若干维度用逻辑 AND 绑成一条新特征,例如“用户已安装 App A AND 用户今天点击过 App B”,记为 \((A \& B)\)。当且仅当两个条件都满足时,这一维特征才取值 1,否则为 0。模型一旦发现这条特征与“下载”高度相关,就会自动给它学一个很大的权重。

Wide 通道本身是一个没有隐藏层的线性模型,输出为权重与输入向量的内积再加偏置:

梁伯的卡片越系越多,但每张都清清楚楚、一翻即中。Wide 要的就是这种“看见熟悉的组合立刻给高分”的爽快——不必深想为什么,记得就够了。

ywide=wT[x,ϕ(x)]+b\displaystyle y_{\text{wide}} = \mathbf{w}^T[\mathbf{x}, \phi(\mathbf{x})] + b
通俗说:Wide 就像一个“翻卡器”,把所有输入特征(含交叉卡)各自乘一个权重再加起来,权重越大代表这条记忆越重要。
  1. 原始特征\(\mathbf{x}\) 是未经交叉的原始特征向量,比如用户年龄、设备型号、已安装应用列表。
    x=[x1,x2,…,xd]\mathbf{x} = [x_1, x_2, \ldots, x_d]
  2. 交叉特征\(\phi(\mathbf{x})\) 是人工构造的 AND 组合特征列表,每一项都是一张“红绳卡片”。
    ϕ(x)=[ϕ1(x),ϕ2(x),…,ϕm(x)]\phi(\mathbf{x}) = [\phi_1(\mathbf{x}), \phi_2(\mathbf{x}), \ldots, \phi_m(\mathbf{x})]
  3. 加权求和对拼接后的整体向量做线性加权,再加上偏置 \(b\),得到 Wide 侧的打分。
    ywide=∑i=1dwixi+∑j=1mwj′ϕj(x)+by_{\text{wide}} = \sum_{i=1}^{d} w_i x_i + \sum_{j=1}^{m} w'_j \phi_j(\mathbf{x}) + b

Deep 通道——小学徒的规律册

小梁没有老师傅的记忆卡,他抱着一个笔记本,专门记录“为什么某些食材天生合拍”:鸭肉配梅子能解腻,卤料里加点陈皮回甘更悠长。他并不关心某个具体客人,而是琢磨食材背后看不见的规律——这正对应深度网络的“泛化”。

Deep 部分不直接处理稀疏的原始 ID,而是先为每个 ID 学一个稠密的嵌入向量(embedding)。原始特征若是一个有几百万维的 one-hot 向量,嵌入层会把它映射为 8~32 维的稠密向量,语义相近的 ID 在这个低维空间里会彼此靠近。比如“美图秀秀”和“轻颜相机”的嵌入向量距离很近。

嵌入向量拼接后,依次经过若干全连接层,每层都接 ReLU 激活函数。全连接层通过矩阵乘法反复变换组合特征,最终在最后一层输出一个 logit:

小梁的笔记本从不记录“张太太要辣不要蒜”这种个案,却能在第一次见面的客人的点菜单上猜中七八分喜好。Deep 的泛化能力,就是这份从数据里提炼规律的悟性。

a(l+1)=ReLU(W(l)a(l)+b(l))\displaystyle \mathbf{a}^{(l+1)} = \text{ReLU}\left(\mathbf{W}^{(l)}\mathbf{a}^{(l)} + \mathbf{b}^{(l)}\right)
通俗说:每一层网络都在对特征做一次“提炼重排”,层数越深,越能表达复杂的特征组合规律。
  1. 输入向量\(\mathbf{a}^{(l)}\) 是第 \(l\) 层神经元的激活值,第 0 层输入是嵌入层输出的稠密向量。
    a(0)=Embedding(xsparse)\mathbf{a}^{(0)} = \text{Embedding}(\mathbf{x}_{\text{sparse}})
  2. 线性变换\(\mathbf{W}^{(l)}\) 是当前层的权重矩阵,\(\mathbf{b}^{(l)}\) 是偏置向量,先把输入线性映射到新空间。
    z(l)=W(l)a(l)+b(l)\mathbf{z}^{(l)} = \mathbf{W}^{(l)}\mathbf{a}^{(l)} + \mathbf{b}^{(l)}
  3. 非线性激活ReLU 把负值压成 0、保留正值,让网络具备拟合非线性关系的能力。
    a(l+1)=max⁡(0,z(l))\mathbf{a}^{(l+1)} = \max(0, \mathbf{z}^{(l)})

联合训练——一口锅里的协同

真正精妙的不是两位厨师各炒各的菜,而是他们共用同一炉火:小梁试出的新配料会被梁伯偷偷加进老卤,梁伯也会提醒小梁“这道菜的熟客口味记忆卡,你翻过没有”。两个人的手艺在同一个灶台上互相渗透,而不是各做一锅再拼盘。

Wide & Deep 的联合训练(joint training)正是如此。两个子模型在同一个损失函数下同时做梯度更新——这与集成学习有本质区别:集成学习是两个模型各自独立训练完,再对打分做加权融合;联合训练则是误差信号同时反向传播到 Wide 的权重和 Deep 的每一层,两边在训练过程中就互相影响。

前向传播时,Wide 的线性输出与 Deep 的网络输出相加,再经过 Sigmoid 函数映射为点击概率:

论文的实用配置是:Wide 侧用 FTRL 优化器配合 L1 正则,保证稀疏权重稳定收敛;Deep 侧用 AdaGrad 优化器,让深层网络平稳学习。这就是“一口锅”的意义——老菜的记忆和新菜的规律在同一个损失函数里互相成就,而不是两锅菜出锅后再拌在一起。

y^=σ(ywide+ydeep+b)\displaystyle \hat{y} = \sigma\left(y_{\text{wide}} + y_{\text{deep}} + b\right)
通俗说:两条通道各打一个分,把两个分数加在一起,再用 Sigmoid 压缩成 0 到 1 之间的概率。
  1. Wide 侧分数线性部分对“原始特征 + 交叉特征”打分,输出一个实数 logit。
    ywide=wwideT[x,ϕ(x)]y_{\text{wide}} = \mathbf{w}_{\text{wide}}^T[\mathbf{x}, \phi(\mathbf{x})]
  2. Deep 侧分数深度网络最后一层输出另一个 logit。
    ydeep=wdeepTa(lf)y_{\text{deep}} = \mathbf{w}_{\text{deep}}^T \mathbf{a}^{(l_f)}
  3. 共享偏置与激活两侧分数加上共享偏置 \(b\) 后,经 Sigmoid 函数得到最终点击概率。
    σ(z)=11+e−z\sigma(z) = \frac{1}{1 + e^{-z}}

特征工程——记忆卡的制作工艺

记忆卡不是越密越好。梁伯有条规矩:只绑那些同时出现且同时有用的组合,比如“张太太”与“辣”。见什么绑什么,卡片就会变成一团乱麻,翻都翻不过来。特征工程要做的,正是决定哪些特征值得绑成一张卡。

对二值特征,交叉特征定义为若干特征的连乘,等价于逻辑 AND:

实践中,一般只挑业务上明显有共生关系的特征对做交叉,比如“城市 × 品类”“人群 × 消费品类”。连续特征要先分桶离散化再参与交叉。Deep 侧的嵌入维度也要精心选择:过大容易过拟合,过小表达不足。特征工程的本质,就是决定记忆卡上写什么、规律册里有哪些原料。

ϕk(x)=∏i=1dxicki,cki∈{0,1}\displaystyle \phi_k(\mathbf{x}) = \prod_{i=1}^{d} x_i^{c_{ki}}, \quad c_{ki} \in \{0, 1\}
通俗说:\(c_{ki}\) 决定第 \(i\) 个原始特征是否参与第 \(k\) 张交叉卡——参与就乘上它,不参与就乘 1,只有所有参与特征都为 1 时,这张卡才“生效”。
  1. 特征幂次\(c_{ki}\) 是一个 0/1 开关,表示第 \(k\) 张交叉卡是否包含第 \(i\) 个特征。
    cki∈{0,1}c_{ki} \in \{0, 1\}
  2. 连乘组合参与的特征值全部相乘,得到交叉特征取值。
    ϕk(x)=x1ck1⋅x2ck2⋯xdckd\phi_k(\mathbf{x}) = x_1^{c_{k1}} \cdot x_2^{c_{k2}} \cdots x_d^{c_{kd}}
  3. 开关语义当 \(c_{ki}=1\) 时,该特征原值参与连乘;为 0 时等价于乘 1 忽略它,实现“AND 绑定”。
    xicki={xi,cki=11,cki=0x_i^{c_{ki}} = \begin{cases} x_i, & c_{ki}=1 \\ 1, & c_{ki}=0 \end{cases}

超参调优——火候与配比的艺术

火候是卤味的命门。大火快卤,食材来不及入味;小火慢炖,又容易把肉煮柴。梁伯常说:“火看菜,不看表。” 训练 Wide & Deep 也是这么一门调火候的学问——Wide 和 Deep 虽在同一口锅里,却需要各自适配的学习率。

Wide 侧配 FTRL 时,常用较大的学习率(0.1~1),因为线性模型需要快速吸收稀疏信号的反馈;Deep 侧配 AdaGrad 或 Adam 时,常用较小的学习率(0.001~0.01),因为网络层数多、参数规模大,步子太大会震荡。正则化上,L1 让 Wide 的权重稀疏化,只保留少数关键交叉;L2 让 Deep 的权重平滑,抑制过拟合。整体损失是数据损失与两类正则的加权和:

网络结构方面,常见配置是 3 层全连接、每层几十到几百个神经元,嵌入维度选 8~32。梁伯的“火看菜”和调参师的“看验证集说话”本质相同:调参没有银弹,只有不断试菜、试火,才能把师徒俩的配合调到最佳。

Ltotal=LogLoss+λ1∥w∥1+λ2∥w∥22\displaystyle \mathcal{L}_{\text{total}} = \text{LogLoss} + \lambda_1\|\mathbf{w}\|_1 + \lambda_2\|\mathbf{w}\|_2^2
通俗说:训练目标 = 把数据拟合好 + 让 Wide 权重别太杂 + 让 Deep 权重别太野。\(\lambda_1\) 和 \(\lambda_2\) 就是这两条约束的松紧旋钮。
  1. 数据损失LogLoss 衡量模型预测与真实标签的差距,是训练的主目标。
    LogLoss=−1N∑i=1N[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\text{LogLoss} = -\frac{1}{N}\sum_{i=1}^{N}\left[ y_i \log \hat{y}_i + (1-y_i)\log(1-\hat{y}_i) \right]
  2. L1 稀疏正则\(\lambda_1\) 乘以权重绝对值之和,促使 Wide 侧大量权重变为 0,保持记忆卡精简。
    λ1∥w∥1=λ1∑j∣wj∣\lambda_1\|\mathbf{w}\|_1 = \lambda_1 \sum_j |w_j|
  3. L2 平滑正则\(\lambda_2\) 乘以权重平方和,约束 Deep 侧权重不过大,增强泛化稳定性。
    λ2∥w∥22=λ2∑jwj2\lambda_2\|\mathbf{w}\|_2^2 = \lambda_2 \sum_j w_j^2

应用落地——从 Google Play 出发

梁记后来开了分店,总店的老规矩依然沿用:每位新店的卤味师傅都带着梁伯的记忆卡,也都要经过小梁那套食材规律培训。这套“记忆 + 泛化”的打法,从一家店变成了一套可复制的体系——这正是 Wide & Deep 在业界的样子。

2016 年,Google 将 Wide & Deep 部署到 Google Play 应用商店。系统先通过检索(retrieval)从海量应用中生成几百个候选,再用 Wide & Deep 对候选做点击率预估排序。Wide 侧记忆“用户已经安装的应用与候选应用”的共现关系,Deep 侧泛化出用户对 app 品类的抽象偏好。上线后,应用下载点击率提升了 3.9%。

排序质量通常用 AUC 评估——随机一个正样本的模型打分高于随机一个负样本打分的概率:

此后,DeepFM、Deep & Cross Network(DCN)等模型继承了“宽深融合”的思想,把 Wide 侧从人工交叉特征演进为自动化特征交叉层。从梁记一家店到连锁店,靠的是把“记忆”和“泛化”打包成一套可复制的体系——Wide & Deep 的价值也正在于此。

AUC=1N+N−∑i∈P∑j∈NI(si>sj)\displaystyle \text{AUC} = \frac{1}{N_+ N_-} \sum_{i \in \mathcal{P}} \sum_{j \in \mathcal{N}} \mathbb{I}(s_i > s_j)
通俗说:把所有“点击样本 vs 未点击样本”两两配对,看模型把点击样本排前面的比例有多高。AUC 越接近 1,排序能力越强。
  1. 正负样本\(\mathcal{P}\) 是正样本(点击)集合,\(\mathcal{N}\) 是负样本(未点击)集合,个数分别为 \(N_+\) 和 \(N_-\)。
    ∣P∣=N+,∣N∣=N−|\mathcal{P}| = N_+, \quad |\mathcal{N}| = N_-
  2. 成对比较对每个正样本 \(i\) 和负样本 \(j\),比较模型打分 \(s_i\) 与 \(s_j\),正样本分高则计 1。
    I(si>sj)={1,si>sj0,otherwise\mathbb{I}(s_i > s_j) = \begin{cases} 1, & s_i > s_j \\ 0, & \text{otherwis}e \end{cases}
  3. 概率含义所有正负对的平均,即随机正样本排在随机负样本前面的概率。
    AUC=P(spos>sneg)\text{AUC} = P(s_{\text{pos}} > s_{\text{neg}})

AI 应用场景

Google Play 应用商店推荐

阶段:候选排序(精排)

解决的问题:传统 LR 能记住“用户看了 A 又下载了 B”的强共现,但无法理解应用之间抽象的语义关联;纯 DNN 泛化能力强,却在冷门应用上记忆不足。Wide & Deep 让“熟客偏好”与“新应用发现”同时发生,用一张记忆卡加一本规律册覆盖两类需求。

具体案例:用户历史安装过“美图秀秀”和“轻颜相机”,Wide 侧记住“美图秀秀 & 轻颜相机 → 下载修图类应用”的共现卡片;同时 Deep 侧从嵌入空间发现“自拍类工具”聚成一簇,向用户推荐一款从未见过的修图应用。两者分数融合后,候选应用的排序更贴合用户真实意图。

电商信息流广告点击率预估

阶段:CTR 预估精排

解决的问题:广告系统特征极度稀疏,用户 ID × 商品 ID 的交叉组合多到人工特征工程无法覆盖。Wide 侧保留少数高价值交叉特征(如“母婴人群 × 奶粉品类”)做精准记忆,Deep 侧自动学习用户与商品之间不易察觉的关联。

具体案例:大促期间,某用户 Wide 侧命中“母婴人群 × 奶粉”记忆卡,给出较高基础分;Deep 侧从用户近期浏览序列发现偏好悄悄漂移到“儿童玩具”。双通道融合后,模型既没有丢掉老偏好,又捕捉到了新兴趣,CTR 预估的 AUC 提升约 1.2%。

短视频推荐中的探索与利用

阶段:召回 / 粗排

解决的问题:用户对重复内容有高粘性(记忆),但一直推同质内容会导致留存下降(需要泛化)。Wide 捕捉“反复观看宠物视频”的强信号,Deep 泛化出“萌宠 + 治愈系音乐”的组合偏好,在熟悉与猎奇之间取得平衡。

具体案例:某短视频平台发现,用户对“金毛犬”视频点击率极高,但连续推送 20 条后次日留存下降。加入 Wide & Deep 后,Wide 继续保底推送金毛相关视频,Deep 则尝试推荐“猫咪 + 轻音乐”等高相关但未看过的内容,整体人均观看时长提升 6%。

Python 演示

python57 行
import torchimport torch.nn as nnimport torch.optim as optim  class WideDeep(nn.Module):    """Wide&Deep 推荐模型:左侧线性记忆 + 右侧嵌入泛化"""     def __init__(self, wide_dim, vocab_size, embedding_dim,                 hidden_units, seq_len):        super(WideDeep, self).__init__()        self.wide = nn.Linear(wide_dim, 1)  # 老师傅的记忆卡        self.emb = nn.Embedding(vocab_size, embedding_dim)  # 稠密嵌入        deep_in = embedding_dim * seq_len        layers = []        for h in hidden_units:            layers.append(nn.Linear(deep_in, h))            layers.append(nn.ReLU())            deep_in = h        layers.append(nn.Linear(deep_in, 1))        self.deep = nn.Sequential(*layers)  # 小学徒的规律册     def forward(self, x_wide, x_sparse):        wide_logit = self.wide(x_wide)        emb_vec = self.emb(x_sparse).view(x_sparse.size(0), -1)        deep_logit = self.deep(emb_vec)        return torch.sigmoid(wide_logit + deep_logit)  # 一口锅里出菜  def main():    torch.manual_seed(42)    wide_dim = 10    vocab_size = 100    batch_size = 64     model = WideDeep(wide_dim, vocab_size, 8, [32, 16], 5)    optimizer = optim.Adam(model.parameters(), lr=0.001)    loss_fn = nn.BCELoss()     for epoch in range(5):        total_loss = 0.0        for _ in range(20):            x_wide = torch.randint(0, 2, (batch_size, wide_dim)).float()            x_sparse = torch.randint(0, vocab_size, (batch_size, 5))            y = torch.randint(0, 2, (batch_size, 1)).float()             pred = model(x_wide, x_sparse)            loss = loss_fn(pred, y)            optimizer.zero_grad()            loss.backward()            optimizer.step()            total_loss += loss.item()        print("epoch {} loss {:.4f}".format(epoch + 1, total_loss / 20))  if __name__ == "__main__":    main()
目的:用 PyTorch 从零搭建一个简化版 Wide & Deep 模型,演示双通道如何共享损失并联合训练。
  1. self.wide = nn.Linear(wide_dim, 1)对应 Wide 通道,直接对原始特征做线性加权,相当于老师傅的记忆卡。
  2. self.emb = nn.Embedding(vocab_size, embedding_dim)把稀疏的 ID 序列映射成稠密向量,是 Deep 通道的入口。
  3. emb_vec = self.emb(x_sparse).view(x_sparse.size(0), -1)将序列中每个 ID 的嵌入拼接成一条长向量,作为全连接网络的输入。
  4. self.deep = nn.Sequential(*layers)用循环堆出多层全连接 + ReLU,模拟小学徒的规律册。
  5. return torch.sigmoid(wide_logit + deep_logit)Wide 与 Deep 的打分相加后过 Sigmoid,这正是“一口锅”的联合输出。
  6. loss_fn = nn.BCELoss()二分类交叉熵损失,对应正文中的 LogLoss 目标函数。

常见误区

误区Wide & Deep 是不是就是把逻辑回归和深度网络分别训练好,最后把两个模型的预测分加起来?感觉跟随机森林、GBDT 那种集成差不多。

正解两者有本质区别。集成学习是“各自训练、事后融合”,两位厨师各炒各的菜,最后拼盘上桌;Wide & Deep 是“联合训练、同步更新”,两个通道共享同一个损失函数,反向传播时梯度同时流向 Wide 和 Deep 的所有参数。Wide 的权重会在 Deep 误差信号的牵引下调整,Deep 的嵌入也会因 Wide 的梯度而更新,这是真正的“同灶共火”。

为何常见:从表面看,两个子模型都有一个输出、最终相加,和集成学习的“多模型融合”形态确实相似。但联合训练与集成在训练机制上完全不同,初学者很容易被“相加”这个动作误导。

误区既然 Deep 网络那么强,能自动学习高阶特征交互,那 Wide 侧的交叉特征是不是多余?我是不是只要堆 Deep 就够了?

正解Deep 对稠密特征(如数值、嵌入)的高阶交互学习能力很强,但对极度稀疏的离散 ID 特征,深度网络很难直接记住“用户 A 装了 B 又点了 C”这种具体共现,尤其在数据稀疏时容易欠拟合。Wide 的交叉特征把“共现先验”直接作为输入喂给模型,让模型不用从头学就能记住这些组合。小梁再聪明,也得靠梁伯的记忆卡记熟客口味。

为何常见:深度学习“自动提取特征”的宣传深入人心,让人误以为特征工程已经过时。但在稀疏场景中,先验知识注入依然是提升记忆能力的关键,这也是 Wide 通道存在的价值。

误区Wide 不就是一个线性模型吗?用什么优化器训练差别不大,统一用 Adam 就好了,简单省事。

正解Wide 侧推荐 FTRL 配合 L1 正则,目的是在训练过程中保持权重稀疏——让大部分交叉特征权重归零,只保留真正有效的记忆卡。如果用 Adam 训练,得到的往往是密集权重,模型会记住大量噪声组合,泛化变差且推理开销增大。FTRL 之于 Wide,就像定期清理记忆卡之于梁伯。

为何常见:很多入门教程为了方便,直接对两个通道统一用 Adam,让学生误以为优化器选择无关紧要。实际工程中 FTRL 是 Wide 侧的标配。

误区模型训练好了,离线 AUC 也达标了,上线部署之后应该就不用管了吧?推荐系统不都是一次训练永久使用的吗?

正解用户兴趣和内容生态都在持续变化。今天红遍全网的“张太太要辣不要蒜”,下周可能就改口味了。推荐模型需要周期性做增量训练或在线学习,Wide 侧的交叉卡片要随数据分布变化不断更新,Deep 侧的嵌入也要定期用新数据微调。否则模型会逐渐落后于用户真实偏好,点击率随之下滑。

为何常见:离线训练给人类似“一次性交付”的错觉,但推荐系统的本质是持续适应数据分布漂移的在线决策系统,这点在校园实验与工程落地之间存在巨大落差。

面试题

Q1. Wide 通道最核心的职责是什么?

单选题 · easy

  • A.记忆特征间共现组合← 正确答案
  • B.自动学习高阶特征
  • C.降低模型推理耗时
  • D.压缩稀疏特征维度

答案:A。Wide 通道是线性模型,直接作用在原始特征和交叉特征上,本质是记忆“特征 A 与特征 B 同时出现”的共现模式。选项 B 是 Deep 通道的职责,C 和 D 与 Wide 无直接关系。

Q2. Deep 通道中嵌入层的作用是什么?

单选题 · easy

  • A.把稀疏 ID 映射为稠密向量← 正确答案
  • B.把稠密向量映射为稀疏 ID
  • C.直接在原始特征上加权求和
  • D.对输出概率做归一化处理

答案:A。嵌入层将一个数百万维的 one-hot 稀疏 ID 映射为 8~32 维稠密向量,语义相近的 ID 在低维空间中距离更近。C 是 Wide 的行为,B 方向反了,D 是 Sigmoid 的职责。

Q3. Wide&Deep 中的“交叉特征”本质是什么?

单选题 · mid

  • A.多个特征的逻辑与组合← 正确答案
  • B.多个特征取算术平均值
  • C.特征经过 Sigmoid 映射
  • D.特征做主成分分析降维

答案:A。交叉特征 \(\phi_k(x) = \prod x_i^{c_{ki}}\) 等价于逻辑 AND——只有所有参与特征同时为 1 时才取 1。这就像梁伯把“辣”和“不要蒜”绑成一张红绳卡片。

Q4. Wide 与 Deep 联合训练时,梯度如何流动?

单选题 · mid

  • A.各自独立训练后加权融合
  • B.共享损失同时反向传播← 正确答案
  • C.先训练 wide 再训练 deep
  • D.每轮交替冻结一侧权重

答案:B。联合训练意味着两个通道共享同一个损失函数,误差信号的梯度同时反向传播到 Wide 和 Deep 的参数。A 描述的是集成学习,C 和 D 是人为构造的训练策略,均不符合 joint training。

Q5. Wide 侧通常搭配哪种优化器?

单选题 · hard

  • A.FTRL 配合 L1 正则← 正确答案
  • B.Adam 配合 L2 正则
  • C.SGD 配合动量加速
  • D.RMSProp 自适应调整

答案:A。论文中 Wide 侧使用 FTRL + L1,目的是在训练中保持权重稀疏,只保留关键交叉特征。Deep 侧才用 AdaGrad。FTRL 之于 Wide,就像定期整理记忆卡之于梁伯。

Q6. 评估排序模型最常用的指标是哪个?

单选题 · mid

  • A.AUC 曲线下面积← 正确答案
  • B.平均绝对误差 MAE
  • C.训练集交叉熵值
  • D.模型推理延迟毫秒

答案:A。AUC 衡量随机正样本排在随机负样本前面的概率,是点击率预估排序最常用的指标。MAE 用于回归,训练集交叉熵容易过拟合误判,推理延迟是工程指标而非排序质量指标。

Q7. Wide&Deep 论文的落地场景是哪里?

单选题 · easy

  • A.YouTube 视频推荐系统
  • B.Google Play 应用商店← 正确答案
  • C.淘宝商品搜索结果
  • D.抖音短视频信息流

答案:B。2016 年的论文将 Wide & Deep 部署到 Google Play 应用商店做应用推荐,上线后点击率提升 3.9%。其余选项是后来类似思想的应用场景,但不是论文原始落地场景。

Q8. Deep 通道的标准构成包含哪些?

多选题 · mid

  • A.稀疏特征的嵌入层← 正确答案
  • B.多层全连接网络← 正确答案
  • C.ReLU 非线性激活← 正确答案
  • D.主成分分析降维

答案:ABC。Deep 通道由嵌入层 + 多层全连接 + ReLU 激活构成,嵌入把稀疏 ID 变稠密,全连接逐层提炼高阶交互。D 的 PCA 是无监督线性降维,与 Deep 通道无关。

Q9. 关于 Wide&Deep 的联合训练,哪些说法正确?

多选题 · hard

  • A.两个通道共用损失函数← 正确答案
  • B.两个通道独立更新参数
  • C.Wide 用 FTRL 保持稀疏← 正确答案
  • D.Deep 用 AdaGrad 稳定收敛← 正确答案

答案:ACD。联合训练的核心就是 A:共享损失、同步更新。C 和 D 是论文的实用配置——Wide 用 FTRL + L1 保持稀疏,Deep 用 AdaGrad 稳定收敛。B 描述的是独立训练,与联合训练矛盾。

Q10. 下列哪些属于 Wide&Deep 思想的后续演进模型?

多选题 · mid

  • A.DeepFM 自动化交叉← 正确答案
  • B.DCN 交叉特征层← 正确答案
  • C.FTRL 在线学习器
  • D.Word2Vec 词嵌入

答案:AB。DeepFM 用因子分解机替代 Wide 侧自动做二阶交叉,DCN 引入 Cross 层做显式特征交叉,两者都继承并演进“宽深融合”思想。FTRL 是优化器,Word2Vec 是词嵌入方法,均不属于 Wide&Deep 的演进模型。