巷口有家“老周咖啡”,店长老周有个绝活:熟客还没开口,他就端出“还是老样子”。他不是靠会员卡上写着“口味:偏甜”这种静态标签,而是靠一本翻旧的点单册。每来一次,他就按时间记一笔:周一冰美式,周二燕麦拿铁,周三手冲。等他预测“下一杯”时,会先看最近这一串顺序,再猜你的下一步。 这种“按时间排成队列,预测下一步”的思路,就是序列推荐。它和传统推荐最大的不同,是不再把你当成一张固定的画像,而是把你每一次点击、购买、播放都当作故事的一环。但老周也有头疼的时候:新客人只点过一次,他摸不清底细;十年老客的记录太长,他不可能从头翻;还有人突然从摩卡换成冷萃,兴趣说变就变。这些,正是序列推荐要面对的数据稀疏、长序列建模和兴趣漂移三大挑战。 本文就把“猜下一杯”变成正式问题:输入行为时间序列,输出下一个交互物品的概率。理解了这个问题框架,后续所有序列模型才有了共同起点。

岗位关联

学会定义序列推荐问题,是读懂 RNN、Transformer、图模型等序列推荐算法的前提;它能帮你从“只会调包”走向“能设计推荐策略”。

目录
  1. 可视化演示
  2. 序列推荐定义
  3. 与传统推荐差异
  4. 输入输出形式
  5. 数据稀疏挑战
  6. 长序列建模
  7. 兴趣漂移处理
  8. 会话与长期对比
  9. 问题定义价值
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

演示序列推荐输入、数据稀疏/长序列/兴趣漂移三大挑战及会话与长期推荐差异,建立问题框架。

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

序列输入:行为时间序列 交互物品 候选 S_u=[i₁,…i_t] 以历史序列预测下一个交互物品

序列推荐定义

老周招待客人时,嘴上聊着天,心里却在翻小本子:“上上次是拿铁,上次是美式,这次刚进门就盯着冷萃壶……”他不是随机推荐,而是把客人的每次点单按时间串起来,再判断下一杯最可能是什么。这个“按时间串起来的行为记录”,就是序列推荐眼里的输入。

如果只统计你最爱喝什么,这叫静态偏好;如果把“你的上一杯”也考虑进去,推荐结果会完全不同。比如刚喝完浓缩的人,可能不会立刻再来一杯浓缩,而更想喝杯水或拿铁。序列推荐的核心,是预测下一个交互物品,而不是泛泛地猜你最想要什么。形式化地说,设 \(v_t\) 表示用户在时刻 \(t\) 交互的物品,历史序列记作 \(S_t\),预测目标就是下一项。

老周的“绝活”一旦写成公式,就有了统一标准:不管咖啡、商品还是视频,只要能把用户行为变成序列,就能用同一套问题框架去优化。

v^t+1=arg⁡max⁡v∈VP(vt+1=v∣St),St=(v1,v2,…,vt)\displaystyle\hat{v}_{t+1} = \arg\max_{v \in \mathcal{V}} P(v_{t+1}=v \mid S_t), \quad S_t=(v_1, v_2, \ldots, v_t)
这个公式把“猜下一杯”翻译成了标准数学语言:给定前面的点单序列,在所有可点物品里挑条件概率最大的那一个。
  1. 行为序列 \(S_t\)把从第 1 次到第 \(t\) 次的交互按时间排成一串。
    St=(v1,v2,…,vt)S_t=(v_1, v_2, \ldots, v_t)
  2. 条件概率 \(P(v_{t+1}=v \mid S_t)\)在已知历史序列时,下一项是物品 \(v\) 的可能性。
    P(vt+1=v∣St)P(v_{t+1}=v \mid S_t)
  3. 候选全集 \(\mathcal{V}\)所有可能被推荐的物品集合。
    V={v(1),v(2),…,v(∣V∣)}\mathcal{V}=\{v^{(1)}, v^{(2)}, \ldots, v^{(|\mathcal{V}|)}\}
  4. 最大后验选择在所有候选中找出概率最大的物品作为预测结果。
    v^t+1=arg⁡max⁡v∈VP(vt+1=v∣St)\hat{v}_{t+1}=\arg\max_{v \in \mathcal{V}} P(v_{t+1}=v \mid S_t)

