当前位置: 首页 > news >正文

别再死记硬背了!用TensorFlow 2.x手把手复现Google的WideDeep推荐模型

从零实现Wide&Deep推荐模型:用TensorFlow 2.x构建电影推荐系统

当你在视频平台看到"猜你喜欢"的推荐结果时,是否好奇背后的算法如何运作?Google提出的Wide&Deep模型巧妙结合了传统推荐系统和深度学习的优势,成为工业界广泛采用的解决方案。本文将带你用TensorFlow 2.x从零实现这一经典模型,基于MovieLens数据集构建一个真实的电影推荐系统。

1. 环境准备与数据理解

在开始建模前,我们需要准备好开发环境和理解数据特性。推荐使用Python 3.8+和TensorFlow 2.6+版本,这些版本在API稳定性和性能上都有良好表现。可以通过以下命令安装必要依赖:

pip install tensorflow==2.8.0 pandas numpy matplotlib

MovieLens数据集包含用户对电影的评分数据,我们将使用其中的100K版本,它包含:

  • 943位用户对1682部电影的100,000条评分(1-5分)
  • 用户 demographic 信息(年龄、性别、职业等)
  • 电影类型信息(如动作、喜剧等)

关键数据字段说明

字段名称类型描述
userIdint用户唯一标识
movieIdint电影唯一标识
ratingfloat用户评分(1-5)
timestampint评分时间戳
titlestring电影标题
genresstring电影类型(多值,用|分隔)

提示:在实际业务中,我们通常会将评分转化为二分类问题。例如将4-5分视为正样本(用户喜欢),1-3分视为负样本。

2. 特征工程实战

特征工程是推荐系统的核心环节,直接影响模型效果。Wide&Deep模型需要同时处理数值型和类别型特征。

2.1 数据预处理

首先加载并预处理数据:

import pandas as pd from sklearn.model_selection import train_test_split # 加载数据 ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=['userId', 'movieId', 'rating', 'timestamp']) movies = pd.read_csv('ml-100k/u.item', sep='|', encoding='latin-1', names=['movieId', 'title', 'release_date', 'video_release_date', 'imdb_url'] + [f'genre_{i}' for i in range(19)]) # 合并数据 data = pd.merge(ratings, movies, on='movieId') # 创建标签 - 将4-5分视为正样本 data['label'] = (data['rating'] >= 4).astype(int) # 划分训练测试集 train_data, test_data = train_test_split(data, test_size=0.2, random_state=42)

2.2 特征构建

Wide&Deep模型的特征处理有其特殊性:

Wide部分特征

  • 用户历史好评电影与当前电影的交叉特征
  • 简单而直接的组合特征,发挥记忆能力

Deep部分特征

  • 用户特征:平均评分、评分标准差等
  • 电影特征:类型、平均评分等
  • 需要Embedding的高维稀疏特征
import tensorflow as tf # 构建特征列 def build_feature_columns(): # 用户ID Embedding user_id = tf.feature_column.categorical_column_with_identity( 'userId', num_buckets=1000) user_id_embed = tf.feature_column.embedding_column(user_id, dimension=16) # 电影ID Embedding movie_id = tf.feature_column.categorical_column_with_identity( 'movieId', num_buckets=2000) movie_id_embed = tf.feature_column.embedding_column(movie_id, dimension=16) # 用户历史好评电影(用于交叉特征) rated_movie = tf.feature_column.categorical_column_with_identity( 'rated_movie', num_buckets=2000) # Wide部分交叉特征 crossed_feature = tf.feature_column.indicator_column( tf.feature_column.crossed_column([movie_id, rated_movie], 10000)) # 数值型特征 numerical_columns = [ tf.feature_column.numeric_column('user_avg_rating'), tf.feature_column.numeric_column('movie_avg_rating') ] return { 'deep_columns': [user_id_embed, movie_id_embed] + numerical_columns, 'wide_columns': [crossed_feature] }

3. 模型架构实现

现在我们可以构建完整的Wide&Deep模型架构。TensorFlow 2.x的Keras API让这一过程变得直观。

