巷口有家开了十多年的小咖啡店,老咖啡师阿岚从不问客人“您喝什么”。她只扫一眼柜台下压着的那卷长长的小票——你上一杯点了冰燕麦拿铁,上上杯是冷萃,再往前翻,三年前你第一次来点的是焦糖玛奇朵。就在你开口前的一瞬间,她已经猜出你八成想换一杯轻盈的手冲耶加雪菲。这手“点单预判术”,底层逻辑就是序列推荐:把用户一路走来的行为按时间串成一条线,顺着这条线推测下一个动作。而阿岚那本“越用越懂你”的大脑,就是本文的主角——Transformer。 Transformer 最初是翻译句子用的,后来被推荐系统“借”了过来,成了序列推荐的顶梁柱。它不关心你叫什么名字、是男是女,只盯着你那串历史行为,像阿岚盯着小票一样。它能在几十毫秒内顺着时间线回看所有关键节点,抓住“每次喝完冷萃,下一杯就想喝清爽的”这类隐藏规律,再给出最可能的下一项。本文会用阿岚和那卷小票陪你从头走一遍:序列怎么表示、注意力怎么回看、模型怎么训练、线上怎么部署,以及小白最容易踩的坑。

岗位关联

Transformer 序列推荐是当今电商、短视频、音乐等主流推荐系统的核心地基。掌握它,你才能真正理解从“猜你喜欢”到“为你推荐下一个”的技术全貌,也是面试搜索推荐算法岗位的必答题。

目录
  1. 可视化演示
  2. 序贯行为建模
  3. 输入特征构建
  4. 自注意力机制
  5. 多头与堆叠
  6. 预测与训练
  7. 多任务学习
  8. 部署调优实战
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

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

序列推荐基本框架 用户行为序列 Next? Transformer序列推荐模型 Q = X \u00b7 W_q K = X \u00b7 W_k Transformer序列推荐可视化:展示行为序列建模、Self-Attention机制、SASRec/BERT4...

序贯行为建模

阿岚柜台下那卷小票,从第一张到最新一张,按时间钉在一起,从不打乱。这就是序列推荐最朴素的起点:用户的每一次点击、购买、播放,都像一张小票,按时间先后排成一条“行为长卷”。传统推荐系统只关心“你是谁、喜欢什么类型”,比如给小甜口用户推摩卡;而序列推荐更进一步,它盯着“你最近做了什么”,因为同一批口味完全相同的用户,昨天看过话剧今天可能只想看喜剧。行为顺序本身就是信息。

把一个用户最近 t 次交互记为 v₁, v₂, …, vₜ,序列推荐的目标就是建模这样一个条件概率:已知过去一串行为的前提下,下一个物品最可能是什么。这和阿岚“顺着小票猜下一杯”是同一个问题,只是机器要算的不是直觉,而是可优化的数值。

这样,推荐问题就变成了一个标准的“下一项预测”问题:序列越长、建模越精细,“预判”就越准。阿岚之所以神,正是因为她不仅记得你上次点过什么,还记得三年前你第一杯是焦糖玛奇朵——序列推荐要学的,正是这种跨越长期与短期的双重记忆。

P(vt+1∣v1,v2,…,vt)\displaystyle P\left(v_{t+1} \mid v_1, v_2, \ldots, v_t\right)
竖线右侧是“已知条件”,左侧是“待预测目标”:给定过去 t 次交互,预测第 t+1 次交互是什么。
  1. 条件概率记号P(A | B) 读作“已知 B 发生时 A 发生的概率”;这里 B 就是全部历史行为。
    P(vt+1∣v1,v2,…,vt)P\left(v_{t+1} \mid v_1, v_2, \ldots, v_t\right)
  2. 下标含义vₜ 表示第 t 次交互的物品,顺序按照真实发生时间排列,绝不可乱序。
    v1,v2,…,vtv_1, v_2, \ldots, v_t
  3. 左边是目标模型的输出层要为每个候选物品算出一个概率,概率最高的就是“下一杯”。
    vt+1v_{t+1}