与传统推荐差异

传统推荐像看客人的会员卡登记表:年龄、性别、常点品类。老周瞄一眼就知道你爱喝甜的,却不知道你今天是想提神还是想解腻。表上的“口味”是静态的,不会因为昨天喝过浓缩而自动变化。

序列推荐不同。它把每一次点单都当作一局新故事的一部分:刚才点了什么,会影响接下来该推荐什么。“先买手机,再买手机壳”和“先买手机壳,再买手机”是完全不同的故事,传统协同过滤往往把两者看成一样的。换句话说,传统推荐做的是“用户画像 vs 物品特征”的静态匹配,而序列推荐做的是“给定行为历史,预测下一步”的条件估计。

老周从“看档案”升级为“看监控回放”,推荐才有现场感。这也是为什么序列推荐能捕捉兴趣的动态变化,而传统推荐往往只能在静态偏好上打转。

\displaystyleR_{\text{trad}}(u,i)=\text{Score}(\mathbf{p}_u,\mathbf{q}_i), \qquadR_{\text{seq}}(u,i)=P(i \mid S_t^u)
左边是传统推荐的静态打分,右边是序列推荐的条件概率;差别就在于有没有把时间顺序放进去。
  1. 静态用户向量 \(\mathbf{p}_u\)传统推荐用固定向量描述用户,类似会员卡上的口味标签。
    pu=Profile(u)\mathbf{p}_u = \text{Profile}(u)
  2. 静态物品向量 \(\mathbf{q}_i\)物品也有固定表示,用来和用户向量计算匹配分。
    qi=Feature(i)\mathbf{q}_i = \text{Feature}(i)
  3. 序列条件概率序列推荐把用户当前历史作为条件,再估计物品概率。
    Rseq(u,i)=P(i∣Stu)R_{\text{seq}}(u,i)=P(i \mid S_t^u)
  4. 差别一句话有没有把时间顺序加入打分函数。
    Rtrad→Rseq: 加入 StuR_{\text{trad}} \to R_{\text{seq}}:\ \text{加入 } S_t^u

输入输出形式

老周的点单册不是日记,而是按固定格式记录:哪个客人、第几杯、点了什么。训练序列推荐模型也需要同样的规范——输入是历史序列,输出是下一项,模型从中学习规律。

假设用户 \(u\) 在时刻 \(t\) 之前的行为是 \(v_1^u,\ldots,v_t^u\),第 \(t+1\) 次行为是 \(v_{t+1}^u\)。把这两部分打包,就得到一条训练样本。一个用户的所有行为可以切成很多条这样的样本,就像老周把一整年的小票剪成一段段“前一串→下一杯”。在线预测时,输入是实时积累的序列,模型对每个候选物品打分排序,输出推荐列表。

有了统一的输入输出形式,模型设计者才能把精力集中在“如何从历史序列中提取信息”,而不是每次都重新定义问题。

D={((v1u,…,vtu), vt+1u)∣u∈U, 1≤t<Lu}\displaystyle\mathcal{D} = \bigl\{ \bigl((v_1^u,\ldots,v_t^u),\, v_{t+1}^u\bigr) \mid u \in \mathcal{U},\ 1 \le t < L_u \bigr\}
这个式子说明:对每个用户、每个时间切分点,都能生成一条“历史序列 → 下一项”的训练样本。
  1. 用户集合 \(\mathcal{U}\)全部用户的集合,对应老周认识的所有客人。
    U={u1,u2,…,u∣U∣}\mathcal{U}=\{u_1,u_2,\ldots,u_{|\mathcal{U}|}\}
  2. 历史输入第 \(t\) 时刻及以前的交互序列。
    (v1u,…,vtu)(v_1^u,\ldots,v_t^u)
  3. 预测标签紧随其后的真实交互。
    vt+1uv_{t+1}^u
  4. 样本切分约束\(t\) 从 1 到 \(L_u-1\) 都能切分,其中 \(L_u\) 是用户行为总数。
    1≤t<Lu1 \le t < L_u

