杭州老城南有家茶楼,陈掌柜有个本事:熟客刚跨进门,他就知道该泡什么茶。凌晨下夜班的护士进门,他端上热姜茶;周末带孩子来的一家人,他先上酸梅汤。他不是会读心,而是会“读顺序”——每一位客人先后点了什么、隔多久来一次、上次离开时说过什么,都被他记在一本随身账本里。今天要讲的“基于RNN/LSTM的序列建模”,就是把这本账本变成一道数学工序,让推荐系统学会同样的本事:把 App 里用户一次次的点击、收藏、购买,按照发生的先后顺序读进去,猜出下一次最可能想要的东西。这个过程中,RNN 像记账的流程,LSTM 像一支懂得删改的笔,会话切分像给账本分页,而梯度消失则是陈掌柜也会遇到的“旧账字迹模糊”难题。读完这篇文章,你会对推荐系统内部的“时间记忆机制”有一张完整的认知地图。

岗位关联

对 AI 从业者来说,这是从“用特征匹配用户”升级到“用顺序理解用户”的分水岭。掌握 RNN/LSTM 序列建模,你将能独立完成行为序列的特征设计、模型选型和效果评估,在电商、内容、广告等推荐场景中直接落地。

目录
  1. 可视化演示
  2. 序列推荐背景:为什么顺序里藏着意图
  3. 循环神经网络:掌柜的活账本
  4. 梯度消失:旧账字迹越翻越淡
  5. LSTM门控机制:可删可写的记账笔
  6. 序列编码方向:正着记还是倒着记
  7. 会话切分策略:什么时候另起一页
  8. 短期兴趣与长序列局限
  9. 工程实践建议:把茶楼手艺写成标准流程
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

演示基于RNN/LSTM的序列推荐过程:用户行为序列的循环编码、LSTM三门控机制对信息流的控制,以及梯度流在长序列中的演化与衰减对比。

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

序列推荐编码过程 用户行为序列按时间步输入RNN循环单元 每个时间步生成隐状态编码用户短期兴趣 最终隐状态经全连接层输出推荐概率分布 h(t)=tanh(W·x(t)+U·h(t-1)+b) 循环结构捕获序列时序依赖关系

序列推荐背景:为什么顺序里藏着意图

陈掌柜判断茶水的依据,从来不是客人某一次点单,而是一连串点单组成的脉络。客人先点了冰镇酸梅汤,喝完又追加热乌龙,这个“由冰转热”的顺序,透露出身体不舒服或天气骤变的信息。单独看任何一次点单都看不出名堂,串起来才有故事。推荐系统也一样——用户的行为序列,是理解其当下意图的密码。

早期协同过滤把用户对物品的交互压缩成“用户-物品矩阵”,本质上假设“过去平均喜欢的,未来也喜欢”,完全不理会前半小时的浏览和昨天的浏览有什么区别。序列推荐则把用户行为按时间排列成序列,目标是在给定历史序列的条件下预测下一个行为,捕捉“最近想做什么”。

形式化地,把用户在 N 个时刻的行为记为序列:

其中 $x_t$ 是第 t 次交互物品的嵌入表示,$N$ 是序列长度。传统矩阵分解以“用户”为行、“物品”为列,而这里以“时间”为主轴,逐时刻刻画用户。

陈掌柜把客人最近的七次点单按时间排好,才敢开口推荐。这串时间顺序,就是序列推荐的“原始食材”——顺序本身,就是信息。

S=[x1,x2,…,xN]\displaystyle S = [x_1, x_2, \dots, x_N]
  1. 行为序列 S这是把用户交互日志按发生时间排序得到的列表,是后面所有模型的输入。
    S=[x1,x2,…,xN]\displaystyle S = [x_1, x_2, \dots, x_N]
  2. 时刻符号 x_t表示第 t 个时间步对应的物品向量,通常由物品 ID 经过嵌入层得到。
    xt∈Rd\displaystyle x_t \in \mathbb{R}^d
  3. 序列长度 N表示一共用了多少个历史行为,N 越大历史信息越多,但模型处理压力也越大。
    N=len(history)\displaystyle N = \text{len}(\text{history})

循环神经网络:掌柜的活账本

掌柜的账本不是静态表格,而是一本“活账”:每来一位客人,他不是翻到旧页从头看,而是只把旧账本的摘要带在身上,结合客人今天说的新话,刷新一次判断。RNN 的隐状态,干的就是这件事。