输入特征构建

阿岚脑中存着近百种豆子的“风味档案”:耶加雪菲有柑橘香,曼特宁醇厚带草药味,瑰夏是明亮的花香。每种咖啡豆都有一串特征,机器世界同样给每个物品配了一个低维稠密向量,叫“嵌入”(Embedding)。它相当于物品的身份证号转成的“口感密码”:语义相近的物品,向量在空间里也挨得近。

但光有风味卡还不够。阿岚知道“刚喝完重口冷萃再点单品”和“三年后才点单品”是两回事。同一杯咖啡,在小票上的位置决定了它的意义。Transformer 本身不带任何顺序概念,必须手动把“先后”信息注入进去,这就是位置编码(Positional Encoding)。做法很简单:给序列中第 pos 个位置生成一个固定模式的向量,再与物品嵌入相加,作为模型真正的输入。

位置编码里分母的 10000 决定了不同维度“摆动”的快慢:低维变化快,捕捉相邻位置的细微差别;高维变化慢,编码长距离的相对位置。这就像阿岚脑海里的小票不仅记得“你点了冷萃”,还标着“这是三天前点的,那是两个月前点的”——时间远近也被刻进了数字里。

Einput=evi+PE(i)\displaystyle E_{\text{input}} = e_{v_i} + \text{PE}(i)
PE(pos,2j)=sin⁡(pos100002j/d),PE(pos,2j+1)=cos⁡(pos100002j/d)\displaystyle \text{PE}(pos, 2j) = \sin\left(\frac{pos}{10000^{2j/d}}\right), \quad \text{PE}(pos, 2j+1) = \cos\left(\frac{pos}{10000^{2j/d}}\right)
物品嵌入镇守“是什么”,位置编码标记“在第几位”,两者相加,模型才同时知道“什么”和“什么时候”。
  1. 物品嵌入e_{vᵢ} 是第 i 个交互物品的嵌入向量,由查表得到,是模型要学习的参数。
    evie_{v_i}
  2. 位置函数PE(pos, 2j) 中 pos 是位置下标,j 是维度下标,偶数维用正弦、奇数维用余弦。
    PE(pos,2j)=sin⁡(pos100002j/d)\text{PE}(pos, 2j) = \sin\left(\frac{pos}{10000^{2j/d}}\right)
  3. 相加融合把“是什么”和“在哪个位置”两个向量逐位相加,得到真正的输入表示。
    Einput=evi+PE(i)E_{\text{input}} = e_{v_i} + \text{PE}(i)

自注意力机制

阿岚回看小票时,不是每张都同等用心:她会盯着“冷萃”这一行想很久,因为根据经验,冷萃之后你十有八九要一杯清淡的;而三年前的焦糖玛奇朵只是轻轻扫过。这种“对历史各环节区别对待”的能力,在 Transformer 里叫自注意力(Self-Attention)。它让序列中每个物品位置,主动去询问其他所有位置:“你与我的下一步有多相关?”再按相关度把对方的信息加权取过来,更新自己的表示。

自注意力的计算分三步走。首先,每个位置的输入向量分别乘上三个不同的矩阵,得到查询 Q、键 K、值 V——打个比方,Q 是“我想找什么样的记忆”,K 是“我这段记忆的标签”,V 是“我真正携带的内容”。然后,用 Q 与所有 K 做点积,得到“相关度分数”。最后,分数经过 Softmax 归一化成权重,再对 V 加权求和,得到该位置融合全局信息后的新向量。

自注意力让阿岚的目光在整卷小票上自由流动:无论“冷萃”出现在三天前还是三个月前,只要它与“下一杯”关系极大,都能被赋予高权重。相比只盯最近几单的旧方法,这种“全序列回看”的能力,正是 Transformer 序列推荐的灵魂。