数据稀疏挑战

老周最怕两种客人:一是第一次进门的新客,只有一笔记录;二是总点冷门单品的老客,一年也点不了几次。他们的点单册太薄,老周看不出规律。放到推荐系统里,这就是数据稀疏。

交互很稀疏时,模型容易把偶然行为当成稳定偏好,产生过拟合;长尾物品因为样本少,很难被学明白。此外,用户点错、手滑、误点也都会混进序列,成为干扰模型判断的噪声。序列推荐既要面对“没有足够数据”的冷启动,也要面对“数据本身不干净”的噪声问题。

这就是为什么老周对新客人只能靠“大多数人这个时间会点什么”来兜底。数据稀疏,是后续所有模型必须面对的第一道坎。

sparsity=1−∣O∣∣U∣×∣I∣\displaystyle\text{sparsity}=1-\frac{|\mathcal{O}|}{|\mathcal{U}| \times |\mathcal{I}|}
稀疏度越高,说明可用的交互记录越少,模型越难从历史中总结规律。
  1. 观测交互数 \(|\mathcal{O}|\)实际产生并记录下来的交互数量。
    ∣O∣=∑u∈ULu|\mathcal{O}| = \sum_{u \in \mathcal{U}} L_u
  2. 潜在配对空间所有用户和所有物品形成的可能交互数量。
    ∣U∣×∣I∣|\mathcal{U}| \times |\mathcal{I}|
  3. 稀疏度没有被观测到的配对占比,越接近 1 越稀疏。
    1−∣O∣∣U∣×∣I∣1-\frac{|\mathcal{O}|}{|\mathcal{U}| \times |\mathcal{I}|}

长序列建模

熟客来了三年,老周的小本子记了三百杯。要把三百杯从头捋一遍再猜下一杯,既慢又容易晕。序列长度一旦增长,模型首先遇到的是效率问题。

许多先进序列模型用自注意力捕捉任意两个行为的关系。自注意力要两两比较,序列长度 \(L\) 每增加一倍,计算量大约变成原来的四倍;再加上隐藏维度 \(d\),总复杂度就是 \(O(L^2 d)\)。长序列不仅算得慢,还会让“很多很多步之前的关键信息”难以被有效传递,这就是长程依赖困难。

老周不会真的从三年前第一杯开始看,而是抓最近一段,再浓缩长期记忆。长序列建模的挑战,本质是在节省计算的同时不丢掉关键历史。

Complexity=O(L2d)\displaystyle\text{Complexity}=O(L^2 d)
计算量随序列长度平方增长,所以不能简单地把所有历史都塞进模型。
  1. 序列长度 \(L\)当前输入序列中的行为数量。
    L=∣St∣L=|S_t|
  2. 隐藏维度 \(d\)每个物品向量或隐状态的维度。
    d=dim⁡(ev)d=\dim(\mathbf{e}_v)
  3. 两两注意力每个位置与所有位置计算一次关联,共 \(L^2\) 次。
    L2L^2
  4. 复杂度含义\(L\) 增长时开销平方上升,模型需要截断窗口、注意力选择或记忆压缩来应对。
    O(L2d)O(L^2 d)

兴趣漂移处理

客人连着喝了一周摩卡,这周却突然开始点冷萃。老周如果只盯着最近几单,会以为他彻底换口味;如果死守历史,又追不上变化。兴趣漂移,就是这种“人的偏好随时间流动”的现象。

好的序列推荐需要同时看两本账:短期账管最近的口味变化,长期账管稳定的偏好底色。模型用一个融合权重 \(\alpha\) 把它们合成当前兴趣表示。\(\alpha\) 越大,最近行为的话语权越重;\(\alpha\) 越小,长期习惯更占主导。

老周心里那杆秤会动态调整:如果客人连续五杯冷萃,\(\alpha\) 自然变大;如果只是偶然尝鲜,长期习惯又会把推荐拉回原位。