循环神经网络的核心是“循环”:同一个参数化函数在每个时间步被反复调用。输入 $x_t$ 与旧隐状态 $h_{t-1}$ 一起被压缩成新隐状态 $h_t$,携带到目前为止的全部历史摘要。参数在时间上共享,所以模型可以处理任意长度的序列。

单步更新写出来就是:

账本虽厚,每一页都只有薄薄一张摘要。RNN 就这样一步步“滚动”读完了整条行为序列,最后掏出这份摘要去预测下一杯茶。

ht=tanh⁡(Whh ht−1+Wxh xt+bh)\displaystyle h_t = \tanh(W_{hh}\, h_{t-1} + W_{xh}\, x_t + b_h)
  1. 旧账本 h_{t-1}上一步留下的历史摘要,是“到目前为止我了解这位客人”的记忆。
    ht−1∈Rh\displaystyle h_{t-1} \in \mathbb{R}^h
  2. 合并信号旧账本与新事件拼在一起,通过权重矩阵投影到同一空间。
    Whhht−1+Wxhxt+bh\displaystyle W_{hh} h_{t-1} + W_{xh} x_t + b_h
  3. tanh 压缩把合并结果压到 -1 到 1 之间,相当于掌柜做一个“温和的消化”,防止数值爆炸。
    tanh⁡(⋅)∈(−1,1)\displaystyle \tanh(\cdot) \in (-1, 1)
  4. 新账本 h_t更新后的状态,同时送给当前输出和下一个时间步。
    ht=tanh⁡(Whhht−1+Wxhxt+bh)\displaystyle h_t = \tanh(W_{hh} h_{t-1} + W_{xh} x_t + b_h)

梯度消失:旧账字迹越翻越淡

陈掌柜的账本记了三百页之后,回翻第一页就会发现字迹淡得几乎看不见。RNN 的长序列训练也遇到同样的麻烦:当序列很长时,早期时间步几乎收不到来自最终损失的“提醒”,学不到东西——这就是梯度消失。

反向传播时,损失对第 1 步参数的梯度,需要穿过从第 N 步到第 1 步的一整条连乘链。每个因子若模长小于 1,连乘结果会指数级缩小到零,早期信息被“吞掉”。

旧账记不清,掌柜必须改进记法——这就是 LSTM 登场的原因:与其让一页页摘要越滚越淡,不如在账本之外另设一条“记忆流水线”,专门保存那些重要的旧事。

∂L∂h1=∏t=2N∂ht∂ht−1⋅∂L∂hN\displaystyle \frac{\partial L}{\partial h_1} = \prod_{t=2}^{N} \frac{\partial h_t}{\partial h_{t-1}} \cdot \frac{\partial L}{\partial h_N}
  1. 损失 L衡量预测和真实下一个物品差距的误差函数,训练就是让 L 变小。
    L=Loss(prediction,ground truth)\displaystyle L = \text{Loss}(\text{prediction}, \text{ground truth})
  2. 偏导 ∂L/∂h_1表示“第 1 步记忆状态微变一点,最终损失变化多少”。
    ∂L∂h1\displaystyle \frac{\partial L}{\partial h_1}
  3. 连乘链从第 1 步到第 N 步的偏导逐一相乘,这是时间维度上的链式法则。
    ∏t=2N∂ht∂ht−1\displaystyle \prod_{t=2}^{N} \frac{\partial h_t}{\partial h_{t-1}}
  4. 指数衰减每个因子范数小于 1 时,乘积以指数趋势趋于 0,早期梯度消失。
    ∥∂ht∂ht−1∥<1  ⇒  ∏t=2N∂ht∂ht−1→0\displaystyle \left\| \frac{\partial h_t}{\partial h_{t-1}} \right\| < 1 \;\Rightarrow\; \prod_{t=2}^{N} \frac{\partial h_t}{\partial h_{t-1}} \to 0

LSTM门控机制:可删可写的记账笔

陈掌柜的记性其实一般,他的绝招是记账前先过一遍规矩:客人今天说“最近在控糖”,就把往年爱点的糖水单子划掉;客人提到“下周要跑马拉松”,就把“能量补给”写进最新一页;最后开口推荐前,还要斟酌一下——今天这番话,该按旧账说,还是按新账说?这三步,正是 LSTM 的三扇门。