Attention(Q,K,V)=softmax(QK⊤dk)V\displaystyle \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V
每个位置先问“谁跟我最有关系”,再按关系强弱从别人那里“吸收”信息,一轮下来,每个位置都成了“集全店记忆于一身”的明白人。
  1. 生成三路向量输入 X 分别乘以 W_Q、W_K、W_V,得到查询、键、值三组向量,三者各司其职。
    Q=XWQ,K=XWK,V=XWVQ = XW_Q, \quad K = XW_K, \quad V = XW_V
  2. 点积打分Q 与所有 K 的转置做矩阵乘法,结果矩阵第 i 行第 j 列表示“位置 i 对位置 j 的关心程度”。
    QK⊤QK^{\top}
  3. 缩放稳定除以 √d_k,防止维度大时点积数值过大,把 Softmax 推入饱和区导致梯度消失。
    QK⊤dk\frac{QK^{\top}}{\sqrt{d_k}}
  4. 归一化成权重Softmax 把每行分数变成非负且和为 1 的权重分布。
    softmax(QK⊤dk)\text{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)
  5. 加权聚合权重矩阵乘 V,按关心程度把各位置的内容融合进自己的表示。
    softmax(QK⊤dk)V\text{softmax}\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V

多头与堆叠

阿岚一个人看小票,容易只盯“搭配习惯”这一个角度。可她心里其实坐着一桌品鉴师:一位盯着风味走向——你正在从重口转向清爽;一位盯着冷热切换——大夏天你总点冰的;一位盯着时段规律——下午三点你必来一杯提神的。每位品鉴师各看各的侧重点,最后凑在一起商量出结论。多头注意力(Multi-Head Attention)干的就是这件事:把输入同时拆给 h 组独立的 Q/K/V,每组从不同子空间里寻找模式,再把 h 组的输出拼接起来,做一次线性融合。

多头之后还要做两件“保稳”的事。一是残差连接:把输入 X 原封不动加到注意力输出上,防止深层网络把初始信息“磨没了”;二是层归一化(LayerNorm):把每一层的输出拉回到稳定尺度,训练更快更稳。这“注意力 + 残差 + 归一化”组成一个 Transformer 块,而完整模型就是这种块一层层堆叠起来的:底层抓相邻物品的短时搭配,越往上越能捕捉长距离的抽象规律。

一桌品鉴师各执一词,最终得出比任何单一视角都全面的判断。回到模型上,这桌“品鉴师”就是多个注意力头:有的头专盯“同类目转移”,有的头专盯“时间间隔”,有的头甚至学会“处处都沾一点”。堆叠几层,阿岚的“预判力”就越发老练。

MultiHead(Q,K,V)=Concat(head1,…,headh)WO\displaystyle \text{MultiHead}(Q, K, V) = \text{Concat}\left(\text{head}_1, \ldots, \text{head}_h\right)W^{O}
多头是“多角度并行观察”,堆叠是“层层提炼升华”:前者扩大视野,后者加深理解。
  1. 分头计算把 Q、K、V 分别投影到 h 组低维子空间,每组独立执行自注意力。
    headi=Attention(QWiQ,KWiK,VWiV)\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)
  2. 拼接结果把 h 个头的输出沿特征维度拼成一个大向量。
    Concat(head1,…,headh)\text{Concat}\left(\text{head}_1, \ldots, \text{head}_h\right)
  3. 输出投影乘以 W^O 做线性融合,把多头信息整合成这一层的最终输出。
    Concat(head1,…,headh)WO\text{Concat}\left(\text{head}_1, \ldots, \text{head}_h\right)W^{O}

预测与训练

阿岚最后会在小黑板上给每款咖啡写一个概率:冰美式 0.4、燕麦拿铁 0.3、手冲耶加 0.2……概率最大那杯就是她的推荐。模型也是这样:把 Transformer 最后一层输出的隐藏向量 h(可以理解为整卷小票浓缩出的“当前口味状态”),与所有物品的嵌入矩阵做内积,再经过 Softmax 变成每个候选物品的概率分布。

