深夜 11 点,你躺在沙发上刷手机,外卖 App 弹出一条推送:“附近新开奶茶店,深夜满减”。你心想:它怎么知道我想喝奶茶?其实系统看到的不只是“现在 23 点”,也不只是“你常点奶茶”,而是把“深夜 + 外卖 + 奶茶”这些特征叠在一起看。单个特征像孤零零的食材——土豆是土豆、辣椒是辣椒,没什么特别;可一旦“土豆 + 辣椒 + 醋”进了炒锅,就成了让人流口水的酸辣土豆丝。推荐系统里,把多个特征组合成新语义的过程,就叫特征交叉(Feature Crossing)。 交叉的方式千差万别:有的像菜谱一样明明白白写下“番茄配鸡蛋”,这是显式交叉;有的像私房菜师傅凭手感“少许盐、适量油”,这是 DNN 自动完成的隐式交叉;有的像水煮鱼那样花椒辣椒豆瓣酱层层叠加,这是高阶交叉;还有的像美食评论家只对招牌菜大书特书,这是注意力交叉。本文就从这口炒锅讲起,看看 DeepFM、Deep&Cross、AutoInt 这些模型如何用不同“做法”烹制特征交叉这道菜。

岗位关联

理解特征交叉的范式差异,能帮你为推荐模型选对架构、定位瓶颈,是 CTR 预估与排序调优的核心内功。

目录
  1. 可视化演示
  2. 交叉核心认知
  3. 显式交叉范式
  4. 隐式交叉范式
  5. 高阶交叉范式
  6. 注意力交叉范式
  7. 范式横向对比
  8. 自动交叉搜索
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示推荐系统中显式特征笛卡尔积交叉、FM隐式二阶交叉的点积参数化、DeepFM联合FM与DNN的高阶交叉架构。

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

显式特征交叉 用户/物品/上下文三组特征独立编码 笛卡尔积手工构造交叉特征如年龄×品类 x_cross=xi×xj 人工定义交叉依赖领域知识且组合爆炸

交叉核心认知

土豆丝单独吃很普通,配上醋和辣椒就成了让人上头的酸辣土豆丝——食材没变,变的是搭配。推荐系统也一样:单看“时间=23 点”,系统猜不出你想吃什么;单看“品类=奶茶”,也未必会下单;但“深夜 + 奶茶 + 外卖”三个特征同时出现,订单概率就直线上升。这种“组合起来才有意义”的模式,就是特征交叉。交叉的本质,是把多个原始特征揉成一个新的语义信号,交给模型去打分。

推荐模型的预测目标通常是 CTR(点击率),而用户是否点击几乎总是由多个因素共同决定的:一个 20 岁的男大学生在深夜看到手游广告,和一位 40 岁的家庭主妇看到同一广告,反应截然不同。如果模型只看“广告是手游”这一个特征,就永远学不到这种差异。交叉特征捕捉的正是这种非线性关系,因此交叉质量往往直接决定 CTR 预估的上限。

如果把“是否点击”写成数学表达式,一阶项是每个特征单独打分,二阶交叉项则是两个特征共同出现时额外加分:

理解交叉的核心认知后会发现:不同的“搭配方式”对应了不同的模型范式。显式交叉像写死的菜谱,隐式交叉像自由发挥的手感,二者各有利弊,而后续要讲的 DeepFM 正是要把两者端上同一张餐桌。

w1x1+w2x2⏟一阶线性项+w12x1x2⏟二阶交叉项\displaystyle \underbrace{w_1 x_1 + w_2 x_2}_{\text{一阶线性项}} + \underbrace{w_{12} x_1 x_2}_{\text{二阶交叉项}}
这个式子说明:先让每个特征独立发言,再给“同时出现”的组合补一笔权重,交叉项只有在两个特征都非零时才被激活。
  1. 特征取值$x_1$ 表示第一个原始特征的取值,比如“深夜=1”;$x_2$ 表示第二个特征,比如“奶茶品类=1”。它们都是稀疏的二值信号。
    x1,x2x_1, x_2
  2. 一阶线性项$w_1 x_1 + w_2 x_2$ 是模型对每个特征单独打分后求和,两个特征互不影响,就像菜单上只写单品、不写搭配。
    w1x1+w2x2w_1 x_1 + w_2 x_2
  3. 二阶交叉项$x_1 x_2$ 的乘积只有在两个特征同时取非零值时才不为零,天然表达“同时出现”这个事件。
    x1x2x_1 x_2
  4. 交叉权重$w_{12}$ 是模型为这对组合专门学习的权重,回答“深夜遇到奶茶,到底值多少分”。
    w12w_{12}