LSTM 在 RNN 基础上增加一条“记忆单元” $c_t$ 作为信息高速公路,并配有遗忘门 $f_t = \sigma(W_f[h_{t-1}, x_t] + b_f)$、输入门 $i_t = \sigma(W_i[h_{t-1}, x_t] + b_i)$、输出门 $o_t = \sigma(W_o[h_{t-1}, x_t] + b_o)$,以及新记忆候选 $\tilde{c}_t = \tanh(W_c[h_{t-1}, x_t] + b_c)$。而记忆单元本身的更新,是序列建模中最关键的一笔:

靠着这支“可删可写”的记账笔,掌柜既能保留“客人从来不吃辣”这类稳定口味,又能快速更新“最近在减肥”这类短期变化。梯度在记忆单元这条高速路上少打折地流过,长距离依赖得以保留。

ct=ft⊙ct−1+it⊙c~t\displaystyle c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t
  1. 遗忘门 f_tsigmoid 输出 0 到 1,决定旧记忆 $c_{t-1}$ 保留多少,1 表示全留,0 表示全删。
    ft=σ(Wf[ht−1,xt]+bf)\displaystyle f_t = \sigma(W_f [h_{t-1}, x_t] + b_f)
  2. 逐元素乘法 ⊙门控值逐位作用到记忆向量上,相当于给账本逐行打勾或打叉。
    ft⊙ct−1\displaystyle f_t \odot c_{t-1}
  3. 输入门 i_t 与新候选 c̃_t决定当前事件里有多少新信息值得写入记忆。
    it⊙c~t\displaystyle i_t \odot \tilde{c}_t
  4. 记忆合成保留下来的旧记忆加上写入的新记忆,得到新一页账本。
    ct=ft⊙ct−1+it⊙c~t\displaystyle c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t
  5. 输出门 o_t决定从记忆里取多少内容生成当前输出。
    ht=ot⊙tanh⁡(ct)\displaystyle h_t = o_t \odot \tanh(c_t)

序列编码方向:正着记还是倒着记

掌柜递茶前有时会下意识问一句“您上次来是不是说这几天嗓子不舒服?”——这说明他既顺着时间往前记账,也会回头调用更早的关键信息。序列编码也有“方向”的选择题。

单向 LSTM 只按时间正序读取行为 $x_1 \to x_N$,这在在线预测场景是唯一的合法选择——预测第 N 步时,第 N+1 步还没发生。双向 LSTM 同时跑一个反向网络,把 $x_N \to x_1$ 的信息也编码进来,适合离线对完整序列做表示学习,但在做“下一个物品预测”时,正向的 $h_t$ 其实看不到未来,双向则会把未来信息带进编码,造成泄漏。

双向编码的最终表示为前向、后向两个隐状态的拼接:

掌柜接待客人时只能顺着聊,但闲下来整理客史时,可以正着倒着反复琢磨。模型同样分场景:线上实时预测必须“只看过去”,线下表征学习则可以“前看后看”。

ht=[h→t ⊤,  h←t ⊤]⊤\displaystyle h_t = [\overrightarrow{h}_t^{\,\top},\; \overleftarrow{h}_t^{\,\top}]^{\top}
  1. 前向隐状态正向 RNN 在 t 步的输出,记住“从开头到 t”的摘要。
    h→t=RNNf(x1,…,xt)\displaystyle \overrightarrow{h}_t = \text{RNN}_f(x_1, \dots, x_t)
  2. 后向隐状态反向 RNN 在 t 步的隐状态,记住“从结尾到 t”的摘要。
    h←t=RNNb(xN,…,xt)\displaystyle \overleftarrow{h}_t = \text{RNN}_b(x_N, \dots, x_t)
  3. 维度拼接把两个向量首尾相接,得到一个信息量更丰富的联合表示。
    ht=[h→t ⊤,  h←t ⊤]⊤\displaystyle h_t = [\overrightarrow{h}_t^{\,\top},\; \overleftarrow{h}_t^{\,\top}]^{\top}

会话切分策略:什么时候另起一页

同一桌客人聊了二十分钟茶歇,接着又开始聊新话题,陈掌柜会不动声色地翻一张新页——上次聊的是婚宴用茶,这次聊的是办公室口粮,混在一页账里只会越记越乱。行为序列同样需要“翻页”。