训练时,模型要把自己“押错”的账算清楚。真实下一项是 y,模型给它的概率是 P(y),我们希望这个概率越大越好,于是定义损失为它的负对数——交叉熵。概率越接近 1,损失越接近 0;反之,押得越离谱,惩罚越重。但真实推荐系统里有几十万甚至上亿个候选物品,对全部物品算 Softmax 代价极高,于是常用负采样:只拿真实物品加随机抽的一小撮“没点过的”来近似计算。

阿岚每次猜错都会默默记住:原来你这次不喝燕麦奶,改喝豆奶了。模型用同样的方式,通过一次次交叉熵的“鞭策”,把注意力权重、嵌入向量打磨得越来越准。负采样则像是阿岚的“对比记忆法”:不用把整本菜单都盘一遍,抓几款你绝不会点的对比一下,就足够校正判断了。

P(vt+1=y∣history)=softmax(Eall⊤ht)y\displaystyle P\left(v_{t+1}=y \mid \text{history}\right) = \text{softmax}\left(E_{\text{all}}^{\top} h_t\right)_y
L=−log⁡P(vt+1=y∣history)\displaystyle \mathcal{L} = -\log P\left(v_{t+1}=y \mid \text{history}\right)
交叉熵就是“押错的代价”:真相的概率越低,代价越高,模型被迫一次次自我纠错。
  1. 打分把末位隐藏向量 hₜ 与全部物品嵌入矩阵 E_all 做内积,得到对每个候选物品的原始分数。
    Eall⊤htE_{\text{all}}^{\top} h_t
  2. 归一化Softmax 把分数变成概率分布,所有候选概率之和为 1。
    softmax(Eall⊤ht)y\text{softmax}\left(E_{\text{all}}^{\top} h_t\right)_y
  3. 取对数对真实物品 y 的概率取对数,概率越接近 1,log 值越接近 0。
    log⁡P(vt+1=y∣history)\log P\left(v_{t+1}=y \mid \text{history}\right)
  4. 取负号负号把“最大化概率”变为“最小化损失”,符合梯度下降的习惯。
    L=−log⁡P(vt+1=y∣history)\mathcal{L} = -\log P\left(v_{t+1}=y \mid \text{history}\right)

多任务学习

阿岚接待一桌客人时,眼睛同时要处理好几件事:客人下一杯会点哪款?要不要加糖?要不要顺手配一份蛋糕?这些问题相互关联——知道“这杯偏苦”就容易推断“要加糖”。在推荐系统里,光预测“点不点”往往信号太弱,于是让 Transformer 主干同时伸出好几个“预测头”:一个负责预测下一个物品,一个负责预测点击率,一个负责预测收藏概率,甚至一个负责预测停留时长。同一个主干,多个任务联合训练,彼此共享信息,这就是多任务学习。

多任务在工程上很划算:一次前向计算,多个结果同时产出;更重要的是,辅助任务在数据稀疏时能提供“额外信号”——用户没点不一定是讨厌,但收藏了一定是喜欢。多个任务的损失按权重相加,构成总的优化目标,权重的大小由业务优先级决定,比如电商更重视“加购”,短视频更重视“完播”。

阿岚的“一脑多用”让这家店越开越懂客人:咖啡推荐得准,连带甜点、糖包也配得恰到好处。多任务学习的妙处就在于此——一个模型干好几件事,任务之间互相“喂招”,比各自为战的单任务模型更稳、更准、更省资源。

Ltotal=λ1Lnext+λ2Lctr+λ3Laux\displaystyle \mathcal{L}_{\text{total}} = \lambda_1 \mathcal{L}_{\text{next}} + \lambda_2 \mathcal{L}_{\text{ctr}} + \lambda_3 \mathcal{L}_{\text{aux}}
多个损失像多位教练共同指导一个学生:各任务互相补充、互相约束,让共享主干学到更通用的行为表征。
  1. 主任务损失L_next 是下一物品预测的交叉熵,负责“猜你会点哪杯”。
    λ1Lnext\lambda_1 \mathcal{L}_{\text{next}}
  2. 辅助任务损失L_ctr 是点击率预估的损失,L_aux 可以是收藏、加购、时长等其他任务。
    λ2Lctr+λ3Laux\lambda_2 \mathcal{L}_{\text{ctr}} + \lambda_3 \mathcal{L}_{\text{aux}}
  3. 加权求和λ 是各损失的权重,总和为模型的最终优化目标。
    Ltotal=λ1Lnext+λ2Lctr+λ3Laux\mathcal{L}_{\text{total}} = \lambda_1 \mathcal{L}_{\text{next}} + \lambda_2 \mathcal{L}_{\text{ctr}} + \lambda_3 \mathcal{L}_{\text{aux}}