ht=α gshort(Strecent)+(1−α) glong(Stlong)\displaystyle\mathbf{h}_t = \alpha\,\mathbf{g}_{\text{short}}\bigl(S_t^{\text{recent}}\bigr)+(1-\alpha)\,\mathbf{g}_{\text{long}}\bigl(S_t^{\text{long}}\bigr)
当前兴趣 = 短期兴趣的加权 + 长期兴趣的加权,权重由模型动态决定。
  1. 短期兴趣表示从最近一段行为提取的偏好向量。
    gshort(Strecent)\mathbf{g}_{\text{short}}(S_t^{\text{recent}})
  2. 长期兴趣表示从完整历史提取的稳定向量。
    glong(Stlong)\mathbf{g}_{\text{long}}(S_t^{\text{long}})
  3. 融合权重 \(\alpha\)控制最近行为有多大话语权,取值在 0 到 1 之间。
    α∈[0,1]\alpha \in [0,1]
  4. 融合表示加权求和得到当前时刻的兴趣向量。
    ht=αgshort+(1−α)glong\mathbf{h}_t = \alpha \mathbf{g}_{\text{short}} + (1-\alpha)\mathbf{g}_{\text{long}}

会话与长期对比

老周有两种待客记录。一种是一桌客人从落座到离开的点单小票,只有这一段,没有客人姓名;另一种是熟客跨年度的完整点单册,知道是谁,也知道过去所有偏好。前者像会话推荐,后者像长期序列推荐。

会话推荐通常没有用户 ID,只能用当前会话里短短几个交互做预测,因此更依赖局部转移关系,比如“点完拉花咖啡后常点蛋糕”;长期序列推荐有用户身份和全部历史,可以同时建模长期偏好与短期意图。问题设定不同,建模方法也随之分化:会话推荐更关注“这一段里发生了什么”,长期序列推荐则要同时回答“这个人是谁”和“他最近怎么了”。

所以,会话推荐更像“陌生人拼一桌时观察局部氛围”,长期序列推荐更像“老熟人来了,既要看交情,也要看他最近心情”。

session: v^t+1=g(st),long-term: v^t+1=g(pu,st)\displaystyle\text{session: } \hat{v}_{t+1}=g(\mathbf{s}_t), \qquad\text{long-term: } \hat{v}_{t+1}=g(\mathbf{p}_u,\mathbf{s}_t)
会话推荐只用当前会话表示做预测;长期序列推荐还会额外引入用户向量。
  1. 会话表示 \(\mathbf{s}_t\)由当前会话的交互序列编码而来。
    st=f(v1,…,vt)\mathbf{s}_t=f(v_1,\ldots,v_t)
  2. 用户向量 \(\mathbf{p}_u\)长期序列额外维护的稳定用户表示。
    pu\mathbf{p}_u
  3. 会话预测只用会话表示预测下一项。
    v^t+1=g(st)\hat{v}_{t+1}=g(\mathbf{s}_t)
  4. 长期预测把用户向量与会话表示结合后预测。
    v^t+1=g(pu,st)\hat{v}_{t+1}=g(\mathbf{p}_u,\mathbf{s}_t)

问题定义价值

老周之所以能把“猜下一杯”做明白,是因为他先把问题框死了:输入是什么?输出是什么?怎么算对?序列推荐也一样,问题定义清楚之后,数据集、评测指标、模型结构才有讨论的基准。

在标准设定下,模型 \(P_\Theta(v_{t+1}\mid S_t)\) 需要在所有候选物品上打分,并用极大似然学习:让真实下一杯的概率尽量大。这就是后续 RNN、Transformer、图模型等方法共同面对的目标函数。有了统一目标,不同模型可以在相同数据集上用 Hit Rate、NDCG 等指标横向比较,老周的点单经验也终于变成一套可迭代的推荐系统流程。

有了这个目标,任何序列模型都有了“指向标”:谁的下一杯预测概率高,谁就更好。老周这本点单册,终于从生活经验变成一套可度量、可迭代、可复用的推荐问题框架。