会话切分是序列建模的第一道数据工序。工程上常用时间间隔阈值:相邻两次行为间隔超过 $\tau$ 分钟就切一刀;也可结合业务边界,如订单完成后、App 从后台切回前台、搜索关键词变化等。切分的本质是保证同一序列内部意图连贯、噪声可控。

用指示函数统一描述切分规则:

每一个会话就像账本里一个完整的小故事。切分之后,掌柜(模型)读每一页时,主角意图都更聚焦,推荐的“下一句”自然更贴切。

Δti=ti+1−ti,cuti=1(Δti>τ)\displaystyle \Delta t_i = t_{i+1} - t_i, \quad \mathrm{cut}_i = \mathbf{1}(\Delta t_i > \tau)
  1. 行为间隔 Δt_i用户第 i+1 次行为与第 i 次行为之间的时间差。
    Δti=ti+1−ti\displaystyle \Delta t_i = t_{i+1} - t_i
  2. 阈值 τ工程上人工设定的超参数,如 30 分钟,超过即视为两个会话。
    τ=30 min\displaystyle \tau = 30 \text{ min}
  3. 指示函数 1(·)括号内条件成立输出 1(切分),不成立输出 0(连续)。
    1(Δti>τ)\displaystyle \mathbf{1}(\Delta t_i > \tau)

短期兴趣与长序列局限

陈掌柜最灵的是“短记性”:你刚进门说的那句话,他能记到你这杯茶喝完;但三个月前你随口提的旅行计划,他多半记岔了。RNN/LSTM 也一样——短期兴趣捕捉是它们的主场,而长序列的记忆则是短板。

隐状态是固定大小的向量,理论上可以容纳任意长度,实际上却像一个容量有限的抽屉:塞进去几百个行为后,早期信息被反复覆盖、挤压。研究显示,标准 LSTM 实际能稳定利用的有效历史只有几十步,再远基本失效。工程上因此普遍采用截断窗口,用最近 K 个行为建模:

掌柜靠台历和熟客档案弥补记忆缺陷,对应到模型就是注意力机制:允许模型在长历史中快速“点名”关键行为。注意力与 LSTM 的组合,正是后来众多序列模型的起点,也是从“单循环”走向“多任务统一建模”的桥梁。

P(at∣x1:t−1)≈P(at∣xt−K:t−1)\displaystyle P(a_t \mid x_{1:t-1}) \approx P(a_t \mid x_{t-K:t-1})
  1. 下一个行为 a_t模型要预测的目标,例如用户下一个点击的物品。
    at=next item\displaystyle a_t = \text{next item}
  2. 完整历史 x_{1t-1}:理论上应该参考的全部过往行为。
    x1:t−1=[x1,…,xt−1]\displaystyle x_{1:t-1} = [x_1, \dots, x_{t-1}]
  3. 最近 K 步 x_{t-Kt-1}:实际送入模型的截断窗口,K 通常取 20 到 50。
    xt−K:t−1=[xt−K,…,xt−1]\displaystyle x_{t-K:t-1} = [x_{t-K}, \dots, x_{t-1}]
  4. 近似相等 ≈说明长史的影响被近似忽略,这是容量受限下的妥协。
    P(at∣x1:t−1)≈P(at∣xt−K:t−1)\displaystyle P(a_t \mid x_{1:t-1}) \approx P(a_t \mid x_{t-K:t-1})

工程实践建议:把茶楼手艺写成标准流程

陈掌柜的手艺再精,也只能服务一条街。真要开遍全城,就得把“察言观色”变成新店员也能照做的标准流程——数据怎么记、账本怎么翻、好坏怎么判。RNN 序列推荐上线同样需要成套工程打法。

数据侧:行为日志按时间排序、同物品短时间重复点击去重、过滤爬虫和异常高频行为;用会话切分和截断长度生成训练样本。模型侧:物品 embedding 维度通常取 16 到 64,隐状态维度与 embedding 相当或翻倍;训练用 Adam 加梯度裁剪缓解梯度爆炸,配合学习率衰减。评估侧:离线用 Recall@K、NDCG@K 衡量排序质量,线上再结合 CTR 等指标做 A/B 实验。

序列推荐最常用的离线指标之一是:

把流程标准化后,哪怕换一批数据、换一个新模型,整条推荐流水线依然稳稳运转。陈掌柜的茶楼开成了连锁——这就是工程化的意义。