部署调优实战

周末高峰期,店门口排起长队,阿岚不可能再把三年小票从头翻到尾。她会扫一眼最近三五张小票,心里就有了答案;夜里人少时,她才会慢慢研究你的完整口味档案。线上推荐同样如此:完整 Transformer 的注意力复杂度随序列长度平方增长——序列越长,计算越贵。所以线上通常只取最近几十个行为(长序列截断),把巨大的物品全集缩小成几百个候选(候选集生成),模型只在这几百个里精排,推理延迟被压到毫秒级。

剩下的工程难题是“新客人怎么办”。冷启动用户没有历史序列,阿岚的做法是先热情推荐店里最经典的几款——对应系统的“热门兜底”;再问两句口味偏好——对应引入用户画像属性。对老用户,模型输出也会做多样性控制,避免永远推同一款。整套线上系统像一条流水线:召回 → 精排 → 重排 → 兜底,Transformer 负责其中“精排”这一环,用最少的计算换最准的判断。

阿岚的“忙时看近三单、闲时翻整卷”正是工业界的标准策略:训练时用尽可能长的序列学足规律,线上推理时截取关键窗口保证速度。理解了这个“训练贵、推理省”的取舍,你就能明白为什么推荐系统既要有强大的模型,也要有精巧的工程。

T(n)=O(n2d)\displaystyle T(n) = \mathcal{O}\left(n^2 d\right)
自注意力对序列长度 n 呈平方级增长:n 翻一倍,计算量变四倍。这决定了线上必须给序列“减肥”。
  1. 平方复杂度序列长度为 n 时,每个位置都要与其他 n 个位置两两算相似度,共 n² 次。
    n2n^2
  2. 维度因子每次相似度计算都在 d 维空间内做点积,复杂度再乘 d。
    n2×dn^2 \times d
  3. 大 O 记号T(n) = O(n²d) 表示计算量随 n 平方增长,是序列不能无限加长的数学根源。
    T(n)=O(n2d)T(n) = \mathcal{O}\left(n^2 d\right)

AI 应用场景

电商“猜你喜欢”的实时序列推荐

阶段:召回与精排阶段

解决的问题:传统协同过滤只按“人相似”推荐,忽略了用户当下的购物旅程。比如用户刚看完婴儿车,再推一个吸奶器显然比推男装合理。Transformer 序列推荐把浏览、加购、下单行为按时间编码,实时捕捉购物意图的转移,在用户点进首页的瞬间完成“下一件商品”的精排预测。

具体案例:某电商 App 用户在十分钟内依次浏览了“手冲壶→滤纸→咖啡豆”,序列模型给“分享壶”打出高分,因为历史规律显示“买齐前三样的人八成要入手分享壶”。推荐栏第一屏便出现分享壶,点击率比旧模型提升 12%。

短视频信息流的“下一条”预测

阶段:精排与流量调控阶段

解决的问题:短视频推荐的最大难点是用户兴趣漂移极快——上一秒看萌宠,下一秒可能想看美食。序列推荐把“完播、点赞、划走”做成事件流,让 Transformer 感知最近几分钟的兴趣变化,从而动态调整下一条视频。注意力机制尤其擅长捕捉“最近事件”的强信号。

具体案例:某短视频平台用基于 Transformer 的序列模型替换 GRU 模型后,在同等算力下单条视频的平均播放时长提升 8%,追“完播序列”的推荐命中率明显上升。

音乐App“接下来听什么”的歌单续播

阶段:个性化召回阶段

