想象你是娱乐圈的数据分析师。公司新推出一支少年偶像团体,老板要你预测:眼前这位追星女孩,会不会为新团掏钱投票?你翻开她的收藏夹——最近点赞过韩流男团、转发过国风歌手的演出视频、还买过电竞选手的联名外套。问题是:她到底是喜欢“青春感”还是“国风韵味”?仅仅把收藏夹里的商品揉成一个“平均画像”,就像给一个活生生的人拍一张静态照片——太容易失真了。 DIN(深度兴趣网络)的做法,正是对用户历史行为做加权求和,得到一张“静态快照”。而 DIEN(Deep Interest Evolution Network,深度兴趣演化网络)更进一步:它像读一本追星日记一样,按时间线逐页翻看用户的“心动记录”,看她从韩团迷妹到国风爱好者再到电竞粉丝的变迁轨迹,再用这条演化曲线去推测她对新偶像团体的态度。毕竟,兴趣不是静止的标签,而是一条会流动的河。DIEN 用 GRU 抽取兴趣、用 AUGRU 演化兴趣,成功把“读日记”的能力装进了推荐系统。

岗位关联

DIEN 是推荐系统排序阶段的经典进阶模型。理解它,你就能在面试中讲清“兴趣是动态的”这一核心命题,也能在真实业务中把用户行为序列从“特征”升级为“剧情”。

目录
  1. 可视化演示
  2. DIN的局限:一张静态快照错过了什么
  3. DIEN架构总览:从快照升级到电影
  4. GRU兴趣抽取层:逐页翻阅追星日记
  5. AUGRU兴趣演化层:带着目标重读日记
  6. 辅助损失机制:用下一个行为当考官
  7. 效果评估:DIEN 与 DIN 的同台竞技
  8. 落地应用:把“读心术”装进生产系统
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

模拟GRU门控机制、兴趣抽取层序列处理与AUGRU注意力调制演化过程,展示DIEN建模用户兴趣时序演化的核心原理。

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

模式1:GRU门控机制 更新门控制历史信息保留比例 重置门控制候选状态的计算 h_t = (1-z_t)⊙h_{t-1} + z_t⊙h̃_t GRU用双门控替代LSTM记忆单元。

DIN的局限:一张静态快照错过了什么

同样是那位追星女孩,她可以“先喜欢韩团、再迷国风、最后爱上电竞选手”,也可以“三个同时喜欢”。这两种情况下的行为记录顺序完全不同,心理动因也截然不同。但 DIN 的做法是:把收藏夹里的所有商品嵌入向量做加权求和,得到一张兴趣快照。它只关心“你收藏了什么”,完全不关心“你先收藏了什么、后收藏了什么”。这就像给一部电影只看最后一帧海报,却想推断整部剧的剧情走向。

在推荐场景中,行为序列的顺序本身携带着大量信息。用户先浏览手机保护壳再购买手机,与先买手机再看保护壳,反映出的购买阶段完全不同。DIN 的目标注意力池化虽然能给每个历史行为分配权重,但权重计算是“各看各的”,没有利用行为之间的前后关系。结果就是:时序信息被彻底折叠,兴趣的演变过程在模型中毫无痕迹。

DIN 的兴趣表达可以用下面的聚合公式理解:

换个大白话收尾:DIN 把追星日记打碎、拌匀、榨成一杯果汁,果肉纤维的先后层次全没了。而 DIEN 想保留的,正是那一片片果肉在时间里的排列顺序——因为兴趣的“剧情”,恰恰藏在顺序里。

eu=∑i=1Nsoftmax(score(vi,vt))⋅vi\displaystyle e_u = \sum_{i=1}^{N} \text{softmax}\big(\text{score}(v_i, v_t)\big) \cdot v_i
这个公式把所有历史行为嵌入 $v_i$ 按与目标商品 $v_t$ 的相似度加权求和,但求和本身对顺序不敏感,相当于把一本日记撕碎后混在一起。
  1. 行为嵌入 $v_i$把用户第 $i$ 个历史交互商品转换成一个稠密向量,相当于日记中第 $i$ 条“心动记录”的文字摘要
    vi∈Rd\displaystyle v_i \in \mathbb{R}^d
  2. 目标商品嵌入 $v_t$候选商品的向量表示,相当于“新偶像”的档案照片
    vt∈Rd\displaystyle v_t \in \mathbb{R}^d
  3. 注意力权重用 softmax 把每个历史行为与目标的相关度归一化成 0 到 1 的权重,相当于按“与新偶像相似程度”给日记打分
    softmax(score(vi,vt))=exp⁡(score(vi,vt))∑j=1Nexp⁡(score(vj,vt))\displaystyle \text{softmax}\big(\text{score}(v_i, v_t)\big) = \frac{\exp(\text{score}(v_i, v_t))}{\sum_{j=1}^{N}\exp(\text{score}(v_j, v_t))}
  4. 加权求和所有权重乘以对应嵌入后相加,得到一个综合向量
    eu=∑i=1Nwi⋅vi\displaystyle e_u = \sum_{i=1}^{N} w_i \cdot v_i