Recall@K=∣Rhit∩RtopK∣∣Rhit∣\displaystyle \text{Recall@K} = \frac{|\mathcal{R}_{\text{hit}} \cap \mathcal{R}_{\text{top}K}|}{|\mathcal{R}_{\text{hit}}|}
  1. 相关物品集合 R_hit测试集中用户真实交互过的物品。
    Rhit\displaystyle \mathcal{R}_{\text{hit}}
  2. 模型 TopK 集合 R_topK模型对下一个物品打分最高的前 K 个候选。
    RtopK\displaystyle \mathcal{R}_{\text{top}K}
  3. 交集取数量命中的真实物品数占真实物品总数的比例,K 越大通常 Recall 越高。
    ∣Rhit∩RtopK∣\displaystyle |\mathcal{R}_{\text{hit}} \cap \mathcal{R}_{\text{top}K}|

AI 应用场景

场景1:电商“猜你喜欢”的实时下一个点击预测

阶段:召回前的序列特征建模

解决的问题:传统 ItemCF 只看最近的单一行为或静态偏好,无法捕捉“先看手机壳、再看充电线”的连串意图;LSTM 把行为序列编码成向量,召回模型直接拿这个向量做输入,显著提升短时意图的响应速度。

具体案例:某电商 App 对用户最近 30 分钟内的点击序列用 LSTM 编码,输出向量与候选物品 embedding 做内积,TopK 召回“下一个可能点击”的商品。实践证明,会话级 LSTM 召回相比热门召回,点击率有明显提升。

场景2:短视频“下一条看什么”

阶段:精排阶段的序列特征 + 多任务排序

解决的问题:用户连续刷视频节奏很快,十秒内就要决定下一个推荐;RNN 能利用最近几十条观看记录与时长信息建模短期兴趣,避免连续推同质内容。

具体案例:某短视频平台用 LSTM 处理观看行为序列,输出序列兴趣向量后与多任务排序模型(同时预估点击、完播、点赞)结合,解决了“只点不看”的坏样本问题,人均观看时长上升。

场景3:新闻资讯流个性化排序

阶段:召回后的个性化打分

解决的问题:新闻意图变化非常快,早上看财经、下午看体育;LSTM 按会话切分后的阅读序列建模当前时段倾向,比长期画像更贴合实时兴趣。

具体案例:某资讯 App 把一次启动内的阅读序列切为一个会话,用 LSTM 编码后预测下一条点击新闻,并对序列预测和 CTR 预估做多任务联合训练,人均阅读时长得到提升。

Python 演示

python39 行
import torchimport torch.nn as nnimport numpy as np class SeqRecLSTM(nn.Module):    def __init__(self, num_items, embed_dim=32, hidden_dim=32):        super(SeqRecLSTM, self).__init__()        self.embedding = nn.Embedding(num_items, embed_dim)        self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)        self.out_layer = nn.Linear(hidden_dim, num_items)     def forward(self, seq):        emb = self.embedding(seq)        out, (hn, cn) = self.lstm(emb)        last_h = hn.squeeze(0)        logits = self.out_layer(last_h)        return logits def generate_data(num_seqs, seq_len, num_items, seed=42):    rng = np.random.RandomState(seed)    items = rng.randint(1, num_items, size=(num_seqs, seq_len + 1))    X = torch.tensor(items[:, :-1], dtype=torch.long)    y = torch.tensor(items[:, 1:], dtype=torch.long)    return X, y num_items = 50seq_len = 10X, y = generate_data(128, seq_len, num_items)model = SeqRecLSTM(num_items)loss_fn = nn.CrossEntropyLoss()optimizer = torch.optim.Adam(model.parameters(), lr=0.01) for epoch in range(5):    logits = model(X)    loss = loss_fn(logits, y[:, -1])    optimizer.zero_grad()    loss.backward()    optimizer.step()    print('epoch', epoch, 'loss', round(float(loss.item()), 4))
目的:用随机生成的行为序列模拟用户点击流,训练一个 LSTM 模型预测“下一个物品”,演示序列推荐建模的最小可运行闭环。
  1. self.embedding = nn.Embedding(num_items, embed_dim)把物品 ID 变成稠密向量,模型才能“看见”物品语义。
  2. self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)用现成 LSTM 层,内部就是三扇门。
  3. out, (hn, cn) = self.lstm(emb)前向跑一遍序列,hn 是最后一步的隐状态。
  4. last_h = hn.squeeze(0)取出最后一个时间步的隐状态,等价于掌柜总结完整个会话后的账本摘要。
  5. logits = self.out_layer(last_h)把账本摘要映射成对每个物品的打分。
  6. items = rng.randint(1, num_items, size=(num_seqs, seq_len + 1))生成行为日志,留出最后一位作为预测目标。
  7. y = torch.tensor(items[:, 1:], dtype=torch.long)用“下一个行为”做监督信号,构造序列自监督样本。
  8. loss_fn = nn.CrossEntropyLoss()在全部物品上做多分类损失。
  9. loss.backward()反传计算梯度,正是梯度消失讨论中的“时间连乘链”。
  10. print('epoch', epoch, 'loss', ...)观察损失下降,验证模型确实从序列中学到了规律。