显式交叉范式

有些餐厅把经典搭配明明白白写进菜单:“番茄炒蛋”——番茄必须配鸡蛋,这是厨师们验证过无数次的黄金组合。显式交叉就是这个思路:在模型里明确指出哪些特征要组合,把 $x_i \times x_j$ 这样的乘积项作为新特征放进去。它的好处是直白、可控、可解释,但推荐场景的特征往往经过 one-hot 编码后有上亿维度,两两组合会膨胀到 $n^2$ 量级,绝大多数组合在样本里压根没出现过,根本学不动。

FM(因子分解机)解决了这个难题。它的巧思是:不再为每对特征单独学一个权重 $w_{ij}$,而是给每个特征学一个低维隐向量 $\mathbf{v}_i$,任意两个特征的交叉权重用两个隐向量的点积 $\langle \mathbf{v}_i, \mathbf{v}_j \rangle$ 来近似。这样参数从 $O(n^2)$ 降到 $O(nk)$,而且相似的食材(特征)会共享调料(隐向量),即使某个组合从未在训练数据中出现,也能借助各自隐向量的相似性推出合理的交叉权重。FM 的完整预测式如下:

DeepFM 则更进一步:它把 FM 作为“显式交叉”模块,同时并联一个 DNN 作为“隐式交叉”模块,两者共享同一份 embedding,最后把两路分数相加。显式交叉保证模型至少能学到可靠的二阶组合,隐式交叉则负责挖掘更复杂的模式。显式交叉像写死的菜谱,稳定但无法穷尽所有美味;隐式的加入让 DeepFM 既有了基本功,也有了想象力。

y^FM(x)=w0+∑i=1nwixi+∑i=1n∑j=i+1n⟨vi,vj⟩xixj\displaystyle \hat{y}_{\mathrm{FM}}(\mathbf{x}) = w_0 + \sum_{i=1}^{n} w_i x_i + \sum_{i=1}^{n}\sum_{j=i+1}^{n} \langle \mathbf{v}_i, \mathbf{v}_j \rangle x_i x_j
FM 的核心贡献:用隐向量点积替代显式的两两权重,在稀疏特征下既控制了参数规模,又实现了跨组合的泛化。
  1. 全局偏置$w_0$ 是模型的底味,代表整体点击率的平均水平,相当于不管什么菜,餐厅都有一个基础人气。
    w0w_0
  2. 一阶部分$\sum_{i=1}^{n} w_i x_i$ 遍历所有特征,为每个特征单独打分,这是每个食材的“单品价格”。
    ∑i=1nwixi\sum_{i=1}^{n} w_i x_i
  3. 双重求和$\sum_{i=1}^{n}\sum_{j=i+1}^{n}$ 保证每对特征只被计算一次,且不包含自己和自己交叉,遍历所有“两两搭配”的菜谱组合。
    ∑i=1n∑j=i+1n\sum_{i=1}^{n}\sum_{j=i+1}^{n}
  4. 隐向量点积$\langle \mathbf{v}_i, \mathbf{v}_j \rangle$ 是两个特征隐向量的内积,数值越大表示这对食材越“合拍”,交叉权重越高。
    ⟨vi,vj⟩\langle \mathbf{v}_i, \mathbf{v}_j \rangle
  5. 特征相乘$x_i x_j$ 是两个特征取值相乘,只有特征同时非零时才激活这个交叉项,对应“同时出现”事件。
    xixjx_i x_j

隐式交叉范式

私房菜师傅说不出精确菜谱,只告诉你“花椒一点点,盐看手感”——但人家炒出来的菜就是香。DNN 的隐式交叉就是这样一种“说不清道不明”的融合:你不需要告诉网络“年龄和品类要交叉”,它自己会在一次次前向传播中,把特征层层混合,最终形成复杂的组合模式。这就是隐式交叉:不显式指定交叉哪些特征,而是通过网络的深度和非线性变换自动完成。

多层神经网络的每一层都在做两件事:对上一层输出做加权求和(线性混合),再经过一个激活函数(引入非线性)。数学上可以证明,足够深的网络能逼近任意函数,理论上隐式交叉的表达空间极大。但理论是理论,实践有代价——在推荐这种超高维、极度稀疏的场景下,网络要学到三阶以上的高阶组合,需要非常深的层数和海量的数据,否则很多权重根本得不到有效训练。

隐式交叉的更新过程可以写成一个简洁的递推式:

隐式交叉像手感型大厨:上限很高,能做出显式菜谱想象不到的惊喜,但也可能发挥不稳定——训练难收敛、交叉模式不可解释、调参像玄学。这也是为什么业界很少单独用纯 DNN 做特征交叉,而是把它和显式方法组合起来,互相兜底。理解隐式交叉的局限,是理解高阶交叉范式出场理由的钥匙。

h(l+1)=σ(W(l)h(l)+b(l))\displaystyle \mathbf{h}^{(l+1)} = \sigma\left(\mathbf{W}^{(l)} \mathbf{h}^{(l)} + \mathbf{b}^{(l)}\right)
每一层本质上是在“搅拌”上一层的特征表示,权重矩阵负责混合,激活函数负责引入非线性,层数越多,混合的“阶数”就越高。
  1. 输入表示$\mathbf{h}^{(l)}$ 是第 $l$ 层的特征向量,可以理解为当前层次的“食材半成品”。
    h(l)\mathbf{h}^{(l)}
  2. 权重矩阵$\mathbf{W}^{(l)}$ 的每一行都是对全部输入特征做一次加权组合,相当于把上一层的所有食材按不同比例倒进锅里。
    W(l)\mathbf{W}^{(l)}
  3. 偏置项$\mathbf{b}^{(l)}$ 给每个神经元一个基础偏移,相当于锅底先抹的一层油,无论食材如何都有个保底。
    b(l)\mathbf{b}^{(l)}
  4. 激活函数$\sigma$ 是 ReLU 等非线性函数,它把线性混合的结果“掰弯”,让网络有能力表达非线性的交叉关系。
    σ\sigma

高阶交叉范式

水煮鱼不是简单的“鱼 + 辣椒”两两搭配,而是豆瓣酱、花椒、蒜末、姜片层层复合,每种调料在不同的烹饪阶段依次释放风味。真实的用户行为也常常需要更高的交叉阶数:“年轻 + 男性 + 学生 + 深夜 + 手游广告”——五阶交叉可能才最能说明问题。所谓高阶交叉,指三个及以上特征的组合。

但问题来了:直接枚举三阶组合,参数是 $n^3$ 量级,计算上完全不可行。Deep&Cross 提出了一种优雅的解法。它的 Cross Network 每一层都做这样一件事:拿原始输入 $\mathbf{x}_0$ 和当前层表示 $\mathbf{x}_l$ 做外积,得到交叉项,再与当前层相加。由于原始输入每一层都参与,所以每一层都在“跟原料对话”,层数越多,能表达的交叉阶数就越高。关键巧妙之处在于,每层只有一份权重向量 $\mathbf{w}_l$,参数只有 $O(d)$,不会随交叉阶数爆炸:

与 Deep&Cross 并列的还有 CIN(Compressed Interaction Network),它通过向量外积和逐位相乘来显式生成高阶特征,思路类似但计算方式不同。高阶交叉的工程要点始终是复杂度控制——用精巧的结构表达高阶组合,而不是盲目堆参数。功夫菜靠层层工序,也靠“回到原料”的初心,这正是残差连接的意义。

xl+1=x0xl⊤wl+bl+xl\displaystyle \mathbf{x}_{l+1} = \mathbf{x}_0 \mathbf{x}_l^{\top} \mathbf{w}_l + \mathbf{b}_l + \mathbf{x}_l
每一层都在“上一层的半成品”与“最初的原料”之间建立连接,残差项 $\mathbf{x}_l$ 保证信息不丢失,层与层叠加就能逼近任意高阶交叉。
  1. 当前层表示$\mathbf{x}_l$ 是第 $l$ 个交叉层输出的特征向量,代表目前已经混合好的“半成品菜”。
    xl\mathbf{x}_l
  2. 原始输入$\mathbf{x}_0$ 是未经任何变换的原始特征向量,相当于厨房里最初的生鲜食材,每一层都要回来“取材料”。
    x0\mathbf{x}_0
  3. 外积交叉项$\mathbf{x}_0 \mathbf{x}_l^{\top} \mathbf{w}_l$ 让原始特征和当前表示逐位相乘再加权,生成新的交叉信息,这一步就是“新的搭配尝试”。
    x0xl⊤wl\mathbf{x}_0 \mathbf{x}_l^{\top} \mathbf{w}_l
  4. 偏置$\mathbf{b}_l$ 是每层的可学习偏置,给交叉结果一个基础偏移。
    bl\mathbf{b}_l
  5. 残差连接$+\mathbf{x}_l$ 把本层的输入原样加到输出上,保证深层叠加时低阶信息不丢失、训练更稳定,如同炖菜时“留一勺原汤”。
    xl\mathbf{x}_l