解决的问题:音乐收听是天然的高频序列行为:开车时听摇滚、深夜听民谣。Transformer 能根据最近 N 首播放记录,预测下一首最可能的歌曲,并顺带预测“是否切歌”,让 AI 歌单像老友一样懂你的耳朵。

具体案例:某音乐 App 的“智能续播”功能,将当前播放会话的最后 20 首歌作为序列输入,模型输出下一首歌候选集。上线后歌单平均连续播放时长提升 15%,切歌率下降 9%。

Python 演示

python70 行
import numpy as np  def build_sinusoid_encoding(max_len, dim):    pe = np.zeros((max_len, dim))    for pos in range(max_len):        for i in range(0, dim, 2):            angle = pos / (10000 ** (i / dim))            pe[pos, i] = np.sin(angle)            if i + 1 < dim:                pe[pos, i + 1] = np.cos(angle)    return pe  class AttentionHead:    def __init__(self, dim, seed=0):        self.dim = dim        rng = np.random.RandomState(seed)        self.wq = rng.randn(dim, dim) * 0.1        self.wk = rng.randn(dim, dim) * 0.1        self.wv = rng.randn(dim, dim) * 0.1     def forward(self, x):        q = x @ self.wq        k = x @ self.wk        v = x @ self.wv        scores = q @ k.T / np.sqrt(self.dim)        exp = np.exp(scores - scores.max(axis=-1, keepdims=True))        weights = exp / exp.sum(axis=-1, keepdims=True)        return weights @ v, weights  class SimpleSeqRec:    def __init__(self, num_items, dim, max_len):        self.num_items = num_items        self.dim = dim        rng = np.random.RandomState(1)        self.item_emb = rng.randn(num_items, dim) * 0.2        self.pos_enc = build_sinusoid_encoding(max_len, dim)        self.attn = AttentionHead(dim, seed=3)        self.out_w = rng.randn(dim, num_items) * 0.1     def train_step(self, seq, target, lr=0.05):        x = self.item_emb[seq] + self.pos_enc[:len(seq)]        h, _ = self.attn.forward(x)        logits = h[-1] @ self.out_w        logits -= logits.max()        exp = np.exp(logits)        probs = exp / exp.sum()        loss = -np.log(probs[target] + 1e-9)        grad = probs.copy()        grad[target] -= 1        self.out_w -= lr * np.outer(h[-1], grad)        return loss  def main():    rng = np.random.RandomState(42)    num_items, dim, max_len = 20, 8, 6    model = SimpleSeqRec(num_items, dim, max_len)    for step in range(80):        seq = rng.randint(0, num_items, size=max_len)        target = int(rng.randint(0, num_items))        loss = model.train_step(seq, target, lr=0.05)        if step % 10 == 0:            print("step", step, "loss", round(float(loss), 4))  if __name__ == "__main__":    main()
目的:演示一个极简的“位置编码 + 自注意力 + Softmax 预测”序列推荐训练闭环,让你看到 Transformer 序列推荐的核心流程在代码里长什么样。
  1. angle = pos / (10000 ** (i / dim))按位置与维度生成不同频率的正余弦相位,把“先后顺序”编码成向量。
  2. scores = q @ k.T / np.sqrt(self.dim)缩放点积注意力分数,是自注意力最核心的一步。
  3. exp = np.exp(scores - scores.max(axis=-1, keepdims=True))减去最大值再取指数,保证数值稳定。
  4. weights = exp / exp.sum(axis=-1, keepdims=True)对分数做 Softmax,得到“谁对谁重要”的权重。
  5. x = self.item_emb[seq] + self.pos_enc[:len(seq)]把物品嵌入与位置编码相加,构造模型输入。
  6. logits = h[-1] @ self.out_w取序列最后位置的隐藏表示,映射到全部物品打分。
  7. self.out_w -= lr * np.outer(h[-1], grad)按交叉熵梯度更新输出层,让模型逐步学会预测下一项。

常见误区

误区既然 Transformer 能捕捉长期依赖,我就把用户三年的全部行为都塞进序列,反正信息越多越准。