DIEN架构总览:从快照升级到电影

如果把用户的行为序列看作一本追星日记,DIN 是“翻到最后一页抄总结”,DIEN 则是“从第一页开始拍成一部电影”。这部电影分两幕:第一幕叫“兴趣抽取”,用 GRU 网络逐页阅读日记,把每一页的心动状态提炼成一个隐藏向量;第二幕叫“兴趣演化”,用 AUGRU 网络带着“新偶像”的照片重新回放日记,把与目标相关的线索放大,最终凝聚成此刻的兴趣。

整体结构上,DIEN 首先把用户行为序列中的每个商品映射为嵌入向量 $e_t$,然后送入兴趣抽取层。抽取层使用 GRU(门控循环单元)按时间顺序读取每个行为,输出一组兴趣状态 $h_1, h_2, ..., h_T$。接着,兴趣演化层以这些状态为输入,结合目标商品嵌入 $v_t$ 计算注意力分数 $a_t$,再通过 AUGRU 逐步更新演化的兴趣状态,最后将最终状态与其他特征拼接,送入多层感知机做点击率预估。

整个前向过程可以用两个核心递推式概括:

打个比方收尾:GRU 像一个不带偏见的书记员,逐页记录女孩的心动历程;AUGRU 则像带着“新偶像照片”的侦探,重看日记时只把与照片相关的情节大写加粗,最终形成一份有明确指向的“兴趣画像”。

ht=GRU(et,ht−1),ht′=AUGRU(ht,ht−1′,at)\displaystyle h_t = \text{GRU}\big(e_t, h_{t-1}\big), \quad h'_t = \text{AUGRU}\big(h_t, h'_{t-1}, a_t\big)
第一行用 GRU 从行为中抽取出兴趣状态序列;第二行用 AUGRU 在目标商品引导下,把这些状态演化成最终的兴趣向量。两层串联,构成了“抽取 + 演化”的双阶段流水线。
  1. GRU 抽取把第 $t$ 个行为的嵌入 $e_t$ 和上一个隐藏状态 $h_{t-1}$ 输入 GRU,得到当前时刻的兴趣状态 $h_t$
    ht=GRU(et,ht−1)\displaystyle h_t = \text{GRU}\big(e_t, h_{t-1}\big)
  2. 注意力分数计算每个兴趣状态 $h_t$ 与目标商品 $v_t$ 的相关度 $a_t$,作为演化的“聚光灯”
    at=exp⁡(score(ht,vt))∑j=1Texp⁡(score(hj,vt))\displaystyle a_t = \frac{\exp(\text{score}(h_t, v_t))}{\sum_{j=1}^{T}\exp(\text{score}(h_j, v_t))}
  3. AUGRU 演化用 AUGRU 将抽取状态 $h_t$、上一演化状态 $h'_{t-1}$ 与注意力分数 $a_t$ 结合,得到演化后的兴趣状态 $h'_t$
    ht′=AUGRU(ht,ht−1′,at)\displaystyle h'_t = \text{AUGRU}\big(h_t, h'_{t-1}, a_t\big)

GRU兴趣抽取层:逐页翻阅追星日记

现在让我们深入第一幕。GRU 读取日记时,不是把每页看完就扔掉,而是每翻一页就更新一次自己脑中的“印象”。这个印象就是隐藏状态 $h_t$,它浓缩了从第一页到第 $t$ 页的全部心动信息。与 LSTM 相比,GRU 结构更简洁——只有两个门,参数量更少,训练更快,适合处理推荐系统中动辄几十上百的行为序列。

GRU 的核心是“门控”思想:更新门决定新信息对旧印象的冲击程度,重置门决定旧印象被遗忘的幅度。举个生活中的例子:你读日记时,如果发现女孩从“喜欢清淡”转向“喜欢麻辣”,你会大幅更新对她的印象(更新门打开);但如果只是偶尔一条小偏爱,你只会微调印象(更新门半开)。重置门则负责决定“过去的印象有多少值得被保留下来参与新印象的构建”。