注意力交叉范式

美食评论家不会给每道菜打一样的分数,而是对招牌菜大书特书,对配菜一笔带过。AutoInt 的注意力交叉就是这个思路:让模型动态“评论”每一对特征,决定谁和谁的交叉值得重视、重视到什么程度。相比 FM 的固定权重,注意力交叉的权重是随输入动态变化的——同一个“奶茶”特征,在深夜和中午得到的交叉权重完全不同。

AutoInt 的核心是多头自注意力。每个特征先映射成 embedding 向量,然后所有特征两两互相“打量”:Query 代表“我想关注什么”,Key 代表“我是什么”,两者点积算出相似度,经过缩放和 softmax 归一化后变成交互权重,再乘上 Value 得到加权融合结果。多头机制让不同的“头”关注不同的语义子空间——一个头可能专注“时段 × 品类”,另一个头专注“性别 × 价格”。类似地,DIN 也通过注意力为用户行为序列加权,本质都是让重要的交互“大声说话”:

注意力交叉让模型不再是“盲人摸象”式地均匀混合所有特征,而是有主次、有重点地完成交叉,并且每个权重天然可以可视化,提供了可解释性。美食评论家点到为止,却让每道菜的价值被更多人看见——注意力交叉正是这样,让重要的组合浮出水面。

Attention(Q,K,V)=softmax(QK⊤dk)V\displaystyle \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left( \frac{Q K^{\top}}{\sqrt{d_k}} \right) V
注意力分数就是模型给每对特征打的“默契分”,分数越高,这对特征在融合时的话语权越大。
  1. 三种角色$Q$ 是查询向量(“我在找什么”),$K$ 是键向量(“我是什么”),$V$ 是值向量(“我能提供什么”),三个角色都由输入特征通过不同变换得到。
    Q,K,VQ, K, V
  2. 相似度打分$Q K^{\top}$ 计算每个 Query 与所有 Key 的点积,点积越大表示两个特征越“投缘”。
    QK⊤Q K^{\top}
  3. 缩放因子除以 $\sqrt{d_k}$ 防止点积数值过大导致 softmax 进入饱和区,梯度消失,就像打分时先统一量纲再比较。
    1dk\frac{1}{\sqrt{d_k}}
  4. 归一化权重$\mathrm{softmax}$ 把原始分数压成总和为 1 的概率分布,得到“默契度权重”。
    softmax(⋅)\mathrm{softmax}(\cdot)
  5. 加权融合权重乘上 $V$ 并求和,每个特征的表示变成“所有特征按默契度加权后的混合”,完成一次交叉。
    VV

范式横向对比

选菜系要看场合:工作日晚上是快手家常菜,宴请宾客得上硬菜,追求新奇才点分子料理。特征交叉的范式选择同样是“预算与需求”的权衡。四种范式各有各的脾气,没有绝对的优劣,只有合不合适的场景。

从计算开销看,假设特征总数为 $n$,隐向量维度为 $k$,embedding 维度为 $d$,网络层数为 $L$,单次前向的计算量大致可以排序:

实践中没有哪个大厂只押注一种范式。DeepFM 就是“显式二阶 + 隐式高阶”的混合;有些团队会把 AutoInt 的注意力权重作为可解释性工具,辅助人工特征工程。选型策略可以总结为:数据稀疏选 FM,特征规模可控且要高阶选 Deep&Cross,重视可解释性和动态交互选 AutoInt,算力紧张就老老实实上 FM + DNN。没有最好的菜系,只有最合适的宴席。

O(nk)<O(Ld)<O(Ln2d)\displaystyle O(nk) < O(Ld) < O(L n^2 d)
这个链式不等式告诉我们:FM 最轻量,Deep&Cross 次之,AutoInt 的注意力交叉最贵——选择前先掂量自己的算力预算。
  1. 特征规模$n$ 是原始特征个数,$k$ 是 FM 中隐向量的维度,通常取值 4~16。
    n,kn, k
  2. FM 的开销$O(nk)$ 表示 FM 用一次矩阵乘就完成所有二阶交叉的计算,是四种范式中最便宜的选择。
    O(nk)O(nk)
  3. Cross 网络开销$L$ 是交叉层层数,$d$ 是特征向量总维度,Deep&Cross 每层只学一个向量,总开销 $O(Ld)$。
    O(Ld)O(Ld)
  4. 注意力开销AutoInt 需要为每一对特征计算注意力分数,因此是 $O(L n^2 d)$,特征数一大就会明显变贵。
    O(Ln2d)O(L n^2 d)