正解序列过长会带来三重麻烦:注意力计算量随长度平方暴涨;太久远的交互大多是噪声,反而稀释近期信号的权重;训练时梯度传播也会更不稳定。工业界通常只取最近几十到几百个行为,配合截断窗口和位置编码,效果远好于“无脑全塞”。就像阿岚高峰期只看最近三五张小票,而不是把三年旧账全翻出来。

为何常见:初学 Transformer 时被“长依赖能力强”宣传所吸引,误以为输入越长一定越好。

误区把序列推荐当成“袋子”来用,乱序输入也能出结果,位置信息不重要。

正解Transformer 结构本身对顺序完全“无感”,把所有物品向量放进一个集合里,模型分不清“三天前”和“三年前”。位置编码是模型感知时间先后、起止边界的关键输入。去掉位置编码,序列推荐就退化成词袋模型,推荐效果会断崖式下跌。

为何常见:注意力公式里看不到显式的“顺序”二字,初学者容易误以为模型天然理解顺序。

误区训练时用真实历史序列,推理时用模型预测出的序列,反正都是序列,没差别。

正解这叫“暴露偏差”(Exposure Bias)。训练时每个位置都拿真实物品做输入,可线上推理时模型只能拿自己预测的物品继续滚动,预测错一步就可能被无限放大。缓解手段包括训练中随机用预测结果替换部分输入(Schedule Sampling)、使用掩码机制等。阿岚现场点单能准,是因为她每单都收到真实反馈;如果她只能靠猜的下单继续猜,迟早跑偏。

为何常见:训练与推理的代码往往写在不同模块里,差异被框架封装隐藏,不易察觉。

误区把注意力头数加到 64、层数堆到 12 层,反正模型容量大,效果肯定更好。

正解推荐场景数据通常比 NLP 稀疏得多,过大的模型容易过拟合,训练也慢。头数过多还会让每个头分到的子空间太小,特征表达反而退化。实际工程里头数 4-8、层数 1-3 是常见配置,且要用验证集调参。阿岚的“一桌品鉴师”够用就好,请来一百个反而吵翻天。

为何常见:看到大模型在 NLP 上的成功,容易照搬到数据形态完全不同的推荐场景。

误区把序列推荐的输出接一个点击率预测头,反正点击是最核心的业务指标。

正解单一任务信号太弱,且点击只反映“感不感兴趣”,无法覆盖收藏、加购、时长等信息。多任务学习让共享主干同时预测多个目标,既能缓解数据稀疏,又能让下游业务直接拿到多种预测分数。阿岚既猜你点什么,也猜你加不加糖、要不要蛋糕,观察维度多了,判断自然更准。

为何常见:单任务模型实现简单、指标单一,容易让初入行者产生“够用”的错觉。

面试题

Q1. 序列推荐模型的核心目标是什么?

单选题 · easy

  • A.预测用户下一个交互的物品← 正确答案
  • B.对所有历史物品重新排序
  • C.把相似用户聚成一个群体
  • D.生成推荐理由的说明文案

答案:A。序列推荐把用户行为按时间排列,目标就是预测“下一个最可能交互的物品”。阿岚猜下一杯,就是最形象的解释。B 是对全部历史重排,不是预测未来;C 是用户聚类;D 是推荐文案任务,均偏离核心。

Q2. Transformer 中位置编码的主要作用是什么?

单选题 · easy

  • A.让模型感知序列中的先后顺序← 正确答案
  • B.缩小模型整体的参数量规模
  • C.替换掉物品嵌入向量的位置
  • D.将输入序列平均分为几段

答案:A。自注意力天然不区分顺序,位置编码把“第几位”的信息注入输入,模型才知道“三天前”和“三年前”的区别。它不减少参数量,也不替代嵌入或切分序列,所以排除 B、C、D。

Q3. 自注意力中 Q 与 K 做点积,衡量的是什么?

单选题 · mid

  • A.查询项与关键项的匹配程度← 正确答案
  • B.所有物品出现的总频次高低
  • C.用户序列本身的长度大小
  • D.模型参数收敛速度的快慢