Θ∗=arg⁡max⁡Θ∑(St,vt+1)∈Dlog⁡P(vt+1∣St;Θ)\displaystyle\Theta^* = \arg\max_{\Theta} \sum_{(S_t, v_{t+1}) \in \mathcal{D}} \log P\bigl(v_{t+1} \mid S_t; \Theta\bigr)
目标是最小化预测误差、最大化真实下一项的概率;这是所有序列推荐模型共用的“指挥棒”。
  1. 模型参数 \(\Theta\)序列模型中所有可学习参数。
    Θ={θ1,θ2,…}\Theta=\{\theta_1,\theta_2,\ldots\}
  2. 单样本对数似然给真实下一项打出的对数概率,越大越好。
    log⁡P(vt+1∣St;Θ)\log P(v_{t+1} \mid S_t; \Theta)
  3. 全部样本求和把训练集里所有序列样本的似然加总。
    ∑(St,vt+1)∈D\sum_{(S_t, v_{t+1}) \in \mathcal{D}}
  4. 最优参数使总对数似然最大的参数组合。
    Θ∗=arg⁡max⁡Θ∑log⁡P(⋅)\Theta^*=\arg\max_{\Theta} \sum \log P(\cdot)

AI 应用场景

电商“下一件商品”推荐

阶段:离线训练与在线排序

解决的问题:用户先看手机壳还是先看手机,顺序不同代表不同购买意图。传统协同过滤忽略顺序,序列推荐则把浏览/加购/购买事件按时间建模,预测用户下一个最可能交互的商品,从而提升点击率和转化率。

具体案例:一个母婴用户在购物 App 上依次浏览婴儿车、奶粉、湿巾,系统根据“婴儿车→奶粉→湿巾”的序列关系,实时推荐尿不湿,而不是再推一辆婴儿车。

音乐与短视频的会话推荐

阶段:在线推理

解决的问题:匿名新用户没有历史画像,属于典型冷启动。会话推荐只利用当前会话内短短几次行为,快速推断用户当下兴趣,避免“因为没历史就推荐热门榜单”的粗放策略。

具体案例:游客打开音乐 App,连续听了周杰伦和林俊杰后,下一首被推荐孙燕姿。系统并没有登录用户 ID,只靠当前播放序列的局部转移规律完成推荐。

长视频平台的兴趣漂移适应

阶段:特征与模型训练

解决的问题:用户长期喜欢科技内容,最近却频繁看露营视频。只保留长期偏好会错过新兴趣,只放大短期行为又会丢失稳定底色。序列推荐用短期与长期兴趣融合的方式,动态调整推荐分布。

具体案例:视频平台发现某用户过去两周从“科技评测”切换到“露营装备”,于是推荐流中同时保留科技频道内容并逐步增加露营视频,让用户在探索新兴趣时不觉得推荐“崩了”。

Python 演示

python58 行
from collections import Counter, defaultdictimport random  class MarkovSequenceRecommender:    def __init__(self, order=1):        self.order = order        self.transitions = defaultdict(Counter)        self.item_count = Counter()     def fit(self, sequences):        for seq in sequences:            for i in range(len(seq)):                self.item_count[seq[i]] += 1                start = max(0, i - self.order)                context = tuple(seq[start:i])                self.transitions[context][seq[i]] += 1     def predict_next(self, sequence):        context = tuple(sequence[-self.order:])        candidates = self.transitions.get(context, {})        if not candidates:            return self.item_count.most_common(1)[0][0]        return max(candidates.items(), key=lambda kv: kv[1])[0]     def evaluate(self, sequences):        hits = 0        total = 0        for seq in sequences:            if len(seq) <= self.order:                continue            for i in range(self.order, len(seq) - 1):                past = seq[:i + 1]                if self.predict_next(past) == seq[i + 1]:                    hits += 1                total += 1        return hits / max(total, 1)  def main():    sequences = [        ["espresso", "latte", "americano", "latte"],        ["espresso", "espresso", "latte", "cold_brew"],        ["latte", "americano", "latte", "cold_brew"],        ["americano", "cold_brew", "latte", "latte"],    ]    random.shuffle(sequences)    split = max(int(len(sequences) * 0.75), 1)    train = sequences[:split]    test = sequences[split:] or [sequences[0]]    model = MarkovSequenceRecommender(order=1)    model.fit(train)    accuracy = model.evaluate(test)    print("next-item accuracy:", round(accuracy, 3))  if __name__ == "__main__":    main()
目的:用一阶马尔可夫链演示“根据历史序列预测下一项”的最简实现,并统计预测准确率。
  1. context = tuple(seq[start:i])把最近一个行为作为上下文,对应老周的“上一杯”。
  2. self.transitions[context][seq[i]] += 1统计“上一杯 → 这一杯”的转移次数。
  3. if not candidates: return self.item_count.most_common(1)[0][0]冷启动兜底:没见过该上下文就推荐全局最热。
  4. return max(candidates.items(), key=lambda kv: kv[1])[0]挑出现频率最高的下一杯。
  5. for i in range(self.order, len(seq) - 1)用历史预测未来,不把标签泄露给模型。

