想象你走进一家商场,迎面走来一位资深导购。她手里有你厚厚一沓购物小票:上周买的猫粮、昨天刚入手的机械键盘、上个月给女儿挑的洋娃娃、去年那根落灰的钓鱼竿……而你此刻正想买一盒鱼饵。她该如何从这堆五花八门的消费记录里,识别出你“钓鱼爱好者”的身份,而不是把你推荐成一个四不像的“平均顾客”?这正是传统推荐模型的死穴。DIN(深度兴趣网络)像一位会“翻旧账”的导购——推荐鱼饵时,重点翻钓鱼相关的记录;DIEN(深度兴趣演化网络)则更像能“看趋势”的导购——她不只翻旧账,还能看出你的兴趣正从钓鱼流向露营,提前把帐篷塞到你手里。这篇文章将用这套“导购心法”,帮你把 DIN 与 DIEN 的原理彻底搞懂。

岗位关联

对 AI 从业者的价值:掌握工业界点击率预估中最实用的两套兴趣建模方案,理解注意力机制与序列建模在真实推荐场景中的落地方式,直接助力电商、广告、内容推荐业务的提效。

目录
  1. 可视化演示
  2. 1. 推荐系统难题
  3. 2. 行为序列处理
  4. 3. DIN 注意力激活
  5. 4. DIEN 兴趣演化
  6. 5. 训练与优化
  7. 6. 应用与对比
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

\u5C55\u793ADIN\u6CE8\u610F\u529B\u673A\u5236\u4E0EDIEN\u5174\u8DA3\u6F14\u5316\u7684\u5BF9\u6BD4\uFF1A\u884C\u4E3A\u5E8F\u5217\u901A\u8FC7\u6CE8\u610F\u529B\u6216GRU\u751F\u6210\u7528\u6237\u5174\u8DA3\u8868\u793A\u3002

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

DIN\u4E0EDIEN\u5174\u8DA3\u5EFA\u6A21\u5BF9\u6BD4 DIN\u901A\u8FC7\u6CE8\u610F\u529B\u673A\u5236\u52A8\u6001\u52A0\u6743\u5386\u53F2\u884C\u4E3A\uFF0C\u6743\u91CD\u53D6\u51B3\u4E8E\u4E0E\u76EE\u6807\u7269\u54C1\u7684\u76F8\u5173\u6027 DIEN\u5728DIN\u57FA\u7840\u4E0A\u5F15\u5165GRU\u5EFA\u6A21\u5174\u8DA3\u6F14\u5316\u8FC7\u7A0B\uFF0C\u6355\u6349\u5174\u8DA3\u8F6C\u79FB\u6A21\u5F0F v_U = \u03A3 \u03B1_i \u00B7 e_i, \u03B1_i = softmax(e_i\u00B7e_t) \u5E95\u90E8\u6743\u91CD\u6761\u53EF\u89C6\u5316\u5404\u884C\u4E3A\u7684\u6CE8\u610F\u529B\u5206\u914D\uFF0C\u4E0E\u76EE\u6807\u76F8\u5173\u7684\u884C\u4E3A\u83B7\u5F97\u66F4\u9AD8\u6743\u91CD

1. 推荐系统难题

假设你走进一家商场,一位资深导购迎面走来。她手里有你厚厚一沓购物小票:上周的猫粮、昨天的机械键盘、上个月的洋娃娃、去年的钓鱼竿……这些记录是你五花八门的兴趣,可导购该如何从一堆混杂的“旧账”里读出你此刻想要什么?这正是推荐系统每天都在面对的“读心”困局。

传统推荐模型(比如曾经很流行的 DeepFM)的做法很粗暴:把这堆记录取个平均,把“平均后的你”当作独一无二的你。于是“爱钓鱼的程序员”被平均成一个模糊的“普通上班族”,推荐结果不咸不淡——既不够懂钓鱼,也不够懂键盘。问题出在数学根源上:模型用一个固定的用户向量表示你,不管候选商品是什么,你的“画像”都不变。

推荐的本质是估计用户 \(u\) 对候选商品 \(i\) 的点击概率,传统模型的预测形式可以简写为:

好在用户的历史行为序列是一座金矿。DIN 与 DIEN 正是来挖这座金矿的:它们撕掉“平均滤镜”,让导购看懂每一张小票背后的真实兴趣。