自动交叉搜索

大餐厅的研发部每天都在实验新配方:罗勒配芒果?巧克力配辣椒?哪怕失败一百次,只要成功一次就能成为招牌。手动设计特征交叉就像老厨师凭经验试菜,但经验有盲区,试错成本也太高——每次都要重新训练模型验证。自动特征交叉搜索,就是让机器自己当“研发员”,在搭配空间里自动探索最有价值的交叉结构。

自动搜索的第一步是定义搜索空间:交叉几阶、哪些特征参与、用什么算子(乘法、加法、拼接还是注意力)。这个空间巨大无比,穷举不可能。于是研究者引入强化学习或进化算法:让一个“控制器”不断提出交叉方案,训练评估后把性能作为奖励反馈给控制器,逐步进化出更优的搭配。近年前沿的可微分搜索更进一步,把“选哪个算子”这种离散决策松弛成连续权重,从而可以端到端地用梯度下降优化整个结构。

自动交叉搜索的优化目标通常不是单纯追求精度,而是精度与成本的权衡:

自动交叉搜索是推荐系统的前沿方向,它把“特征工程”从手工作坊变成了自动化流水线。但要泼一盆冷水:机器再会找配方,也得有齐全的食材库和稳定的灶台——高质量的特征建设与数据治理仍是地基。让机器代找新配方,人类厨师才能腾出手来想更长远的事。

θ∗=arg⁡max⁡θ∈Θ  (AUC(θ)−λ⋅Cost(θ))\displaystyle \theta^{*} = \arg\max_{\theta \in \Theta} \; \big( \mathrm{AUC}(\theta) - \lambda \cdot \mathrm{Cost}(\theta) \big)
这个式子表达了一个朴素道理:好的交叉结构不仅要 AUC 高,还要计算开销小,λ 就是“愿意为省钱牺牲多少精度”的旋钮。
  1. 搜索空间$\Theta$ 是所有候选交叉结构的集合,包含阶数、特征子集、算子类型等维度。
    Θ\Theta
  2. 目标指标$\mathrm{AUC}(\theta)$ 是候选结构 $\theta$ 在验证集上的排序能力,越高代表交叉效果越好。
    AUC(θ)\mathrm{AUC}(\theta)
  3. 成本惩罚$\mathrm{Cost}(\theta)$ 是结构 $\theta$ 的计算开销,比如参数量或推理时延,防止模型无限膨胀。
    Cost(θ)\mathrm{Cost}(\theta)
  4. 权衡系数$\lambda$ 控制“精度优先”还是“效率优先”,λ 越大,模型越倾向于选择轻量结构。
    λ\lambda

AI 应用场景

电商 CTR 预估与商品推荐

阶段:特征工程与模型训练

解决的问题:电商平台的特征是典型的超高维稀疏数据(用户 ID、商品 ID、类目、品牌),人工做两两组合会让维度爆炸且无法覆盖长尾组合。FM 和 DeepFM 用隐向量刻画交叉权重,自动完成显式二阶交叉,在稀疏数据下也能学到可靠的“用户偏好 × 商品属性”组合,显著提升点击率预估的 AUC。

具体案例:某电商 App 的首页信息流,用户特征“价格敏感度”与商品特征“是否参加满减”单独看都不够强,交叉后却能精准识别“爱买便宜货但需要凑单”的用户群。工程上以 DeepFM 为主模型,把商品侧的类别特征和用户侧的消费水平特征通过 FM 部分显式交叉,行为序列部分交给 DNN 隐式建模,在离线评估和线上 A/B 中均稳定提升 CTR。

短视频信息流的高阶兴趣捕捉

阶段:粗排与精排模型

解决的问题:用户刷短视频的决策往往是多因素共同作用的结果,比如“通勤 + 晚高峰 + 短视频时长偏好 + 内容类型”这样的高阶组合。传统 LR 模型无法表达这种非线性关系。Deep&Cross 网络通过多层交叉结构,在保持参数规模可控的同时自动学习高阶特征组合,捕捉复杂多变的兴趣模式。

具体案例:某短视频平台发现,“晚上 10 点到 12 点”这个时段特征单独看对点击率影响不大,但叠加“用户是大学生 + 内容为游戏解说”后,点击率显著抬升。引入 Deep&Cross 后,这类三阶及四阶的组合被网络自动捕捉,推荐流的人均观看时长提升了约 5%。