常见误区

误区我以为序列推荐就是给用户维护一个不断更新的静态向量,每次算一算这个向量和物品向量的相似度就行。

正解序列推荐的核心是条件概率 \(P(v_{t+1}\mid S_t)\),输入是完整的行为时间序列,一旦新增一个行为,整个序列的表示都可能被重组。老周不是只记你“爱喝甜”,而是翻最近一串点单;同一个用户刚看完《沙丘》和刚看完《猫和老鼠》,下一部推荐应该截然不同。

为何常见:很多入门资料把推荐简化成向量内积,让人忽略了时间维度的存在。

误区我觉得会话推荐和长期序列推荐都是行为序列,区别只是会话短一点,模型上没什么本质不同。

正解两者问题设定不同:会话推荐通常没有用户 ID,只利用当前会话内短短几次交互,靠局部转移关系;长期序列推荐拥有用户 ID 与完整历史,可以同时建模长期偏好和短期意图。前者更像老周看一桌陌生人的临时点单,后者更像他翻熟客的三年账本。

为何常见:两者输入都是序列,表面很像,初学者很容易混淆。

误区我觉得用户历史越多,模型掌握的信息越全,推荐一定更准,所以应该把能拿到的历史全放进去。

正解序列过长会带来噪声、计算开销和兴趣漂移。自注意力复杂度是 \(O(L^2 d)\),老周也不会从三年前第一杯开始想。实际中常用截断窗口、注意力选择、记忆压缩来处理长序列,盲目堆历史反而让推荐又慢又糊。

为何常见:直觉上“信息越多越好”,忽略了噪声和效率成本。

误区我觉得只要用户历史够长,数据稀疏问题就自然消失了。

正解历史长只代表少数老用户信息丰富,新用户和长尾物品仍然交互很少;而且长序列里还混着大量误点噪声。数据稀疏与长序列是同时存在的两个挑战,一个管“有没有历史”,一个管“历史太长怎么用”。

为何常见:人们容易把稀疏等同于“总数据量少”,忘了冷启动和长尾分布并不随单个用户历史变长而消失。

面试题

Q1. 序列推荐的核心输入是什么?

单选题 · easy

  • A.用户静态画像文件
  • B.用户行为时间序列← 正确答案
  • C.物品的固定属性表
  • D.全站热门物品榜单

答案:B。序列推荐把用户交互按时间排成 \(S_t\),并预测下一项。静态画像、固定属性、热门榜单都不包含顺序信息,就像老周看的是点单顺序,而不是会员卡。

Q2. “老王昨天买手机,今天买手机壳”,哪个推荐方式最能体现序列信息?

单选题 · easy

  • A.推荐全站热销的手机
  • B.推荐类似的电子产品
  • C.按手机到手机壳顺序推荐← 正确答案
  • D.推荐用户收藏的品牌

答案:C。序列信息指“先手机后手机壳”的先后依赖关系。热销、相似、收藏都忽略顺序,只有 C 明确使用了“手机 → 手机壳”的转移关系。