p(u,i)=σ(MLP([vu,vi,vu,i]))\displaystyle p(u,i) = \sigma\left(\text{MLP}\left([\mathbf{v}_u, \mathbf{v}_i, \mathbf{v}_{u,i}]\right)\right)
这个公式把用户向量、商品向量拼起来喂给神经网络,输出点击概率。关键缺陷是 \(\mathbf{v}_u\) 固定不变——无论推荐鱼饵还是猫粮,你都被描述成同一个人。
  1. \(p(u,i)\)(点击概率)用户 \(u\) 点击商品 \(i\) 的概率,是推荐系统输出的“心动值”,数值越大越值得推荐。
    p(u,i)\displaystyle p(u,i)
  2. \(\sigma\)(Sigmoid 函数)把任意实数压缩到 0 到 1 之间,就像把温度计的读数归一化成“百分之多少的热度”。
    σ(x)=11+e−x\displaystyle \sigma(x) = \frac{1}{1 + e^{-x}}
  3. MLP(多层感知机)一连串“加权求和 + 非线性激活”堆叠而成,相当于导购大脑里的思考回路。
    MLP(x)=激活(W2⋅激活(W1x+b1)+b2)\displaystyle \text{MLP}(\mathbf{x}) = \text{激活}(\mathbf{W}_2 \cdot \text{激活}(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2)
  4. \([\mathbf{v}_u, \mathbf{v}_i, \mathbf{v}_{u,i}]\)(拼接向量)把用户向量、商品向量、两者交叉特征拼成一条长向量,喂给 MLP。
    [vu,vi,vu,i]\displaystyle [\mathbf{v}_u, \mathbf{v}_i, \mathbf{v}_{u,i}]
  5. 致命短板\(\mathbf{v}_u\) 不随候选商品变化,就像导购只记得“你是个爱买东西的人”,却忘了你此刻站在鱼饵柜台前——这就是“一根筋”的数学根源。
    vu=固定的用户向量\displaystyle \mathbf{v}_u = \text{固定的用户向量}

2. 行为序列处理

导购决定认真看小票,可小票上有中文、有数字、有模糊的店名。她得先把每一条记录翻译成自己能理解的标准语言——在模型里,这个“翻译”动作叫 Embedding(嵌入)。

每个商品 ID 都是离散的编号(比如“猫粮=10034”、“钓鱼竿=20331”),编号之间没有语义距离。Embedding 层把每个 ID 映射为一个稠密向量,比如“猫粮”→\((0.2, 0.8, -0.3)\),“钓鱼竿”→\((-0.5, 0.9, 0.4)\)。这样一来,模型就能用向量之间的夹角和距离来衡量“兴趣相似度”。

用户的点击、购买、收藏记录按照时间排列,就构成行为序列 \(S(u) = [b_1, b_2, \ldots, b_n]\)。经过 Embedding 层,每条行为变成一个向量 \(\mathbf{e}_j\)。因为不同用户的行为长度不一样,传统模型通常用平均池化把整个序列压成一个固定维度的向量:

平均池化显然配不上“资深导购”的称号。于是 DIN 登场,它要解决的核心问题就一句话:如何让模型在“翻旧账”时,对不同的小票分配不同的关注度。

eˉu=1n∑j=1nej\displaystyle \bar{\mathbf{e}}_u = \frac{1}{n}\sum_{j=1}^{n}\mathbf{e}_j
平均池化就是把所有行为向量逐元素相加再除以数量。它默认每张小票的重要性一样,像把所有消费记录倒进搅拌机打成一杯“兴趣奶昔”,口味全都串了。
  1. \(S(u)\)(行为序列)用户 \(u\) 按时间排列的行为列表,相当于导购手里那摞按日期排好的购物小票。
    S(u)=[b1,b2,…,bn]\displaystyle S(u) = [b_1, b_2, \ldots, b_n]
  2. \(\mathbf{e}_j\)(嵌入向量)第 \(j\) 条行为经 Embedding 后得到的稠密向量,是小票的“标准译文”。
    ej∈Rd\displaystyle \mathbf{e}_j \in \mathbb{R}^d
  3. \(\sum_{j=1}^{n}\)(逐元素相加)把 \(n\) 条行为向量在每个维度上分别相加,像把多张胶片叠在一起,重叠处越来越糊。
    ∑j=1nej\displaystyle \sum_{j=1}^{n}\mathbf{e}_j
  4. \(\frac{1}{n}\)(平均缩放)除以序列长度,得到一条“中心化”的向量,代表用户的平均兴趣。
    1n\displaystyle \frac{1}{n}
  5. 致命问题平均让“鱼竿”和“猫粮”的向量互相稀释。推荐鱼饵时,鱼竿这条关键记录只拿到和猫粮一样的 \(1/n\) 权重——导购眼中没有重点。
    eˉu=1n∑j=1nej\displaystyle \bar{\mathbf{e}}_u = \frac{1}{n}\sum_{j=1}^{n}\mathbf{e}_j

3. DIN 注意力激活

聪明的导购在推荐鱼饵时,会重点翻“钓鱼竿、渔网”这些和鱼相关的小票,把“猫粮”轻轻带过。这种“看人下菜碟”的翻账功夫,就是 DIN 的注意力机制。

DIN(Deep Interest Network,深度兴趣网络)的直觉非常朴素:用户历史行为对当前候选商品的影响,应该由历史行为与候选商品的相关度决定。相关度高的行为权重高,相关度低的行为权重低。而且这个权重不是固定的——换一个候选商品,权重要重算。

具体做法是:对于候选商品向量 \(\mathbf{v}_A\) 和每条历史行为向量 \(\mathbf{v}_j\),用局部激活单元(Local Activation Unit)打一个相关分,再经过 Softmax 归一化成注意力权重:

其中局部激活单元 \(f\) 把两向量及它们的逐元素乘积拼接后送入两层 MLP。得到权重后,用加权池化把历史行为融合成兴趣向量:

DIN 让导购学会了“看人下菜碟”,但它还有个盲区:它把行为序列当作一堆没有先后顺序的散票。然而用户的兴趣是会流动的——今天爱钓鱼,明天可能迷上露营。谁来看懂这条“兴趣河流”?DIEN 接过了接力棒。

aj=exp⁡(f(vj,vA))∑k=1nexp⁡(f(vk,vA))\displaystyle a_j = \frac{\exp\left(f(\mathbf{v}_j, \mathbf{v}_A)\right)}{\sum_{k=1}^{n}\exp\left(f(\mathbf{v}_k, \mathbf{v}_A)\right)}
vU=∑j=1najvj\displaystyle \mathbf{v}_U = \sum_{j=1}^{n} a_j \mathbf{v}_j
注意力权重 \(a_j\) 是“候选商品 × 历史行为”的函数:推鱼饵时,鱼竿的权重飙高;推猫粮时,猫粮记录的权重上位。同一个用户,在不同候选商品前呈现出不同的兴趣画像。
  1. \(f(\mathbf{v}_j, \mathbf{v}_A)\)(局部激活打分)把历史行为向量与候选商品向量拼接,并加入逐元素乘积 \(\mathbf{v}_j \odot \mathbf{v}_A\),让两者做细粒度交互,最后由 MLP 输出一个标量分数。
    f(vj,vA)=MLP([vj; vA; vj⊙vA])\displaystyle f(\mathbf{v}_j, \mathbf{v}_A) = \text{MLP}\left([\mathbf{v}_j;\, \mathbf{v}_A;\, \mathbf{v}_j \odot \mathbf{v}_A]\right)
  2. \(\exp\)(指数化)把分数变成正数,并放大分数之间的差异,就像给高相关的小票贴上醒目标签。
    exp⁡(f(vj,vA))\displaystyle \exp(f(\mathbf{v}_j, \mathbf{v}_A))
  3. 分母(归一化)把全体行为的指数分加总,让所有权重之和为 1——相当于把 100% 的注意力在 \(n\) 张小票之间分配。
    ∑k=1nexp⁡(f(vk,vA))\displaystyle \sum_{k=1}^{n}\exp\left(f(\mathbf{v}_k, \mathbf{v}_A)\right)
  4. \(a_j\)(注意力权重)第 \(j\) 条行为拿到的注意力份额,代表“这张小票值得看几眼”。
    aj=exp⁡(fj)∑kexp⁡(fk)\displaystyle a_j = \frac{\exp(f_j)}{\sum_k \exp(f_k)}
  5. \(\mathbf{v}_U\)(加权兴趣向量)把每条行为向量按权重缩放后相加,得到“此刻的用户兴趣画像”。注意权重随候选商品而变,这正是自适应(adaptive)的含义。
    vU=∑j=1najvj\displaystyle \mathbf{v}_U = \sum_{j=1}^{n} a_j \mathbf{v}_j

4. DIEN 兴趣演化

想想追剧的你:去年爱看悬疑,今年转粉甜宠,下个月可能迷上综艺。导购光知道你昨天买了什么还不够,还得看出你兴趣的演化趋势。这就是 DIEN(Deep Interest Evolution Network,深度兴趣演化网络)要做的事。

DIEN 在 DIN 的基础上引入时间维度,用 GRU(门控循环单元)按时间顺序读行为序列,把“离散小票”串成“故事线”。GRU 像一位带着小本本的导购,每读一张新小票,就在本子上更新一次对顾客的印象。它有两个关键“闸门”——重置门和更新门,决定忘掉多少旧印象、吸收多少新信息:

GRU 的计算细节如下:

光有 GRU 还不够。为了让每一步兴趣状态都有“标准答案”,DIEN 引入辅助损失(auxiliary loss):在第 \(t\) 步,用当前兴趣状态 \(\mathbf{h}_t\) 去预测第 \(t+1\) 步的真实行为。这就是导购的“随堂测验”——每读一条小票就自测一下:“我猜的下一步对不对?”

DIEN 还在兴趣演化层用 AUGRU(注意力更新的 GRU)替代普通 GRU,让注意力权重直接嵌入更新门,避免兴趣在演化中被平均掉。训练完成之后,这位导购才算真正出师——但上岗之前,她还得经历一套完整的“培训与考核”。

ht=GRU(et,ht−1)\displaystyle \mathbf{h}_t = \text{GRU}(\mathbf{e}_t, \mathbf{h}_{t-1})
rt=σ(Wr⋅[ht−1⊕et])\displaystyle \mathbf{r}_t = \sigma\left(\mathbf{W}_r \cdot [\mathbf{h}_{t-1} \oplus \mathbf{e}_t]\right)
zt=σ(Wz⋅[ht−1⊕et])\displaystyle \mathbf{z}_t = \sigma\left(\mathbf{W}_z \cdot [\mathbf{h}_{t-1} \oplus \mathbf{e}_t]\right)
h~t=tanh⁡(Wh⋅[(rt⊙ht−1)⊕et])\displaystyle \tilde{\mathbf{h}}_t = \tanh\left(\mathbf{W}_h \cdot [(\mathbf{r}_t \odot \mathbf{h}_{t-1}) \oplus \mathbf{e}_t]\right)
ht=(1−zt)⊙ht−1+zt⊙h~t\displaystyle \mathbf{h}_t = (1 - \mathbf{z}_t) \odot \mathbf{h}_{t-1} + \mathbf{z}_t \odot \tilde{\mathbf{h}}_t
辅助损失像抽查:对真实发生的下一步行为给高分,对随机抽样的“没发生的商品”给低分。这逼着 GRU 的每一步都准确踩在兴趣演化的节拍上。
  1. \(\mathbf{e}_{t+1}\)(真实下一步)用户第 \(t+1\) 步真实交互的商品向量,是“随堂测验的标准答案”。
    et+1\displaystyle \mathbf{e}_{t+1}
  2. \(\hat{\mathbf{e}}_{t+1}\)(负样本)从全量商品中随机抽一个用户没有交互过的商品,充当“错误答案”。
    e^t+1\displaystyle \hat{\mathbf{e}}_{t+1}
  3. 第一项 \(\log\sigma(\mathbf{w}_b \mathbf{h}_t + b)\)模型用当前兴趣状态预测“真实行为”的概率,这个概率要尽量大。
    log⁡σ(wbht+b)\displaystyle \log\sigma(\mathbf{w}_b \mathbf{h}_t + b)
  4. 第二项 \(\log(1 - \sigma(\mathbf{w}_b \hat{\mathbf{e}}_{t+1} + b))\)模型预测“负样本”的概率要尽量小,防止它对任何商品都点头。
    log⁡(1−σ(wbe^t+1+b))\displaystyle \log\left(1 - \sigma(\mathbf{w}_b \hat{\mathbf{e}}_{t+1} + b)\right)
  5. 外层 \(-\frac{1}{N}\sum\)对所有时刻的测验成绩取负平均——负号让“考得好”对应“损失小”。
    −1N∑t=1N\displaystyle -\frac{1}{N}\sum_{t=1}^{N}

5. 训练与优化

就像导购要经过岗前培训才能上岗,DIN/DIEN 也要通过一套“考试题”反复操练。这套考试的标准答案来自用户的真实点击行为:点击了的商品是正样本,没点击的是负样本。

DIN/DIEN 是监督学习模型,核心训练目标是最小化交叉熵损失——它衡量模型的预测概率与真实标签之间的差距,相当于考试的“扣分标准”:

其中 \(\hat{y}_i = \sigma(\text{MLP}([\mathbf{v}_U,\, \mathbf{v}_A,\, \mathbf{v}_U \odot \mathbf{v}_A]))\)。DIEN 的最终损失是主损失与辅助损失的加权组合:

训练数据中负样本远比正样本多。工业界的做法是负采样:对每个正样本随机抽取一定数量的未交互商品作为负样本,而不是把全量商品都塞进去。这样既控制了计算量,又让模型学会了“什么样算不像”。训练完成后,这位“导购”被派往真实柜台服务亿万用户——她的实战表现如何?

Lmain=−1N∑i=1N[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\displaystyle \mathcal{L}_{main} = -\frac{1}{N}\sum_{i=1}^{N}\left[y_i \log \hat{y}_i + (1 - y_i)\log(1 - \hat{y}_i)\right]
L=Lmain+βLaux\displaystyle \mathcal{L} = \mathcal{L}_{main} + \beta \mathcal{L}_{aux}
联合损失像“期末考试 + 随堂测验”双轨评价:期末考试(主损失)保证最终推荐的准确率,随堂测验(辅助损失)保证每一步兴趣演化都踩在正轨上。\(\beta\) 是平时成绩占总评的比重。
  1. \(y_i\)(真实标签)第 \(i\) 个样本的真实结果,1 代表点击,0 代表未点击。
    yi∈{0,1}\displaystyle y_i \in \{0, 1\}
  2. \(\hat{y}_i\)(预测概率)模型输出的点击概率,由兴趣向量与候选商品向量拼接后经 MLP 和 Sigmoid 得到。
    y^i=σ(MLP([vU; vA; vU⊙vA]))\displaystyle \hat{y}_i = \sigma(\text{MLP}([\mathbf{v}_U;\, \mathbf{v}_A;\, \mathbf{v}_U \odot \mathbf{v}_A]))
  3. \(y_i \log \hat{y}_i\)(正样本项)当真实标签为 1 时,模型预测越接近 1,损失越小——“点击过的商品就该得高分”。
    yilog⁡y^i\displaystyle y_i \log \hat{y}_i
  4. \((1-y_i)\log(1-\hat{y}_i)\)(负样本项)当真实标签为 0 时,模型预测越接近 0,损失越小。
    (1−yi)log⁡(1−y^i)\displaystyle (1-y_i)\log(1-\hat{y}_i)
  5. \(\beta\)(辅助损失权重)一个超参数(常见取值 0.1~1.0),调节随堂测验占总评的分量。
    β∈[0,1]\displaystyle \beta \in [0, 1]

6. 应用与对比

培养好的导购终究要上岗。DIN/DIEN 在电商推荐、广告 CTR 预估里就是那位“上岗导购”,用点击率(CTR,用户点击广告或商品的占比)和转化率作为“客户满意度”指标。

与传统模型相比,DIN 的突破在于用户表征随候选商品自适应变化。DeepFM 这类模型把用户兴趣压缩成一碗静态的“平均糊”,无论推荐什么都用一个固定的用户向量;DIN 则让用户向量在每次推荐时都重新计算——推鱼饵时你是“钓鱼人”,推猫粮时你是“铲屎官”。DIEN 更进一步,用 GRU + 辅助损失把兴趣的演化轨迹建模出来,让推荐不只是“猜你现在想要什么”,而是“预判你下一步想要什么”。在阿里妈妈展示广告场景中,DIN 相比当时的基线模型带来约 20% 的 CTR 相对提升。

工程上也有代价:DIN 的注意力打分要对每条历史行为单独计算,序列越长开销越大。实际部署时通常采取三类手段:对行为序列做截断(只保留最近 50~100 条)、对行为做采样(随机或按时间加权抽样)、以及用向量检索先粗筛候选商品缩小打分范围。另外,并非所有场景都需要 DIEN——如果用户行为本身缺乏时间规律(比如偶尔才逛一次的低频用户),DIN 的静态注意力已经够用,强行上 DIEN 反而增加训练成本。

这里不是“更复杂就一定更好”,而是像挑选导购一样:DIN 是懂得“看人下菜碟”的普通导购,DIEN 是能“预测顾客心思”的金牌导购。大型电商平台流量大、行为密,DIEN 的演化建模能带来稳定增益;中小型业务行为稀疏,DIN 的性价比更高。选择哪一位,取决于你的商场里有多少顾客、顾客留下了多长的“购物小票”。

AI 应用场景

场景一:电商 App“猜你喜欢”首页推荐

阶段:召回 + 精排

解决的问题:传统模型把用户所有历史行为平均成一个固定向量,导致“爱钓鱼的程序员”被推荐成“普通上班族”,点击率平平。DIN 让用户向量随候选商品自适应变化——当候选商品是鱼饵时,钓鱼相关历史权重飙升,推荐精准度大幅提高。

具体案例:用户在淘宝连续浏览了 iPhone、耳机壳、手机膜,DIN 实时给“数码配件”相关历史行为分配高注意力权重,首页下一刷立刻出现更多配件推荐,而不是突然跳到婴儿车。阿里妈妈公开论文表明,DIN 在展示广告场景使 CTR 相对提升约 20%。

场景二:信息流广告点击率(CTR)预估

阶段:广告排序(精排)

解决的问题:广告系统在多个候选广告中排序,谁预估点击率高谁获得展示。DIN 用候选广告与用户历史行为的注意力权重,让每个候选广告得到“量身定制”的用户兴趣向量,排序更合理。

具体案例:某信息流平台输入用户最近 100 条点击行为,用 DIN 对三十个候选广告分别计算注意力权重,把用户最可能感兴趣的广告排到首位,广告收入和用户体验双提升。

场景三:视频平台连续追剧推荐

阶段:序列推荐

解决的问题:用户在平台上的兴趣随时间演化——今年爱悬疑、明年爱甜宠。DIN 只关注“与当前候选相关的历史”,DIEN 则用 GRU 建模兴趣演化路径,配合辅助损失逐点校准,能预判用户下一时段想看什么。

具体案例:某长视频平台用 DIEN 建模用户连续的观看记录:从悬疑剧 → 犯罪剧 → 甜宠剧的演化路径被 GRU 捕捉,平台在用户看完一部甜宠剧后,优先推荐同类型新剧而非回到悬疑片库。

Python 演示

python46 行
import numpy as np  def softmax(scores):    """把任意实数数组转成和为 1 的概率分布(注意力权重)"""    exp_scores = np.exp(scores - np.max(scores))    return exp_scores / exp_scores.sum()  class SimpleDIN:    """简化版深度兴趣网络: 用两层 MLP 实现局部激活单元"""     def __init__(self, embed_dim, hidden_dim):        self.embed_dim = embed_dim        self.w1 = np.random.randn(embed_dim * 2, hidden_dim) * 0.1        self.b1 = np.zeros(hidden_dim)        self.w2 = np.random.randn(hidden_dim, 1) * 0.1        self.b2 = np.zeros(1)     def local_activation(self, behavior_vec, target_vec):        """候选商品与单个历史行为的打分函数"""        concat = np.concatenate([behavior_vec, target_vec])        hidden = np.tanh(concat @ self.w1 + self.b1)        return hidden @ self.w2 + self.b2     def predict(self, behavior_seq, target_vec):        """输入行为序列与候选商品, 返回加权兴趣向量和注意力权重"""        scores = np.array([            self.local_activation(b, target_vec)[0] for b in behavior_seq        ])        weights = softmax(scores)        interest_vec = np.sum(            weights.reshape(-1, 1) * np.array(behavior_seq), axis=0        )        return interest_vec, weights  if __name__ == "__main__":    np.random.seed(42)    model = SimpleDIN(embed_dim=8, hidden_dim=16)    # 5 条历史行为: 鱼竿, 猫粮, 渔网, 运动鞋, 鱼饵盒    behaviors = [np.random.randn(8) for _ in range(5)]    target = np.random.randn(8)  # 候选商品    interest, attn = model.predict(behaviors, target)    print("兴趣向量:", np.round(interest, 3))    print("注意力权重:", np.round(attn, 3))
目的:用约 60 行代码实现 DIN 的核心——局部激活单元打分 + Softmax 归一化 + 加权池化,直观展示“不同历史行为被分配不同注意力”的过程。
  1. exp_scores = np.exp(scores - np.max(scores))减去最大值再取指数,防止数值上溢,这是 Softmax 的标准稳妥写法。
  2. concat = np.concatenate([behavior_vec, target_vec])把历史行为与候选商品向量拼在一起,作为局部激活单元的输入。
  3. hidden = np.tanh(concat @ self.w1 + self.b1)一层带 tanh 激活的线性变换,让模型学习历史行为与候选商品之间的非线性交互。
  4. weights = softmax(scores)把 5 个行为的打分归一化成和为 1 的注意力权重,对应 DIN 公式里的 Softmax 步骤。
  5. interest_vec = np.sum(weights.reshape(-1, 1) * np.array(behavior_seq), axis=0)加权求和,把历史行为按注意力权重融合成“此刻的用户兴趣向量”。

常见误区

误区DIN 不就是把行为向量加权求和吗?权重也是归一化的,跟平均池化差别不大,叫“注意力”纯属换个名字。

正解区别在于权重从哪来。平均池化的权重恒为 \(1/n\),与候选商品毫无关系;DIN 的权重是候选商品向量的函数 \(a_j = \text{Softmax}(f(\mathbf{v}_j, \mathbf{v}_A))\)。推荐鱼饵和推荐猫粮时,同一个用户的行为权重分布完全不同——这才是“注意力”的本质。就像导购推鱼饵时重点看鱼竿,推猫粮时重点看猫砂。

为何常见:两个公式外观看都是“求和”,初学者只看到形式相似,没意识到权重是“条件化于候选商品”的,这正是 DIN 的核心创新。

误区DIN 不建模时间顺序,DIEN 加一个 GRU 把序列编码一遍不就行了?听起来很简单。

正解DIEN 的结构远不止一个 GRU。它包含兴趣提取层(GRU 编码)和兴趣演化层两个阶段,后者不是简单地把 GRU 状态送入注意力,而是用 AUGRU 把注意力权重乘进 GRU 的更新门,让兴趣演化过程中每一步都受候选商品影响。此外还有辅助损失对每一步中间状态单独监督。论文里的图看起来简单,细节全是功夫。

为何常见:论文架构图上 GRU 和 Attention 模块相邻,容易让人误以为只是串联拼接,忽略了“注意力改写更新门”这个精妙设计。

误区既然历史行为是金矿,那把用户从注册到现在所有行为都喂进模型,信息量最大,效果肯定最好。

正解序列太长带来两个问题:一是计算开销线性增长,DIN 的注意力要对每条行为单独打分,服务端扛不住;二是“兴趣漂移”——三年前买过 PS2 的用户现在可能完全不玩游戏,早期行为对当下推荐只是噪声。工业界通常截断最近 50~100 条行为,或按时间衰减加权。GRU 本身也有长期依赖衰减问题,所以不是越长越好。

为何常见:“信息越多越好”的直觉在稀疏场景成立,但没考虑计算成本与兴趣的时间衰减,被“数据是金矿”的说法带偏了。

误区注意力机制不就是 \(\text{Softmax}(\mathbf{Q}\mathbf{K}^\top / \sqrt{d})\) 吗?DIN 应该也是一样的套路。

正解DIN 用的是局部激活单元,不是缩放点积注意力。它把 \([\mathbf{v}_j; \mathbf{v}_A; \mathbf{v}_j \odot \mathbf{v}_A]\) 拼接后过两层 MLP 打分,其中逐元素乘积让两个向量在细粒度维度上交互,表达能力比内积更强。后续工作还证明这种“拼接 + MLP”的打分方式在稀疏特征场景下往往优于点积注意力。

为何常见:Transformer 太出名,导致很多人默认所有注意力都是点积形式。实际上“注意力”是一种思想,具体打分函数可以灵活设计。

面试题

Q1. DIN 模型的核心创新是以下哪一项?

单选题 · easy

  • A.引入注意力机制自适应加权← 正确答案
  • B.使用卷积网络提取图像特征
  • C.利用循环网络拼接行为序列
  • D.采用图神经网络聚合社交关系

答案:A。DIN 的核心是用注意力机制让用户历史行为对候选商品自适应加权。B 是图像领域方法,C 更接近 DIEN 的做法,D 是社交推荐思路,均不是 DIN 的标志性创新。

Q2. DIN 的注意力权重主要衡量谁和谁的相关度?

单选题 · easy

  • A.候选商品与用户历史行为← 正确答案
  • B.用户画像与商家利润比例
  • C.商品库存与推荐频次关系
  • D.行为序列长度与用户活跃度

答案:A。DIN 的局部激活单元输入是“历史行为向量 + 候选商品向量”以及它们的逐元素乘积,输出打分代表两者相关度。其余选项涉及库存、利润、活跃度等,DIN 并不直接建模这些关系。

Q3. DIEN 模型中负责“兴趣提取”的模块是?

单选题 · mid

  • A.双向长短期记忆网络
  • B.门控循环单元 GRU← 正确答案
  • C.多层感知机分类器
  • D.变分自编码器解码器

答案:B。DIEN 用 GRU 按时间顺序编码行为序列,提取每一步的兴趣状态。论文中的兴趣提取层(Interest Extractor Layer)正是由 GRU 构成的。LSTM 虽然也能编码序列,但 DIEN 原文使用的是 GRU。

Q4. DIEN 引入辅助损失的主要目的是?

单选题 · mid

  • A.对每一步兴趣状态施加监督约束← 正确答案
  • B.降低模型推理时的计算延迟
  • C.压缩用户行为序列长度
  • D.绘制用户兴趣分布图像

答案:A。辅助损失用第 t 步的隐藏状态预测第 t+1 步真实行为,相当于给每一步兴趣状态一个“随堂测验”,防止 GRU 中间状态无监督而失准。它不直接作用于推理延迟、序列压缩或画图。

Q5. 相比 DeepFM,DIN 在用户建模上的关键区别是?

单选题 · mid

  • A.用户向量随候选商品自适应变化← 正确答案
  • B.用 FM 做更充分的高阶交叉
  • C.完全不使用用户行为序列数据
  • D.引入图像增强提升特征丰富度

答案:A。DeepFM 用固定的用户向量,DIN 让用户兴趣向量由注意力权重动态生成,随候选商品改变。B 是 DeepFM 本身的特色,C 与事实相反,D 与用户行为建模无关。

Q6. DIN 用加权池化替代平均池化的根本原因是?

单选题 · hard

  • A.平均池化无法区分行为与候选的相关程度← 正确答案
  • B.平均池化参数量大导致训练难以收敛
  • C.平均池化在 GPU 上无法并行计算
  • D.平均池化要求序列等长才能计算

答案:A。平均池化对每条历史行为一视同仁,忽略了它们与候选商品相关度的差异。DIN 用注意力权重做加权和,让相关行为主导用户兴趣向量。B、C 说法不符合事实,D 的“序列等长”可由 padding 解决。

Q7. AUGRU 与普通 GRU 的最大差异在于?

单选题 · extreme

  • A.更新门被注意力权重相乘修正← 正确答案
  • B.重置门被替换为卷积核卷积
  • C.隐藏状态维度比输入维度更大
  • D.激活函数从 tanh 换成 ReLU

答案:A。AUGRU(Attention-based GRU)把注意力权重直接乘进更新门,使兴趣演化的每一步都受候选商品引导,避免注意力被时间池化平均掉。B、C、D 都不是 AUGRU 的结构改动。

Q8. DIN 模型结构包含下列哪些模块?

多选题 · mid

  • A.物品嵌入映射层← 正确答案
  • B.局部激活单元层← 正确答案
  • C.加权池化聚合层← 正确答案
  • D.图像旋转数据增强

答案:ABC。DIN 由嵌入层、局部激活单元(打分)、加权池化(聚合兴趣)构成。图像旋转增强属于 CV 领域的数据增广,与 DIN 的推荐建模无关。

Q9. DIEN 相比 DIN 的改进包括哪些?

多选题 · hard

  • A.用 GRU 按时间序列编码行为← 正确答案
  • B.引入辅助损失约束中间状态← 正确答案
  • C.用 AUGRU 强化演化注意力← 正确答案
  • D.删除所有用户历史行为特征

答案:ABC。DIEN 的三大改进正是 GRU 时间编码、辅助损失逐点监督、AUGRU 让注意力融入演化过程。D 明显错误——DIEN 恰恰更充分利用了行为序列。

Q10. 行为序列中可能包含哪些有价值的用户兴趣信号?

多选题 · easy

  • A.点击商品的类目标签排列顺序← 正确答案
  • B.同一商品被重复浏览的次数← 正确答案
  • C.用户停留时长的长短快慢← 正确答案
  • D.服务器日志文件的行号编号

答案:ABC。行为序列中的类目顺序反映兴趣演化,重复浏览次数反映偏好强度,停留时长反映关注程度,这些都能帮助建模用户兴趣。日志行号只是工程元信息,不代表用户兴趣。