广告投放中的动态交叉寻优

阶段:广告排序与出价模型

解决的问题:广告系统的特征交互随上下文剧烈变化:同一个广告主行业在不同年龄段用户面前的表现完全不同,固定权重的交叉无法适应这种动态性。AutoInt 用多头注意力让模型动态计算特征对的交互权重,同时给出可解释的权重供投放策略分析,帮助广告主理解“哪些特征组合在什么场景下最有效”。

具体案例:某广告平台在游戏行业投放中,通过 AutoInt 的注意力权重发现“新上线手游 + 男性用户的付费行为”这对组合在周末权重极高,据此调整了周末出价策略和素材定向,广告转化成本下降了 12%。

Python 演示

python84 行
import numpy as np  def sigmoid(z):    z = np.clip(z, -30.0, 30.0)    return 1.0 / (1.0 + np.exp(-z))  class LR:    """逻辑回归: 只做一阶线性特征组合"""     def __init__(self, lr=0.1, epochs=100):        self.lr = lr        self.epochs = epochs        self.w = None     def fit(self, X, y):        n = X.shape[1]        self.w = np.zeros(n)        for _ in range(self.epochs):            p = sigmoid(X @ self.w)            grad = X.T @ (p - y) / len(X)            self.w -= self.lr * grad        return self     def predict(self, X):        return sigmoid(X @ self.w)  class FM:    """因子分解机: 显式二阶特征交叉, 交互权重用隐向量点积"""     def __init__(self, n_features, k=6, lr=0.05, epochs=80, reg=0.01):        self.n_features = n_features        self.k = k        self.lr = lr        self.epochs = epochs        self.reg = reg        self.w0 = 0.0        self.w = np.zeros(n_features)        self.V = np.random.normal(0, 0.1, (n_features, k))     def _interaction(self, X):        xv = X @ self.V                       # (n, k) 特征加权表示        sq = (X ** 2) @ (self.V ** 2)        return 0.5 * ((xv ** 2).sum(axis=1) - sq.sum(axis=1))     def predict(self, X):        logit = self.w0 + X @ self.w + self._interaction(X)        return sigmoid(logit)     def fit(self, X, y):        n = len(X)        for _ in range(self.epochs):            p = self.predict(X)            err = p - y            self.w0 -= self.lr * err.mean()            self.w -= self.lr * (X.T @ err / n + self.reg * self.w)            xv = X @ self.V            dV = np.zeros_like(self.V)            for f in range(self.n_features):                # 公式: x_f * (xv_k - x_f * v_fk) 对 err 加权取平均                dV[f] = (err * X[:, f] * (xv - X[:, f] * self.V[f])).mean(axis=0)            self.V -= self.lr * (dV + self.reg * self.V)        return self  def make_ctr_data(n=2000, seed=42):    """构造 CTR 数据, 标签依赖二阶交叉规律"""    rng = np.random.default_rng(seed)    X = rng.integers(0, 2, size=(n, 6)).astype(float)    logit = 0.3 - 1.5 * X[:, 0] * X[:, 2] + 1.0 * X[:, 1] * X[:, 3]    y = (rng.random(n) < sigmoid(logit)).astype(int)    return X, y  if __name__ == "__main__":    X, y = make_ctr_data()    lr = LR().fit(X, y)    fm = FM(n_features=6, k=6).fit(X, y)    lr_acc = ((lr.predict(X) > 0.5) == y).mean()    fm_acc = ((fm.predict(X) > 0.5) == y).mean()    print("LR 一阶准确率: %.3f" % lr_acc)    print("FM 二阶交叉准确率: %.3f" % fm_acc)
目的:演示显式二阶交叉的价值——当标签规律藏在特征组合里时,一阶线性模型 LR 学不到,而 FM 通过隐向量点积能显著提升预测准确率。
  1. self.V = np.random.normal(0, 0.1, (n_features, k))初始化每个特征的隐向量,k 是隐向量维度,相当于给每种“食材”备好一组“调味料”。
  2. xv = X @ self.V把特征矩阵与隐向量矩阵相乘,得到所有特征在隐维度上的加权表示,这是计算全部两两交叉的原料。
  3. sq = (X ** 2) @ (self.V ** 2)二阶交叉公式的另一半,用来在 O(nk) 时间内一口气算出所有组合,而不是逐个枚举 n² 对。
  4. return 0.5 * ((xv ** 2).sum(axis=1) - sq.sum(axis=1))用等式变换把“两两交叉求和”化简成两项之差,这是 FM 能高效处理稀疏特征的关键技巧。
  5. logit = 0.3 - 1.5 * X[:, 0] * X[:, 2] + 1.0 * X[:, 1] * X[:, 3]生成数据时故意把标签规律藏在二阶交叉里,一阶模型看不到这个规律,FM 却能学到。
  6. dV[f] = (err * X[:, f] * (xv - X[:, f] * self.V[f])).mean(axis=0)对每个特征的隐向量求梯度,让交叉项朝降低误差的方向更新,这是 FM 训练的“出锅调味”步骤。