GRU 的更新过程可以写成三个式子:

到这里你已明白:GRU 把一本日记变成了一条平滑的“心路历程曲线”,每个时刻的隐藏状态都是对“这阶段她喜欢什么”的浓缩回答。但这只是抽取,还没回答最终问题——她会不会喜欢“新偶像”呢?

zt=σ(Wz⋅[ht−1,xt])\displaystyle z_t = \sigma\big(W_z \cdot [h_{t-1}, x_t]\big)
rt=σ(Wr⋅[ht−1,xt])\displaystyle r_t = \sigma\big(W_r \cdot [h_{t-1}, x_t]\big)
h~t=tanh⁡(W⋅[rt⊙ht−1,xt]),ht=(1−zt)⊙ht−1+zt⊙h~t\displaystyle \tilde{h}_t = \tanh\big(W \cdot [r_t \odot h_{t-1}, x_t]\big), \quad h_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t
前两个式子分别计算更新门 $z_t$ 和重置门 $r_t$,第三个式子在重置门的控制下生成候选状态 $\tilde{h}_t$,最后用更新门在旧状态和候选状态之间做插值。
  1. 更新门计算把上一时刻隐藏状态与当前输入拼接,经过 sigmoid 压缩到 0 到 1 之间,数值越大表示新信息越该被吸收
    zt=σ(Wz⋅[ht−1,xt])\displaystyle z_t = \sigma\big(W_z \cdot [h_{t-1}, x_t]\big)
  2. 重置门计算结构上与更新门相似,决定从前一状态中“回忆”多少信息用于生成新候选
    rt=σ(Wr⋅[ht−1,xt])\displaystyle r_t = \sigma\big(W_r \cdot [h_{t-1}, x_t]\big)
  3. 候选状态生成用重置门逐元素过滤旧状态后,与当前输入一起过 tanh 激活,得到候选新状态
    h~t=tanh⁡(W⋅[rt⊙ht−1,xt])\displaystyle \tilde{h}_t = \tanh\big(W \cdot [r_t \odot h_{t-1}, x_t]\big)
  4. 状态更新按更新门的比例,在旧状态与候选状态之间做加权平均,完成“印象更新”
    ht=(1−zt)⊙ht−1+zt⊙h~t\displaystyle h_t = (1 - z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t

AUGRU兴趣演化层:带着目标重读日记

读完日记只是第一步。要预测女孩对新偶像的态度,还必须带着“新偶像”这个目标去重新审视整段心路历程。AUGRU(Attention-based GRU)干的就是这件事:它把目标商品嵌入当作一面“照妖镜”,给每个兴趣状态打一个相关度分数 $a_t$,然后让这个分数去调制 GRU 的更新门。相关度高的行为会在演化过程中被放大,相关度低的则被弱化。

这就像你带着一张“新偶像”的照片去重翻日记:翻到“她曾花三个月攒钱买韩团专辑”那页,你会重点标记;翻到“她顺手点赞了一条美食视频”那页,你只会轻轻带过。AUGRU 的巧妙之处在于,它不是简单地对各状态加权求和,而是把注意力分数乘进了循环网络的门控中,让“演化”本身也带上目标的指向性。

AUGRU 的更新过程可以描述为:

所以,AUGRU 回答的是“她的兴趣是如何一路演化到今天、并指向这个目标商品的”。它保留了 GRU 对时序的建模能力,又注入了目标导向,让兴趣演化不再漫无目的。故事讲到这里,主角已登场:GRU 负责“读”,AUGRU 负责“带着问题读”。

z~t=at⋅zt,ht′=(1−z~t)⊙ht−1′+z~t⊙h~t′\displaystyle \tilde{z}_t = a_t \cdot z_t, \quad h'_t = \big(1 - \tilde{z}_t\big) \odot h'_{t-1} + \tilde{z}_t \odot \tilde{h}'_t
注意力分数 $a_t$ 与 GRU 更新门 $z_t$ 相乘,得到“注意力调制后的更新门” $\tilde{z}_t$。这样,与目标越相关的兴趣状态,越能推动演化状态大幅前进。
  1. 注意力分数计算用目标商品嵌入与兴趣状态 $h_t$ 做内积(或通过多层感知机打分),再对所有时刻做 softmax 归一化
    at=exp⁡(score(ht,vt))∑j=1Texp⁡(score(hj,vt))\displaystyle a_t = \frac{\exp\big(\text{score}(h_t, v_t)\big)}{\sum_{j=1}^{T}\exp\big(\text{score}(h_j, v_t)\big)}
  2. 门控调制将标量 $a_t$ 乘到更新门 $z_t$ 上,得到新的门控值 $\tilde{z}_t$,相当于给“信息吸收量”安了一个注意力阀门
    z~t=at⋅zt\displaystyle \tilde{z}_t = a_t \cdot z_t
  3. 演化状态更新沿用 GRU 的插值结构,但使用调制后的门控,使演化状态平滑地向目标相关的兴趣方向移动
    ht′=(1−z~t)⊙ht−1′+z~t⊙h~t′\displaystyle h'_t = \big(1 - \tilde{z}_t\big) \odot h'_{t-1} + \tilde{z}_t \odot \tilde{h}'_t

辅助损失机制:用下一个行为当考官

如果一部电影只有演员自我发挥,没有导演喊“卡”,拍摄质量很难保证。DIEN 同样面临这个问题:GRU 抽取出的中间状态,虽然理论上应该反映当时的兴趣,但如果没有额外的监督信号,谁也无法保证 $h_t$ 真的编码了“她当时的喜好”。于是 DIEN 引入了辅助损失——让每个中间状态都去预测下一个真实行为,相当于给每段日记末尾安排一个“突击考试”:读到这里,猜猜她下一个会迷上什么?

辅助损失的具体做法是:在每一步 $t$,用当前兴趣状态 $h_t$ 去预测第 $t+1$ 个行为商品。预测目标是一个二分类问题:正样本是用户真实交互的下一个商品嵌入,负样本则从用户未交互的商品中随机采样。这个预测任务迫使每个中间状态都承载足够多的“预测能力”,从而让兴趣抽取更加充分、平滑。

辅助损失可以写成:

最终的总损失是目标损失与辅助损失的加权和:$L = L_{target} + \alpha L_{aux}$,其中 $\alpha$ 是超参数。辅助损失让“读日记”这件事本身变得可靠,而不是只看最终结果对不对。

Laux=−1T∑t=1T[log⁡σ(ht⋅et+1)+log⁡(1−σ(ht⋅eneg))]\displaystyle L_{aux} = -\frac{1}{T}\sum_{t=1}^{T}\Big[\log \sigma\big(h_t \cdot e_{t+1}\big) + \log\big(1 - \sigma\big(h_t \cdot e_{neg}\big)\big)\Big]
对每个时刻 $t$,都让状态 $h_t$ 与真实下一行为嵌入 $e_{t+1}$ 的相似度尽可能高(第一项),与负样本嵌入 $e_{neg}$ 的相似度尽可能低(第二项),所有时刻取平均。
  1. 正样本对数似然用 $h_t$ 与真实下一行为 $e_{t+1}$ 的内积过 sigmoid,希望输出接近 1,即状态确实“预测中了”下一个行为
    log⁡σ(ht⋅et+1)\displaystyle \log \sigma\big(h_t \cdot e_{t+1}\big)
  2. 负样本对数似然采样一个用户未交互的负样本 $e_{neg}$,希望内积过 sigmoid 后接近 0,防止模型把什么都预测成“下一个行为”
    log⁡(1−σ(ht⋅eneg))\displaystyle \log\big(1 - \sigma\big(h_t \cdot e_{neg}\big)\big)
  3. 时间平均对所有时刻的损失取平均,保证每一页日记都经得起“剧透测验”
    1T∑t=1T\displaystyle \frac{1}{T}\sum_{t=1}^{T}

效果评估:DIEN 与 DIN 的同台竞技

想象你同时让两位分析师预测追星女孩的打榜行为:一位只翻收藏夹总结(DIN),另一位从头到尾读日记并关注心路历程(DIEN)。谁的命中率更高?答案几乎显而易见。在淘宝、阿里妈妈等真实业务场景的离线评估中,DIEN 相比 DIN 在 AUC(Area Under Curve,ROC 曲线下面积)上有稳定提升,尤其在高频交互场景中表现突出。

为什么高频场景增益更大?因为行为序列越长、越丰富,“剧情”就越完整,时序建模的优势就越能发挥。而在低频场景(如买房、买车),用户历史行为稀疏,GRU 读到的“日记”只有寥寥几页,演化轨迹很难成形,此时 DIN 的简单加权反而更稳健。这也提醒我们:模型没有绝对优劣,只有适配场景之分。

AUC 是推荐排序最常用的离线指标之一,其统计意义是:随机抽一对正负样本,模型给正样本打更高分的概率。DIEN 相比 DIN 的增益可以简单表示为:

从业务视角看,DIEN 在服饰、美妆、3C 数码等购买频次高的类目上增益明显,而在低频耐用品上可能只带来微小提升甚至持平。因此,工业界常把 DIEN 与 DIN 同时作为候选模型,离线对比 AUC、在线对比点击率与转化率,再决定是否全量上线。

ΔAUC=AUCDIEN−AUCDIN\displaystyle \Delta AUC = AUC_{DIEN} - AUC_{DIN}
DIEN 的 AUC 减去 DIN 的 AUC,得到正数说明 DIEN 在排序质量上有提升。
  1. 模型打分对于同一条用户行为序列,分别用 DIN 和 DIEN 计算对目标商品的点击概率
    y^DIN=fDIN(x),y^DIEN=fDIEN(x)\displaystyle \hat{y}_{DIN} = f_{DIN}(x), \quad \hat{y}_{DIEN} = f_{DIEN}(x)
  2. AUC 计算AUC 衡量模型把正样本排在负样本之前的概率,值越接近 1 越好
    AUC=P(y^pos>y^neg)\displaystyle AUC = P\big(\hat{y}_{pos} > \hat{y}_{neg}\big)
  3. 差值比较两者相减得到增量,用于判断时序建模带来的排序质量提升幅度
    ΔAUC=AUCDIEN−AUCDIN\displaystyle \Delta AUC = AUC_{DIEN} - AUC_{DIN}

落地应用:把“读心术”装进生产系统

理论再漂亮,也要经得起生产线上的考验。DIEN 在工业落地时,通常被嵌入推荐排序模型的主链路:用户行为日志经过清洗和特征工程后,构造成定长行为序列;序列中的每个商品查表得到嵌入向量;随后依次经过 GRU 兴趣抽取层和 AUGRU 兴趣演化层;最终演化出的兴趣向量与用户静态特征、商品特征拼接,送入多层感知机输出点击率。

工程上有几个常见的经验:一是行为序列往往很长,直接全量训练成本太高,通常按时间截断到最近 50~100 个行为;二是辅助损失的负采样比例需要调参,一般控制在 1:1 到 1:5 之间;三是 GRU 隐藏单元数不宜过大,常见配置是 32 到 128 维,过大反而容易在小数据集上过拟合。训练时总损失为:

从论文走向生产线,DIEN 已被广泛应用于电商推荐、广告 CTR 预估、短视频推荐等场景。它告诉我们一个朴素的道理:给模型一本“日记”而不是一张“名片”,它才能真正理解用户的心。

L=Ltarget+α⋅Laux\displaystyle L = L_{target} + \alpha \cdot L_{aux}
目标损失负责“最终点击准不准”,辅助损失负责“每一步兴趣状态准不准”,两者通过权重 $\alpha$ 平衡,通常取 0.5 到 1.0。
  1. 目标损失模型对最终点击率预测的交叉熵损失,是排序模型的“主考官”
    Ltarget=−1M∑i=1M[yilog⁡y^i+(1−yi)log⁡(1−y^i)]\displaystyle L_{target} = -\frac{1}{M}\sum_{i=1}^{M}\big[y_i \log \hat{y}_i + (1 - y_i) \log (1 - \hat{y}_i)\big]
  2. 辅助损失前面定义的逐时刻行为预测损失,是“平时测验”
    Laux=−1T∑t=1T[log⁡σ(ht⋅et+1)+log⁡(1−σ(ht⋅eneg))]\displaystyle L_{aux} = -\frac{1}{T}\sum_{t=1}^{T}\Big[\log \sigma\big(h_t \cdot e_{t+1}\big) + \log\big(1 - \sigma\big(h_t \cdot e_{neg}\big)\big)\Big]
  3. 加权求和用超参数 $\alpha$ 控制两者比例,既不过度偏科也不放任平时成绩
    L=Ltarget+α⋅Laux\displaystyle L = L_{target} + \alpha \cdot L_{aux}

AI 应用场景

电商商品推荐排序

阶段:推荐系统排序阶段(CTR 预估模型)

解决的问题:电商平台中,用户点击、收藏、购买行为天然带有时序性。传统 DIN 把所有行为揉成静态向量,无法区分“曾经喜欢但已过气”和“最近正在上头”的兴趣状态。DIEN 通过 GRU 抽取 + AUGRU 演化,把“兴趣正在往哪个方向走”这件事显式建模。

具体案例:某服饰电商 App 的推荐流中,一位用户近两周先后浏览了卫衣、运动鞋、篮球短裤,最终在目标商品“球星联名款卫衣”上转化。DIEN 能从序列中捕捉到“运动风格兴趣正在强化”的趋势,AUGRU 让与联名款相关的行为主导演化,从而给出比 DIN 更高的点击概率。

信息流广告 CTR 预估

阶段:广告系统排序阶段(广告点击率预估)

解决的问题:广告场景中用户行为序列混杂了大量内容浏览和广告点击,噪声大、序列长。DIEN 的辅助损失相当于给每一步兴趣状态配了“课后练习”,让模型在噪声中依然能提炼出可预测的兴趣信号。

具体案例:某广告平台要预估用户是否会点击一款手游广告。用户最近 30 天的行为序列中,前 20 天以视频内容为主,后 10 天密集出现游戏相关视频和直播。DIEN 能识别出“兴趣迁移”的关键转折点,并将近期的游戏兴趣加权放大,最终刷新了广告 CTR 的历史最优水平。

短视频内容推荐

阶段:内容推荐召回 / 排序阶段

解决的问题:短视频场景下用户兴趣变化极快,可能一周内从萌宠视频切换到露营装备测评。DIEN 的时序建模能力恰好匹配这种“短周期强演化”的兴趣模式,帮助平台抓住兴趣拐点。

具体案例:某短视频平台发现,用户在连续看完 5 条露营视频后,对“户外装备”类广告的完播率显著提升。通过 DIEN 捕捉这一演化信号,推荐系统在用户刷到第 4 条露营视频时就开始松动广告策略,整体完播率提升约 8%。

Python 演示

python58 行
import numpy as np  def sigmoid(x):    return 1.0 / (1.0 + np.exp(-np.clip(x, -15, 15)))  class DIENCell:    """简化版DIEN核心单元:GRU兴趣抽取 + AUGRU兴趣演化"""     def __init__(self, dim):        self.dim = dim        self.Wz = np.random.randn(dim, dim) * 0.1        self.Uz = np.random.randn(dim, dim) * 0.1        self.Wr = np.random.randn(dim, dim) * 0.1        self.Ur = np.random.randn(dim, dim) * 0.1        self.Wh = np.random.randn(dim, dim) * 0.1        self.Uh = np.random.randn(dim, dim) * 0.1        self.bz = np.zeros(dim)        self.br = np.zeros(dim)        self.bh = np.zeros(dim)     def gru_step(self, x, h):        z = sigmoid(self.Wz @ x + self.Uz @ h + self.bz)        r = sigmoid(self.Wr @ x + self.Ur @ h + self.br)        h_tilde = np.tanh(self.Wh @ x + self.Uh @ (r * h) + self.bh)        return (1 - z) * h + z * h_tilde     def augru_step(self, h_state, h_prev, att):        z = sigmoid(self.Wz @ h_state + self.Uz @ h_prev + self.bz)        h_tilde = np.tanh(self.Wh @ h_state + self.Uh @ (1 - z) * h_prev + self.bh)        gate = att * z        return (1 - gate) * h_prev + gate * h_tilde     def forward(self, seq, target_vec):        h_prev = np.zeros(self.dim)        states = []        for x in seq:            h_prev = self.gru_step(x, h_prev)            states.append(h_prev)        scores = np.array([np.dot(s, target_vec) for s in states])        scores = scores - np.max(scores)        atts = np.exp(scores) / np.exp(scores).sum()        interest = np.zeros(self.dim)        for s, a in zip(states, atts):            interest = self.augru_step(s, interest, a)        return interest  np.random.seed(42)dim = 8cell = DIENCell(dim)seq = [np.random.randn(dim) for _ in range(6)]target_vec = np.random.randn(dim)vec = cell.forward(seq, target_vec)print("行为序列长度:", len(seq))print("兴趣向量维度:", vec.shape)print("兴趣向量:", np.round(vec, 3))
目的:用 NumPy 实现 DIEN 的核心前向计算,帮助理解 GRU 抽取与 AUGRU 演化的数据流。
  1. def gru_step(self, x, h):GRU 单步更新,接收当前行为嵌入与上一隐藏状态,输出新兴趣状态
  2. z = sigmoid(self.Wz @ x + self.Uz @ h + self.bz)更新门,决定旧印象保留多少、新信息吸收多少
  3. r = sigmoid(self.Wr @ x + self.Ur @ h + self.br)重置门,过滤旧状态中参与候选构建的信息
  4. h_tilde = np.tanh(self.Wh @ x + self.Uh @ (r * h) + self.bh)候选新状态,先用重置门调制旧状态再与输入融合
  5. return (1 - z) * h + z * h_tilde按更新门插值,完成“印象更新”
  6. scores = np.array([np.dot(s, target_vec) for s in states])计算每个兴趣状态与目标商品的内积打分
  7. atts = np.exp(scores) / np.exp(scores).sum()softmax 归一化注意力权重
  8. gate = att * zAUGRU 核心:用注意力分数调制更新门,相关行为主导演化
  9. return (1 - gate) * h_prev + gate * h_tilde注意力调制下的演化状态更新

常见误区

误区我以为 DIEN 先单独训练一个 GRU 抽取兴趣,再另外训练一个 AUGRU 做演化,两个网络各管各的,最后拼在一起用。

正解实际上,GRU 兴趣抽取层和 AUGRU 兴趣演化层是端到端联合训练的,它们共享同一个损失函数(目标损失 + 辅助损失的加权和)。就像“读日记的人”和“带着问题分析日记的人”是同一个人,阅读和分析的过程相互促进,而不是先读完再另请高明。

为何常见:因为 GRU 和 AUGRU 名字相似、功能不同,容易被误认为是两个独立组件。加上很多讲解分别介绍两者,更加深了“独立模块”的印象。

误区我觉得 DIEN 就是把 DIN 的注意力池化层换成 RNN,本质上还是对行为做加权,没什么大区别。

正解DIEN 的关键升级不是“加了个循环网络”,而是用“抽取 + 演化”双阶段重新定义了兴趣建模方式:GRU 负责把行为序列变成兴趣状态序列,AUGRU 负责在目标商品引导下完成兴趣演化,辅助损失又额外约束了中间状态的质量。这三点共同作用,才带来 AUC 的稳定提升。

为何常见:从表面结构上看,DIEN 确实只是多了一层循环网络,容易让人低估它“时序建模 + 目标引导 + 辅助监督”的系统性设计。

误区我认为辅助损失是额外加上的任务,会让模型在“预测点击率”和“预测下一行为”之间左右为难,反而降低效果。

正解辅助损失不会“抢戏”,它是通过加权系数 $\alpha$ 与主损失融合的(通常 $\alpha$ 取 0.5~1.0)。它更像是给中间状态配备的“平时测验”,让每一步兴趣状态都更有信息量,最终帮助主任务做得更好。大量实验证明,加入辅助损失后 AUC 是提升而非下降。

为何常见:直觉上“多一个任务”可能分散模型注意力,但这里辅助任务与主任务高度相关(都围绕用户兴趣),属于互相促进的多任务学习。

误区既然 DIEN 效果更好,那干脆把所有推荐模型都换成 DIEN,一劳永逸。

正解DIEN 在行为序列丰富的高频场景优势明显,但在行为稀疏的低频场景(如房产、汽车),GRU 能读到的“日记页数”太少,时序演化难以成形,此时 DIN 的简单加权反而更稳健。工业界的常见做法是把两者都作为候选模型,用离线 AUC 和在线 AB 测试结果来决定用哪个。

为何常见:人们容易用“新模型一定碾压旧模型”的线性思维看问题,忽略了数据稀疏度、序列长度等现实约束对模型效果的影响。

面试题

Q1. DIEN 相比 DIN 的核心改进是什么?

单选题 · easy

  • A.用更大的嵌入维度来增加模型容量
  • B.引入 GRU 和 AUGRU 建模兴趣时序演化← 正确答案
  • C.改用决策树作为排序模型的基学习器
  • D.直接对原始特征做哈希处理加速

答案:B。DIEN 的核心贡献是在 DIN 的静态加权求和基础上,引入 GRU 抽取兴趣状态、AUGRU 建模兴趣演化,从而捕捉行为序列中的时序信息。A 是容量调整而非结构创新,C 和 D 与 DIEN 无关。

Q2. 在 DIEN 中负责“逐时刻提取兴趣状态”的是哪个模块?

单选题 · easy

  • A.嵌入层
  • B.GRU 兴趣抽取层← 正确答案
  • C.AUGRU 兴趣演化层
  • D.多层感知机

答案:B。GRU 兴趣抽取层按时间顺序读取每个行为嵌入,输出对应的兴趣状态序列;AUGRU 负责在目标商品引导下融合演化这些状态;嵌入层只负责查表,MLP 负责最终输出。

Q3. 关于 GRU 中更新门 $z_t$ 的作用,下列说法正确的是?

单选题 · mid

  • A.控制旧状态保留多少、新候选状态引入多少← 正确答案
  • B.直接输出最终的点击率预测值
  • C.决定嵌入向量的维度大小
  • D.对注意力分数做归一化处理

答案:A。更新门 $z_t$ 是一个 0 到 1 之间的门控值,$h_t = (1-z_t) \odot h_{t-1} + z_t \odot \tilde{h}_t$,它控制着旧状态与候选状态的比例。B 是 MLP 的事,C 是网络设计超参,D 是 AUGRU 注意力机制的事。

Q4. AUGRU 与标准 GRU 最本质的区别是什么?

单选题 · mid

  • A.AUGRU 的网络层数一定更深
  • B.AUGRU 的更新门被目标商品相关的注意力分数调制← 正确答案
  • C.AUGRU 使用 LSTM 的细胞状态结构
  • D.AUGRU 在训练时不需要更新任何参数

答案:B。AUGRU 将注意力分数 $a_t$ 乘到 GRU 更新门上,得到 $\tilde{z}_t = a_t \cdot z_t$,使演化过程具备目标导向性。这与层数、细胞状态和参数更新无关。

Q5. 关于 DIEN 的辅助损失,下列说法正确的有?

多选题 · mid

  • A.每个隐藏状态都预测下一个行为← 正确答案
  • B.负样本来自未交互的商品集合← 正确答案
  • C.用二分类交叉熵形式计算辅助损失← 正确答案
  • D.只在最终时间步计算该损失值

答案:ABC。辅助损失在每一步都用当前隐藏状态预测下一行为,正样本是真实下一行为,负样本随机采样自未交互商品,损失形式为二分类交叉熵。D 错误,因为辅助损失在每一步都计算并取平均。

Q6. AUGRU 中注意力分数 $a_t$ 的典型计算方式是什么?

单选题 · hard

  • A.对所有历史行为的注意力分数做全局 softmax 归一化← 正确答案
  • B.直接取固定常数 0.5 作为门控权重
  • C.由 LSTM 的细胞状态直接输出
  • D.用随机数生成器产生

答案:A。AUGRU 将目标商品与各兴趣状态的相关度打分后,用 softmax 归一化得到 $a_t$,使所有时刻的注意力权重和为 1。固定常数、随机数都与注意力机制无关。

Q7. 为什么 DIEN 在“低频耐用品”场景的增益可能不如高频场景?

单选题 · mid

  • A.行为序列太短,时序信息不足← 正确答案
  • B.模型无法处理高维稀疏特征
  • C.耐用品商品的嵌入维度更低
  • D.用户对耐用品的兴趣永远不会变化

答案:A。低频率导致用户行为序列过短,GRU 读到的“日记页数”太少,兴趣演化轨迹难以成形。B、C 与场景无关,D 本身就是不合理假设。

Q8. 下列哪些属于 DIEN 落地时的常见工程实践?

多选题 · hard

  • A.对超长行为序列做截断或采样处理← 正确答案
  • B.用负采样加速辅助损失的计算← 正确答案
  • C.冻结嵌入层参数以大幅提升精度
  • D.将 DIEN 与 DIN 作为候选模型离线对比 AUC← 正确答案

答案:ABD。超长序列截断能控制训练成本,负采样是辅助损失的标准加速手段,离线 AUC 对比是上线前的常规评估流程。C 中冻结嵌入层通常不会提升精度,反而可能损失特征学习能力。

Q9. 相比 LSTM,GRU 的显著优势是什么?

单选题 · easy

  • A.参数量更少、训练速度更快← 正确答案
  • B.可以处理无限长的序列
  • C.完全不需要激活函数
  • D.不需要任何门控机制

答案:A。GRU 只有两个门(更新门和重置门),而 LSTM 有三个门和一个细胞状态,因此 GRU 参数量更少、训练更快。“无限长序列”“无激活函数”“无门控”都是错误说法。

Q10. 关于 DIEN 的最终输出兴趣向量,下列说法正确的有?

多选题 · mid

  • A.已经融合了目标商品的相关性信息← 正确答案
  • B.可以直接拼接其他特征后送入 MLP← 正确答案
  • C.与行为序列的顺序完全无关
  • D.维度通常等于 GRU 隐藏单元数量← 正确答案

答案:ABD。AUGRU 在演化时融入了目标商品的注意力分数,因此输出向量带有目标相关性;它作为排序模型的兴趣特征拼接后进入 MLP;输出维度等于隐藏单元数。C 错误,因为 DIEN 明确建模了顺序信息。