3.1 模型定义

def create_wide_deep_model(wide_columns, deep_columns): # 输入层 inputs = { 'userId': tf.keras.layers.Input(name='userId', shape=(1,), dtype='int32'), 'movieId': tf.keras.layers.Input(name='movieId', shape=(1,), dtype='int32'), 'rated_movie': tf.keras.layers.Input(name='rated_movie', shape=(1,), dtype='int32'), 'user_avg_rating': tf.keras.layers.Input(name='user_avg_rating', shape=(1,), dtype='float32'), 'movie_avg_rating': tf.keras.layers.Input(name='movie_avg_rating', shape=(1,), dtype='float32') } # Deep部分 deep = tf.keras.layers.DenseFeatures(deep_columns)(inputs) deep = tf.keras.layers.Dense(128, activation='relu')(deep) deep = tf.keras.layers.Dropout(0.2)(deep) deep = tf.keras.layers.Dense(64, activation='relu')(deep) # Wide部分 wide = tf.keras.layers.DenseFeatures(wide_columns)(inputs) # 合并两部分 combined = tf.keras.layers.concatenate([wide, deep]) output = tf.keras.layers.Dense(1, activation='sigmoid')(combined) return tf.keras.Model(inputs=inputs, outputs=output)

3.2 模型训练与评估

准备好数据输入管道后,我们可以开始训练:

# 初始化模型 feature_columns = build_feature_columns() model = create_wide_deep_model(feature_columns['wide_columns'], feature_columns['deep_columns']) # 编译模型 model.compile( optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy', tf.keras.metrics.AUC(name='auc')] ) # 创建训练数据集 def df_to_dataset(dataframe, shuffle=True, batch_size=32): dataframe = dataframe.copy() labels = dataframe.pop('label') ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels)) if shuffle: ds = ds.shuffle(buffer_size=len(dataframe)) ds = ds.batch(batch_size) return ds train_ds = df_to_dataset(train_data) test_ds = df_to_dataset(test_data, shuffle=False) # 训练模型 history = model.fit( train_ds, validation_data=test_ds, epochs=10, callbacks=[ tf.keras.callbacks.EarlyStopping(patience=3, restore_best_weights=True) ] )

训练过程关键指标监控

EpochTrain AccuracyTrain AUCVal AccuracyVal AUC
10.7120.7830.7210.791
20.7280.8020.7290.803
30.7350.8120.7330.809
40.7390.8180.7350.812
50.7420.8220.7360.814

4. 模型优化与生产部署

获得基础模型后,我们需要考虑如何优化和部署到生产环境。

4.1 模型优化技巧

特征工程优化

  • 增加用户行为序列特征(如最近观看的5部电影)
  • 尝试不同的Embedding维度
  • 添加时间衰减权重(近期行为更重要)

模型结构改进

  • 在Deep部分添加BatchNormalization
  • 调整Wide和Deep部分的连接方式
  • 尝试不同的激活函数
# 改进的Deep部分示例 deep = tf.keras.layers.DenseFeatures(deep_columns)(inputs) deep = tf.keras.layers.Dense(256, activation='relu')(deep) deep = tf.keras.layers.BatchNormalization()(deep) deep = tf.keras.layers.Dropout(0.3)(deep) deep = tf.keras.layers.Dense(128, activation='swish')(deep)

4.2 生产部署考虑

在实际生产环境中,我们需要考虑:

  1. 实时推理性能

    • 使用TF Serving部署模型
    • 优化特征预处理流水线
  2. 模型更新策略

    • 全量更新 vs 增量更新
    • A/B测试框架集成
  3. 监控与日志

    • 预测结果分布监控
    • 特征覆盖率检查

注意:生产环境推荐使用Docker容器化部署,确保环境一致性。同时要建立完善的特征存储系统,避免训练/服务特征不一致问题。

5. 模型效果分析与案例解读

理解模型的预测行为对改进系统至关重要。我们可以通过以下方式分析模型:

5.1 特征重要性分析