常见误区

误区新手常常认为,交叉就是 x1 乘 x2 嘛,把乘出来的新特征直接喂给模型就完事了,哪有那么复杂。

正解对稠密连续特征,直接乘积可能有效;但对 one-hot 后的稀疏特征(推荐场景的常态),直接乘积会让特征维度从 n 膨胀到 n²,而且绝大多数组合在样本里从未出现,学不到可靠权重。FM 的隐向量点积才是处理稀疏交叉的正确姿势:参数只有 O(nk),还能让相似特征共享隐向量,实现跨组合泛化。交叉的本质是“学到组合的权重”,而不是“把两个数乘起来”。

为何常见:从特征工程的直觉出发,乘法是最自然的组合操作,人们容易忽略高维稀疏下维度爆炸和样本稀疏的现实。

误区DNN 不是万能逼近器吗?多层网络总能自动学会特征组合,显式交叉完全是多此一举。

正解理论万能不等于实践可行。DNN 每个神经元对全部输入做加权混合,要近似高阶交叉需要足够深和足够多的数据;而推荐特征超高维稀疏,大量权重学不到有效信号。FM 类显式交叉把二阶组合直接建模,收敛快、可解释、参数高效,还能给 DNN 一个“站在肩膀上”的起点。这也是 DeepFM 混合两者往往能涨点的原因——显隐结合,互相兜底。

为何常见:被万能逼近定理的结论误导,忽略了有限数据和稀疏特征这两个推荐场景最硬的现实约束。

误区Deep&Cross 的交叉层能产生高阶交叉,那我叠个一百层,表达能力不就无敌了?

正解Cross 层每层参数只有 O(d),加深确实能提高交叉阶数,但过深的层会引入冗余和噪声,造成过拟合与训练不稳定。主流实践通常控制在 2~6 层,并配合残差与正则使用。高阶交叉带来的收益是递减的:三阶到四阶的提升远小于二阶到三阶,而计算和内存开销却在增加。适度交叉,别把蒸笼叠到天花板。

为何常见:把“模型越深越强”的一般印象不加分析地套用到交叉网络上,忽略了交叉层的特殊性。

误区AutoInt 的注意力能动态加权交叉,比 FM 和 Cross 都高级,那其他范式都可以扔掉了。

正解AutoInt 的自注意力要对所有特征对计算分数,复杂度是 O(n²d),特征维度一大,训练和推理的延迟都明显上升。它学到的权重是模型内部的软分配,并不保证能替代显式交叉那样直接可控的组合。实践中 AutoInt 常与 FM、DNN 组合使用,或作为特征重要性分析工具辅助人工特征工程。选型要按数据规模、延迟预算和可解释需求来定,而不是追新。

为何常见:被新模型的宣传效果吸引,忽略了场景约束和成本考量。

面试题

Q1. FM 中两个特征的交互权重是怎么获得的?

单选题 · easy

  • A.直接训练一个乘积项专属参数
  • B.两个特征各自隐向量的点积← 正确答案
  • C.两个特征基础权重的平均值
  • D.注意力分数乘以特征值的和

答案:B。FM 的核心创新是不直接学 w_ij,而是给每个特征配一个隐向量,交互权重用两个隐向量的内积计算。A 是朴素二阶模型的做法,参数爆炸;C 只是简单的算术;D 是注意力机制的做法。

Q2. 特征交叉的“阶数”指的是什么?

单选题 · easy

  • A.参与组合的特征数量← 正确答案
  • B.模型神经网络的层数
  • C.特征 embedding 的维度
  • D.候选特征集合的大小

答案:A。二阶交叉是两个特征组合,三阶是三个特征组合,阶数就是参与组合的特征数量。B 是网络深度,C 是向量维度,D 是特征池规模,都与交叉阶数的定义无关。

Q3. DeepFM 中 FM 与 DNN 的分工,正确的是?