常见误区

误区我之前以为 LSTM 就是 RNN 的完全升级版,有了门控就不会再丢远距离信息,序列想多长就多长。

正解门控只是给记忆提供了一条“高速路”,让梯度更容易直通,但记忆容量仍是固定大小的向量。极端长序列下,遗忘门会稳定地关掉大量早期记忆,这是它“学会”的行为,梯度依然会随信息丢失而衰减。所以长序列仍需截断、注意力或多层结构来兜底。

为何常见:论文和教程反复强调 LSTM“为缓解梯度消失而设计”,学习者容易从“缓解”过度解读为“彻底解决”。

误区推荐系统需要的序列,就是把用户所有点击下载下来按时间排好,直接丢给 LSTM 训练就完事了。

正解原始日志有大量噪声:机器行为、秒退点击、跨天悬挂的会话、异常高频操作。直接训练会让模型学到“乱序”和“刷屏”的假规律。必须先做去重、过滤、会话切分、截断、补 padding,样本质量决定了模型上限。

为何常见:初学者最先接触的是干净数据集(如 MovieLens),误以为生产环境的日志也同样干净。

误区双向能同时看到过去和未来,信息更全,模型效果肯定比单向好,序列推荐里直接用双向总没错。

正解在“预测下一个行为”这类自回归任务中,未来行为在做预测时并不存在,双向编码会让当前步偷看未来,导致离线指标虚高、线上大跌,即“标签泄漏”。只有对完整序列做表示学习(如生成会话向量)时才适合用双向。

为何常见:在 NLP 预训练任务中双向好处显著,学习者容易把经验直接搬进序列推荐,忽略时序因果。

误区模型能学到更多历史,输入序列长度从 10 加到 100,效果总该越来越好?

正解固定容量隐状态面对过长输入,早期信息被连续压缩,信噪比下降;过长的历史还包含大量过时意图,反而干扰预测。实验与工程经验都表明,截断在最近 20 到 50 步内通常最优。

为何常见:直觉上“数据越多越好”在静态模型里成立,但序列模型要同时考虑容量、噪声和意图漂移。

误区LSTM 的网络结构是固定的,所以输入序列必须是定长的,不像传统 MLP 那样可以随意变化。

正解恰恰相反,RNN 的参数是时间共享的,天然支持任意长度序列,这正是它比全连接网络更适合序列数据的原因;工程中定长只是为了 batch 训练时能 padding 成矩阵加速,推理时完全可以输入变长序列。

为何常见:因为练习时都用 padding 后的定长 tensor,误把这当成了模型本身的硬性限制。

面试题

Q1. 在推荐场景中,RNN 的隐状态 h_t 最主要承担什么角色?

单选题 · easy

  • A.保存历史行为的压缩摘要← 正确答案
  • B.存储用户唯一不变的画像
  • C.记录每个物品的原始文本
  • D.缓存模型所有可训练参数

答案:A。隐状态是“到目前为止历史行为的滚动摘要”,相当于掌柜的活账本。B 错在“唯一不变”,用户画像会漂移;C 错在隐状态不是原始文本;D 错在参数是权重,不是状态。

Q2. LSTM 中遗忘门 f_t 的输出数值经过哪个激活函数?

单选题 · easy

  • A.ReLU 函数输出通常大于等于零
  • B.sigmoid 函数取值被压缩到零一← 正确答案
  • C.tanh 函数取值被压缩到负一正一
  • D.softmax 多层分类输出和为一定

答案:B。遗忘门输出 0 到 1 的保留比例,必须由 sigmoid 产生。A 的 ReLU 无上界且不是门控惯例;C 的 tanh 在 LSTM 中用于候选记忆和输出调节,不是门;D 的 softmax 用于多分类概率分布。

