如何用Python TensorFlow实现序列推荐系统_通过Embedding处理解决

轻墨同学_6639

轻墨同学_6639

2026-05-09

142人浏览

原创

直接用tf.keras.layers.Embedding做序列推荐会出错,因其仅完成ID到向量的静态查表,无法建模时序性、变长序列和上下文依赖;必须结合LSTM/Transformer等结构生成序列表示,并正确处理padding、mask及输出截断。

如何用python tensorflow实现序列推荐系统_通过embedding处理解决

为什么直接用 tf.keras.layers.Embedding 做序列推荐会出错

因为 Embedding 层本身只负责查表映射,不处理序列顺序、上下文依赖或动态长度——而推荐场景里用户行为序列(比如点击商品ID序列)天然具有时序性、变长、且需建模“下一个最可能点击什么”。直接把整条序列喂给 Embedding,等于丢掉了位置信息和交互逻辑,模型只会学到静态 ID 分布,无法预测 next-item。

常见错误现象:Model output shape doesn't match label shape(比如输出是 [batch, seq_len, vocab_size],但 label 是 [batch] 或 [batch, 1]);或者训练 loss 不下降,AUC 始终在 0.5 附近徘徊。

  • 必须明确区分「item embedding」和「sequence representation」两个阶段:前者用 Embedding,后者得靠 LSTM、GRU 或 Transformer 等结构
  • 输入序列需做 padding 或使用 tf.keras.preprocessing.sequence.pad_sequences 统一长度,但注意 mask 掉 padding 位置(否则梯度会被污染)
  • 推荐任务通常只预测最后一个 item,所以最终 logits 应取 sequence output 的最后一维,而不是全序列 softmax

怎么用 tf.keras.layers.Embedding + tf.keras.layers.LSTM 构建基础序列推荐模型

这是最易上手、调试成本低的 baseline。关键不是堆叠层数,而是让 embedding 和 RNN 的维度对齐,并正确截断输出。

示例核心代码片段(不含数据加载):

user_seq_input = tf.keras.Input(shape=(None,), dtype=tf.int32)  # 变长序列
mask = tf.keras.layers.Masking(mask_value=0)(user_seq_input)  # 自动忽略 0-padding
<h1>item embedding,vocab_size 是商品总数 + 1(含 padding id=0)</h1><p>item_emb = tf.keras.layers.Embedding(input_dim=vocab_size, output_dim=64)(mask)</p><h1>LSTM 提取序列特征,return_sequences=False → 只返回 final state</h1><p>seq_output = tf.keras.layers.LSTM(64, return_sequences=False)(item_emb)</p><h1>预测下一个 item:logits 维度 = vocab_size,但只对非 padding item 计算 loss</h1><p>logits = tf.keras.layers.Dense(vocab_size, activation=None)(seq_output)
model = tf.keras.Model(inputs=user_seq_input, outputs=logits)</p>

注意:return_sequences=False 是关键,否则输出 shape 是 [batch, seq_len, 64],后续 dense 层会广播出错;若想用 attention 或多步预测,才设为 True 并配合 TimeDistributed。

macOS UI 自动化技能包 —— 用 Python 控制你的 Mac
macOS UI 自动化技能包 —— 用 Python 控制你的 Mac

让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限

下载
  • embedding 的 input_dim 必须 ≥ 最大 item_id + 1,否则运行时报 IndexError: index out of bounds
  • 训练时 label 应为单个 item_id(int),不是整个序列;即每条样本是 (seq[:-1], seq[-1])
  • 用 sparse_categorical_crossentropy 损失函数,它能自动处理整数 label,比 categorical_crossentropy 更省内存、更准

tf.keras.layers.MultiHeadAttention 替代 LSTM 时要注意哪些兼容细节

Transformer 类模型在长序列上效果更好,但 TensorFlow 的 MultiHeadAttention 默认不支持变长输入,且要求显式提供 attention_mask,否则会把 padding 也当有效 token 计算 attention score。

必须手动构造 mask(形状为 [batch, 1, seq_len, seq_len]),并传入 call():

# 假设 seq_input 已 pad 到 max_len=50
attn_mask = tf.cast(tf.not_equal(seq_input, 0), tf.float32)  # [batch, seq_len]
attn_mask = attn_mask[:, tf.newaxis, tf.newaxis, :]  # 扩维成 [batch, 1, 1, seq_len]
# 注意:这是 causal mask 的基础,如需自回归(只看前面),还得叠加 tf.linalg.band_part(..., -1, 0)
<p>item_emb = Embedding(vocab_size, 64)(seq_input)
pos_emb = PositionalEncoding(max_len=50, d_model=64)(item_emb)  # 需自定义或用 tf.keras.layers.Layer 实现
x = tf.keras.layers.MultiHeadAttention(num_heads=4, key_dim=64)(
query=pos_emb, value=pos_emb, attention_mask=attn_mask
)</p><h1>后续接 LayerNorm、FFN,最后取 x[:, -1, :] 作为序列表示</h1>
  • 没有现成的 PositionalEncoding 层,必须自己写一个继承 tf.keras.layers.Layer 的类,否则位置信息丢失,模型退化为 bag-of-items
  • attention_mask 必须是 float32 类型,值为 0/1 或 -inf/0,不能是 bool;传错类型会导致 silent fail(loss 不更新)
  • 如果序列平均长度很短(

训练时 tf.data.Dataset 如何高效构造序列样本

原始日志是用户→行为列表,直接 for-loop 拆分效率低、内存炸、无法 pipeline。必须用 tf.data 的 sliding_window_batch 或自定义 map 函数生成 (seq, label) 对。

推荐做法(避免 as_numpy_iterator()):

def make_sequence_sample(x):
    # x 是一维 int32 tensor,如 [101, 205, 302, 408]
    seq = x[:-1]   # 输入序列
    label = x[-1]  # 下一个 item
    return seq, label
<p>ds = tf.data.Dataset.from_tensor_slices(user_item_lists)  # list of 1D tensors
ds = ds.map(make_sequence_sample, num_parallel_calls=tf.data.AUTOTUNE)
ds = ds.padded_batch(batch_size=256, padding_values=(0, 0), padded_shapes=([None], []))</p>
  • padded_shapes=([None], []) 表示第一个元素(seq)变长,第二个(label)是标量;写成 ([-1], []) 会报错
  • padding_values 必须与输入 dtype 一致:int32 输入就得用 0(int),不能用 0.0(float)
  • 别在 map 里调用 numpy 方法(如 x.numpy()),这会让 dataset 退出 graph mode,训练速度暴跌 5–10 倍

真正难的不是模型结构,而是把用户原始行为流对齐成 (seq, next_item) 格式——漏掉时间戳排序、混入测试期数据、没按用户切分,都会让指标完全不可信。

Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

python

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1871

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

5084

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1809

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

30597

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3627

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3647

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1243

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

616

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2823

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程