单选题 · easy

  • A.FM 学显式二阶,DNN 学隐式高阶← 正确答案
  • B.FM 做特征选择,DNN 做维度压缩
  • C.FM 负责序列建模,DNN 处理交叉
  • D.FM 输出初筛候选,DNN 输出终分

答案:A。DeepFM 的设计哲学是“显隐互补”:FM 部分负责显式二阶交叉,DNN 部分凭借深层非线性自动完成隐式高阶交叉。其余选项描述的特征选择、序列建模、级联排序都不是两者的原始分工。

Q4. 相比对每个特征对单独学权重,FM 用隐向量的最大好处是?

单选题 · mid

  • A.参数从平方级降到线性级← 正确答案
  • B.让特征顺序不再影响结果
  • C.完全消除特征稀疏问题
  • D.使模型变成纯线性模型

答案:A。n 个特征两两组合需要学 n² 个权重,FM 给每个特征一个 k 维隐向量,参数总共 nk 个,从平方级降到线性级。B 特征顺序本就不影响;C 隐向量不消除稀疏只是缓解;D FM 含交叉项不是纯线性。

Q5. Deep&Cross 交叉层中残差连接的主要作用是什么?

单选题 · mid

  • A.保留低阶信息并稳定训练← 正确答案
  • B.引入额外的非线性激活函数
  • C.把高维特征降维到低维空间
  • D.让每层的参数量翻倍增长

答案:A。残差连接把本层输入 x_l 原样加到输出上,让深层叠加时低阶信息不丢失,同时为梯度提供短路通道,训练更稳定。B 非线性由激活函数提供;C 是降维层的事;D 参数量不会因残差翻倍。

Q6. AutoInt 缩放点积注意力除以 sqrt(dk) 的目的是什么?

单选题 · hard

  • A.防止点积过大导致 softmax 饱和← 正确答案
  • B.把 Q 与 K 映射到同一维度
  • C.让注意力分数限定在零到一
  • D.降低矩阵乘法的计算复杂度

答案:A。当向量维度 dk 较大时,点积数值会很大,softmax 进入饱和区导致梯度极小。除以 sqrt(dk) 是 Transformer 论文中的标准缩放技巧。B 是线性变换的职责;C softmax 才负责归一化到零一;D 缩放不改变计算复杂度。

Q7. 下列哪些属于隐式交叉的特点?

多选题 · mid

  • A.交叉由网络自动学习完成← 正确答案
  • B.无需手工指定交叉特征← 正确答案
  • C.交叉过程完全可被解释
  • D.需要较多数据才能学好← 正确答案

答案:ABD。隐式交叉指 DNN 通过多层非线性变换自动完成组合,不需要手工设计,这是 A 和 B;但交叉过程像黑盒,C 错误;深度网络在稀疏数据上收敛困难,确实需要较多数据,D 正确。

Q8. DeepFM 相比单一模型能带来哪些好处?

多选题 · mid

  • A.同时获得显式与隐式交叉← 正确答案
  • B.增强模型的特征表达能力← 正确答案
  • C.保证所有交叉均可解释
  • D.减少训练所需的全部数据

答案:AB。DeepFM 并联 FM 和 DNN,同时获得显式二阶与隐式高阶的表达,特征能力更强。但 DNN 部分仍不可解释,C 错误;模型结构不会减少数据需求,D 错误。

Q9. 关于 AutoInt 多头注意力,下列说法正确的是?

多选题 · hard

  • A.多头可关注不同语义子空间← 正确答案
  • B.注意力权重具一定可解释性← 正确答案
  • C.计算复杂度随特征数线性增长
  • D.只能处理数值型连续特征

答案:AB。不同注意力头可以分别关注“时段 × 品类”“性别 × 价格”等不同交互模式,A 正确;softmax 归一化后的注意力分数代表特征对的重要性,可以可视化,B 正确。注意力需要两两计算,复杂度是 O(n²d) 而非线性,C 错误;经过 embedding 后类别特征和数值特征都能处理,D 错误。

Q10. 自动特征交叉搜索中可微分搜索的核心思想是什么?

单选题 · extreme

  • A.把离散结构松弛为连续权重优化← 正确答案
  • B.用随机网格搜索枚举全部组合
  • C.依赖人工经验设计固定交叉组合
  • D.直接删除低阶特征仅保留高阶

答案:A。可微分搜索借鉴 DARTS 的思路,把“选哪个交叉算子”的离散选择松弛为 softmax 连续权重,从而能用梯度下降端到端优化交叉结构。B 是穷举,C 是人工特征工程,D 是粗暴的剪枝,都谈不上“可微分搜索”。