import shap # 创建解释器 explainer = shap.DeepExplainer(model, train_ds.take(1000)) # 计算SHAP值 shap_values = explainer.shap_values(dict(test_ds.take(10)))

典型特征影响

  1. 用户历史好评电影与当前电影的交叉特征(Wide部分)
  2. 电影平均评分(Deep部分)
  3. 用户平均评分(Deep部分)
  4. 电影类型Embedding(Deep部分)

5.2 推荐案例解析

假设用户A(userId=123)有以下特征:

  • 历史好评电影:《教父》、《肖申克的救赎》
  • 平均评分:4.2
  • 当前候选电影:《阿甘正传》

模型预测流程:

  1. Wide部分检测到《教父》与《阿甘正传》的交叉特征在训练数据中频繁共现
  2. Deep部分通过Embedding发现用户偏好严肃剧情片
  3. 综合两部分信息,给出高预测概率(0.87)

相比之下,对于同一用户的动作片候选:

  1. Wide部分缺乏强关联交叉特征
  2. Deep部分识别类型不匹配
  3. 最终预测概率较低(0.32)

这种分析帮助我们理解模型如何结合记忆和泛化能力做出推荐决策。

http://www.jsqmd.com/news/980262/

相关文章:

  • ASP.NET MVC多租户仓储系统源码:支持多企业隔离库存+采购销售财务全流程管理
  • 企业微信外部群机器人接入 AI:一套能落地的工程方案
  • 2026肇庆市黄金回收铂金回收白银回收彩金回收机构实力:项链+戒指+手镯+吊坠专业鉴定上门服务及联系方式推荐 - 亦辰小黄鸭
  • C语言介绍——通用的计算机编程语言
  • Gemini 3.5逻辑推理与精准度实测:算法题与知识问答场景下的能力边界
  • Bending Spoons 上市声明或揭秘“收购、裁员、然后呢?”策略真相
  • 归环夏奈角色介绍 归环夏奈玩法解析
  • Qt连接仪器踩坑记:VISA库配置、SCPI指令调试与NI-MAX使用全攻略
  • 云尖信息亮相英特尔至强6+发布会暨数据中心创新日,以全栈能力构筑Agentic AI时代新算力底座
  • BLE、Zigbee 超市货架电子价签(ESL)应用方案
  • 从DH1到3DH5:一文读懂蓝牙射频测试中那些让人头疼的数据包与调制方式
  • 告别均匀采样!用PER优先经验回放,让你的DQN在Atari游戏上快人一步
  • 科视 Christie 激光投影助力沉浸式水秀呈现南宋诗人陆游文化之旅
  • 定制换热板片该怎么选才靠谱
  • 华为USG6000防火墙升级避坑实录:从V1R1C30到V500R005C20的完整操作指南
  • 用C语言实战:最小公倍数在嵌入式编程和单片机开发中的一个具体应用案例
  • PHP并发处理与协程入门
  • 成本降87.5%:模具冲头助力3C企业年省28万 - 速递信息
  • Python小说章节自动采集入库工具:含MySQL连接池、去重建表与配置化部署
  • vue3实现的纯前端护肤品商城网站
  • 无人机管理系统|完整源码交付,支持私有化部署与定制开发
  • 手把手教你用Simulink搭建永磁直驱风机并网模型(附单位功率因数控制与弱磁控制仿真)
  • 2026年6月岳阳楼区流量卡“闭眼入”指南:39元电信神卡杀疯了!
  • 鼻毛剪刀哪个牌子好?鼻毛器哪个牌子最好用?2026鼻毛修剪器第一名
  • 普元EOS平台深度体验:除了快速开发,它的监控治理工具EOS Governor到底有多强?
  • LLM多智能体语义传播监控与漂移治理方法
  • UniVidX——基于扩散先验的统一多模态视频生成框架
  • 小程序毕设选题推荐:基于python的档案室档案宝微信小程序基于python的档案室档案宝微信小程序【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 手机拍证件照哪个好2026年专业证件照工具推荐
  • 51单片机控制16×16点阵LED,支持自定义文字滚动显示(含仿真+代码+文档)