Q3. 序列推荐中“数据稀疏”最典型的场景是?

单选题 · easy

  • A.老用户历史记录超一万条
  • B.新用户只有一两次交互← 正确答案
  • C.所有用户交互都被完整记录
  • D.物品数量只有几十个

答案:B。新用户只有一两笔记录,模型无法判断其偏好趋势,属于典型冷启动。老用户历史长、数据完整、物品少都不构成稀疏问题。

Q4. 长序列建模中,自注意力模型的主要问题是?

单选题 · mid

  • A.无法感知交互的时间顺序
  • B.计算量随序列长度平方增长← 正确答案
  • C.不能捕捉用户的长期兴趣
  • D.只能用于会话推荐场景

答案:B。自注意力需要两两计算,复杂度为 \(O(L^2 d)\)。它可以通过位置编码感知顺序,也能捕捉长期兴趣,并非只能用于会话推荐,核心瓶颈是平方级计算开销。

Q5. 下列哪些属于兴趣漂移带来的挑战?

多选题 · mid

  • A.最近偏好发生明显改变← 正确答案
  • B.长期与短期兴趣互相冲突← 正确答案
  • C.用户交互数据更加稀疏
  • D.模型需要动态适应变化← 正确答案

答案:ABD。兴趣漂移体现为短期偏好变化、长期与短期冲突,以及模型需要动态调整。数据稀疏是另一个独立挑战,不一定由兴趣漂移引起。

Q6. 关于会话推荐与长期序列推荐,下列说法正确的是?

单选题 · mid

  • A.会话推荐不利用用户历史,只利用当前会话← 正确答案
  • B.长期序列推荐通常不使用用户身份信息
  • C.会话推荐必须使用 Transformer 模型训练
  • D.长期序列推荐无法捕捉短期兴趣变化

答案:A。会话推荐面向匿名场景,只用当前会话;长期序列推荐通常有用户身份和完整历史。Transformer 不是会话推荐必须使用的模型,长期序列推荐同样可以捕捉短期兴趣。

Q7. 序列推荐训练样本通常如何构造?

多选题 · hard

  • A.取前 t 个行为作输入,下一项作标签← 正确答案
  • B.从历史中随机抽取若干物品作为标签
  • C.每个位置都切分生成一条训练样本← 正确答案
  • D.只取最后一个交互作为标签

答案:AC。标准做法是对每个时间切分点构造“前 t 个行为 → 第 t+1 个行为”的样本。随机抽取和只取最后一项都会破坏序列监督信息,不能充分利用历史。

Q8. 在长期序列推荐中,把用户所有历史直接拼接作为输入的主要风险是?

单选题 · mid

  • A.历史越长,噪声和计算开销越大← 正确答案
  • B.数据越少,模型越容易过拟合
  • C.无法使用用户身份信息
  • D.无法捕捉短期兴趣变化

答案:A。直接拼接全部历史会让序列变得冗长,引入噪声并增大计算量;长期序列推荐仍然有用户身份,也能建模短期兴趣,因此 A 最符合题意。

Q9. 下列哪些是应对长序列建模的常见手段?

多选题 · hard

  • A.截断最近窗口← 正确答案
  • B.使用注意力机制选择关键历史← 正确答案
  • C.把所有历史压缩为固定长度表示← 正确答案
  • D.删除所有用户历史记录

答案:ABC。截断窗口、注意力选择和记忆压缩都能缓解长序列问题。删除所有历史等于放弃建模,显然不是可行策略。

Q10. 在公式 \(h_t = \alpha g_{\text{short}} + (1-\alpha)g_{\text{long}}\) 中,\(\alpha\) 越大表示?

单选题 · easy

  • A.越看重长期兴趣
  • B.越看重短期兴趣← 正确答案
  • C.模型训练越快
  • D.数据越稀疏

答案:B。\(\alpha\) 是短期兴趣的权重,\(\alpha\) 越大,最近行为对当前兴趣的影响越强。就像老周看到客人连喝五杯冷萃后,更愿意相信他最近真的换口味了。