答案:A。Q 代表“想找什么样的记忆”,K 代表“这段记忆的标签”,点积越大说明越匹配。它不统计频次、不体现序列长度、更与收敛速度无关,因此选 A。

Q4. 自注意力公式里除以 √d_k 的目的是什么?

单选题 · mid

  • A.避免点积过大致梯度消失← 正确答案
  • B.直接压缩特征向量的维度
  • C.提升注意力的计算并行度
  • D.强制各头输出保持一致

答案:A。维度高时点积数值容易变得很大,Softmax 会进入饱和区,梯度趋近于零。除以 √d_k 把分数拉回合理范围,保障训练稳定。它不改变向量维度、不影响并行度,也与多头一致性无关。

Q5. 关于 Transformer 序列推荐中的多任务学习,下列说法正确的有?

多选题 · mid

  • A.共享主干并输出多个预测头← 正确答案
  • B.各任务损失加权地联合训练← 正确答案
  • C.辅助任务能缓解数据稀疏性← 正确答案
  • D.多任务必定降低主任务精度

答案:ABC。多任务学习共享一个 Transformer 主干,同时输出点击、收藏等多个预测头,损失加权联合训练,辅助信号能缓解稀疏问题。D 说“必定降低”过于绝对,实践中大多反而提升主任务精度。

Q6. 负采样在序列推荐训练中主要解决什么问题?

单选题 · mid

  • A.降低候选物品 softmax 开销← 正确答案
  • B.让位置编码更加稀疏化
  • C.替代全部训练样本的数据增强
  • D.消除用户历史中的噪声

答案:A。物品候选集动辄几十万,对全集做 Softmax 代价极高。负采样只保留真实物品加一小撮随机负例,大幅降低计算量。它不针对位置编码,也不是数据增强或去噪手段。

Q7. “训练时用真实物品,推理时用模型预测物品”导致的偏差通常叫做什么?

单选题 · hard

  • A.训练与推理的暴露偏差← 正确答案
  • B.训练数据分布的采样偏差
  • C.推荐结果排序的相互挤压
  • D.模型参数过大导致的过拟合

答案:A。训练时模型看到的都是真实历史,推理时却要拿自己的预测结果继续推荐,二者输入分布不一致,称为暴露偏差(Exposure Bias)。它特指训练/推理的序列差异,而非采样偏差、排序挤压或过拟合。

Q8. 面对新用户冷启动,下列可行的应对策略有?

多选题 · hard

  • A.用热门物品作为兜底推荐← 正确答案
  • B.引入用户年龄等属性特征← 正确答案
  • C.用内容特征替代交互序列← 正确答案
  • D.增大模型训练的学习率

答案:ABC。冷启动没有历史序列,常见做法是热门兜底、引入画像属性、用物品内容特征作为序列的替代信号。增大学习率属于训练超参数调整,解决不了“没有数据”的问题。

Q9. 长度为 n 的序列,单头自注意力的时间复杂度是?

单选题 · extreme

  • A.时间复杂度是序列长度的平方← 正确答案
  • B.时间复杂度与序列长度线性正比
  • C.复杂度与物品数量完全无关
  • D.复杂度只取决于嵌入维度大小

答案:A。每个位置都与所有位置两两计算相似度,得到 n×n 的注意力矩阵,复杂度为 O(n²d),本质上是序列长度的平方项主导。线性正比、只看维度、与物品数量无关的表述都不准确。

Q10. 关于多头注意力的特点,下列说法正确的有?

多选题 · mid

  • A.不同头关注不同的行为模式← 正确答案
  • B.各头独立计算后拼接融合← 正确答案
  • C.增加模型容量并提升表达力← 正确答案
  • D.必须移除残差连接才能生效

答案:ABC。多头让不同头从不同子空间学习,如有的盯同类目转移、有的盯冷热切换;各头独立算完拼接再投影,增加容量与表达力。残差连接是配套的稳定手段,不能移除,D 错误。