Q3. 朴素 RNN 在长序列上梯度易消失,直接原因是什么?

单选题 · mid

  • A.激活函数输出通常严格大于一
  • B.前向传播完全不携带序列信息
  • C.长序列损失函数完全无法定义
  • D.时间维度反向连乘导致梯度衰减← 正确答案

答案:D。反向传播沿时间展开成偏导连乘链,因子小于 1 时指数衰减,早期梯度趋于零。A 应是小于一才衰减;B 前向传播显然携带信息;C 损失在任何长度下都可定义。

Q4. 会话切分的主要目标是?

单选题 · mid

  • A.让序列内部行为意图更加连贯← 正确答案
  • B.把所有用户行为拼成大序列
  • C.彻底删除中长期记忆信息
  • D.减少模型的整体参数量

答案:A。切分按间隔或业务边界把长日志切成意图一致的段,减少跨会话噪声,让“每一页账本”故事完整。B 方向反了;C 切分不删除模型记忆;D 切分不改变参数量。

Q5. 在线实时推荐通常不用双向 LSTM,主要原因是?

单选题 · mid

  • A.双向模型在训练时必然不收敛
  • B.双向模型在推理时速度过慢
  • C.会利用未来行为造成信息泄漏← 正确答案
  • D.双向模型不支持 GPU 加速

答案:C。预测当前时刻时未来尚未发生,双向编码会把右侧未来信息带进来,使离线指标虚高、线上失效。A 并非必然;B 是劣势但不是主因;D 双向完全可以 GPU 并行。

Q6. LSTM 记忆更新公式 c_t = f_t ⊙ c_{t-1} + i_t ⊙ c̃_t 中 ⊙ 表示?

单选题 · hard

  • A.矩阵的普通加法运算
  • B.向量逐元素相乘运算← 正确答案
  • C.向量拼接后的维度扩展
  • D.损失函数梯度的反向传播

答案:B。⊙ 是哈达玛积,即逐元素相乘,门控向量按位作用于记忆向量,相当于给账本逐行打勾或打叉。A 是加号;C 是拼接操作;D 是训练阶段概念,与符号无关。

Q7. 序列推荐把输入截断到最近 K 个行为,最根本的原因是?

单选题 · hard

  • A.固定大小的隐状态难以容纳过长历史← 正确答案
  • B.用户行为序列的实际长度通常小于 K
  • C.超过 K 的行为会被系统永久物理删除
  • D.截断后模型就不再需要任何训练了

答案:A。隐状态容量固定,过长序列会碾压早期信息,截断保留信噪比最高的近邻行为。B 与实际不符,序列往往很长;C 只是不送入模型而非物理删除;D 截断与训练无关。

Q8. 关于 RNN 参数时间共享的说法,正确的有哪些?

多选题 · mid

  • A.所有时间步共用同一组模型参数← 正确答案
  • B.参数共享显著减少模型的参数量← 正确答案
  • C.参数共享让模型支持任意长度输入← 正确答案
  • D.每个时间步使用各自独立的参数

答案:ABC。参数时间共享是 RNN 的核心,所有时间步用同一套权重,从而减少参数量并支持变长序列。D 描述恰好相反,若每步独立参数就退化为普通全连接网络。

Q9. 下列属于 RNN 序列推荐常用工程措施的有?

多选题 · easy

  • A.对行为按时序去重并过滤异常← 正确答案
  • B.用时间间隔阈值完成会话切分← 正确答案
  • C.用梯度裁剪技术稳定模型训练← 正确答案
  • D.用大量重复样本扩充训练数据

答案:ABC。去重过滤、会话切分、梯度裁剪都是序列推荐的标准操作。D 是反面典型——大量重复样本会造成过拟合,且不会增加真实信息量。

Q10. 关于 LSTM 门控机制,下列说法正确的是?

多选题 · hard

  • A.遗忘门控制旧记忆保留的比例← 正确答案
  • B.输入门控制新信息写入的多少← 正确答案
  • C.输出门控制送往下游的信息量← 正确答案
  • D.门控让 LSTM 不受任何长度限制

答案:ABC。遗忘门、输入门、输出门分别控制“留旧、写新、给出”。D 错在门控只是缓解长程依赖问题,记忆容量依旧有限,超长序列仍会遗忘早期信息。