PyTorch 神经协同过滤 (NCF) 推荐系统教程

目录

      • 教程概述
      • 1. 神经协同过滤模型概述
        • NCF 模型的主要组成部分:
      • 2. 数据加载与预处理
      • 3. 定义神经协同过滤模型
      • 4. 训练模型
      • 5. 模型评估
      • 6. 推荐物品
      • 7. 完整示例
      • 8. 总结

在本教程中,我们将使用 PyTorch 实现一个神经协同过滤(Neural Collaborative Filtering,简称 NCF)推荐系统。神经协同过滤是一种基于深度学习的推荐系统模型,通过学习用户和物品的嵌入表示来预测用户对物品的评分,进而提供个性化的推荐。

教程概述

推荐系统通过分析用户历史行为数据,为用户推荐相关的物品或内容。在协同过滤方法中,我们关注于从用户-物品评分矩阵中挖掘出潜在的规律,从而预测用户对未见物品的评分。

在本教程中,我们将:

  1. 介绍神经协同过滤模型的基本原理。
  2. 使用 PyTorch 实现 NCF 模型。
  3. 训练并评估该模型。
  4. 使用训练好的模型为用户推荐物品。
  5. 绘制训练过程中的损失曲线图表,帮助我们更直观地理解模型训练效果。

1. 神经协同过滤模型概述

神经协同过滤 (NCF) 是一种深度学习方法,用于解决传统协同过滤方法在处理用户-物品关系时的限制。其基本思想是通过将用户和物品的特征嵌入到低维向量空间中,然后通过神经网络对这些嵌入向量进行组合和映射,最终预测用户对物品的评分。

NCF 模型的主要组成部分:
  • 嵌入层 (Embedding Layer):通过学习低维的用户和物品嵌入向量,将高维的用户 ID 和物品 ID 映射到低维空间。
  • 多层感知机 (MLP):通过一个多层感知机(全连接层)将用户和物品的嵌入向量拼接起来,进行进一步的特征学习和映射,最后输出预测的评分。

2. 数据加载与预处理

首先,我们需要准备一个评分数据集。该数据集通常包含用户对物品的评分,格式如下:

userId, movieId, rating
1, 102, 4.32
2, 47, 3.85
3, 356, 4.72
...

我们使用 pandas 加载数据并进行预处理,将用户 ID 和物品 ID 昻射到连续的整数索引,并划分训练集和测试集。

import torch
import torch.nn as nn
import torch.optim as optim
import pandas as pd
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt# 1. 加载并准备数据
def load_data(file_path):df = pd.read_csv(file_path)train_data, test_data = train_test_split(df, test_size=0.2, random_state=42)# 创建用户和物品的映射字典user_map = {user: idx for idx, user in enumerate(df['userId'].unique())}movie_map = {movie: idx for idx, movie in enumerate(df['movieId'].unique())}# 映射用户和物品 IDtrain_data['user'] = train_data['userId'].map(user_map)train_data['movie'] = train_data['movieId'].map(movie_map)test_data['user'] = test_data['userId'].map(user_map)test_data['movie'] = test_data['movieId'].map(movie_map)return train_data, test_data, len(user_map), len(movie_map)

3. 定义神经协同过滤模型

接下来,我们将使用 PyTorch 定义神经协同过滤模型。该模型包含两个嵌入层(一个用于用户,另一个用于物品)和一个多层感知机(MLP)来组合用户和物品的嵌入向量,最后输出一个预测评分。

import torch
import torch.nn as nnclass NCF(nn.Module):def __init__(self, num_users, num_movies, embedding_dim=50, hidden_dim=64):super(NCF, self).__init__()# 嵌入层self.user_embedding = nn.Embedding(num_users, embedding_dim)self.movie_embedding = nn.Embedding(num_movies, embedding_dim)# MLP 层self.mlp = nn.Sequential(nn.Linear(embedding_dim * 2, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, hidden_dim),nn.ReLU(),nn.Linear(hidden_dim, 1))def forward(self, user, movie):# 获取用户和物品的嵌入向量user_emb = self.user_embedding(user)movie_emb = self.movie_embedding(movie)# 拼接用户和物品的嵌入向量x = torch.cat([user_emb, movie_emb], dim=-1)# 通过 MLP 计算预测评分output = self.mlp(x)return output.squeeze()  # 返回标量预测值

4. 训练模型

模型训练包括使用均方误差 (MSE) 损失函数,采用 Adam 优化器进行优化。我们在每个 epoch 后记录损失值,并使用 matplotlib 绘制损失曲线图。

def train_model(model, train_data, num_epochs=10, batch_size=64, learning_rate=0.001):criterion = nn.MSELoss()optimizer = optim.Adam(model.parameters(), lr=learning_rate)train_users = torch.tensor(train_data['user'].values, dtype=torch.long)train_movies = torch.tensor(train_data['movie'].values, dtype=torch.long)train_ratings = torch.tensor(train_data['rating'].values, dtype=torch.float32)model.train()# 用于记录每个epoch的损失epoch_losses = []for epoch in range(num_epochs):total_loss = 0for i in range(0, len(train_users), batch_size):user_batch = train_users[i:i+batch_size]movie_batch = train_movies[i:i+batch_size]rating_batch = train_ratings[i:i+batch_size]# 前向传播optimizer.zero_grad()predictions = model(user_batch, movie_batch)# 计算损失loss = criterion(predictions, rating_batch)# 反向传播loss.backward()optimizer.step()total_loss += loss.item()avg_loss = total_loss / len(train_users)epoch_losses.append(avg_loss)  # 记录损失值print(f"Epoch {epoch+1}/{num_epochs}, Loss: {avg_loss}")return epoch_losses

5. 模型评估

训练完成后,我们可以使用测试集来评估模型的表现,计算其均方误差(MSE)来衡量预测的准确性。

def evaluate_model(model, test_data):test_users = torch.tensor(test_data['user'].values, dtype=torch.long)test_movies = torch.tensor(test_data['movie'].values, dtype=torch.long)test_ratings = torch.tensor(test_data['rating'].values, dtype=torch.float32)model.eval()with torch.no_grad():predictions = model(test_users, test_movies)mse = nn.MSELoss()(predictions, test_ratings)print(f'Mean Squared Error on Test Set: {mse.item()}')

6. 推荐物品

一旦模型训练完成,我们可以使用它为用户推荐物品。模型将根据用户的历史评分为其推荐最相关的电影。

def recommend_for_user(model, user_id, num_movies, movie_map, top_n=10):user_tensor = torch.tensor([user_id], dtype=torch.long)all_movies = torch.tensor(range(num_movies), dtype=torch.long)model.eval()with torch.no_grad():scores = model(user_tensor.repeat(num_movies), all_movies)# 获取前 N 个物品recommended_movie_ids = scores.argsort(descending=True)[:top_n]recommended_movies = [list(movie_map.keys())[i.item()] for i in recommended_movie_ids]return recommended_movies

7. 完整示例

最后,将所有组件组合在一起,完成模型的训练和推荐过程:

if __name__ == "__main__":# 1. 加载数据train_data, test_data, num_users, num_movies = load_data('ratings.csv')# 2. 创建和训练模型model = NCF(num_users, num_movies)num_epochs = 10  # 训练的 epoch 数epoch_losses = train_model(model, train_data, num_epochs=num_epochs, batch_size=64, learning_rate=0.001)# 3. 测试模型evaluate_model(model, test_data)# 4. 推荐:为用户 1 推荐物品recommended_movies = recommend_for_user(model, 1, num_movies, dict(enumerate(range(num_movies))))print("Recommended movies for user 1:", recommended_movies)# 5. 绘制损失图表plt.plot(range(1, num_epochs + 1), epoch_losses, marker='o', color='b')plt.title('Training Loss Over Epochs')plt.xlabel('Epoch')plt.ylabel('Loss')plt.grid(True)plt.show()

8. 总结

在本教程中,我们使用 PyTorch 实现了一个基于神经网络的协同过滤推荐系统(NCF)。通过训练用户和物品的嵌入向量,模型能够学习到用户和物品之间的复杂关系,从而进行准确的评分预测和个性化推荐。我们还通过绘制损失曲线图,直观地展示了模型训练过程中的损失变化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3270.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot+Vue小区智享物业管理系统(高质量源码,可定制,提供文档,免费部署到本地)

作者简介:✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容:🌟Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

Json转换类型报错问题:java.lang.Integer cannot be cast to java.math.BigDecimal

Json转换类型报错问题:java.lang.Integer cannot be cast to java.math.BigDecimal 小坑规避指南 小坑规避指南 项目中遇到json格式转换成Map,已经定义了Map的key和value的类型,但是在遍历Map取值的时候出现了类型转换的报错问题&#xff08…

在Playwright中使用PO模式

1.新建项目 安装库 npm init -y npm install -D playwright npm install -D playwright/test npm install typescript ts-node types/node npx playwright install 项目目录 2.编写代码 package.json {"name": "pom_playwright","version": …

Web渗透测试之伪协议与SSRF服务器请求伪装结合? 能产生更多的效果

目录 ssrf漏洞利用{危害} 伪协议介绍 Gopher协议简介 SSRF攻击中常用协议 file协议 file协议数据格式: dict协议 dict协议数据格式: Gopher攻击Redis redis的协议数据流格式: 简单示例: 使用gopher协议写入定时任务 …

【论文阅读笔记】人工智能胃镜在盲区检测和自主采图中的应用

作者:李夏/吴练练/于红刚 小结 盲区检测的意思,实际上在算法的需求定义上,就是部位识别。   胃肠镜检查中,按照不同的规范,有不同应该观察到的地方。当医生知道哪些部位比较容易出病灶的情况下,就容易忽…

python之二维几何学习笔记

一、概要 资料来源《机械工程师Python编程:入门、实战与进阶》安琪儿索拉奥尔巴塞塔 2024年6月 点和向量:向量的缩放、范数、点乘、叉乘、旋转、平行、垂直、夹角直线和线段:线段中点、离线段最近的点、线段的交点、直线交点、线段的垂直平…

AI编程工具使用技巧——通义灵码

活动介绍通义灵码1. 理解通义灵码的基本概念示例代码生成 2. 使用明确的描述示例代码生成 3. 巧妙使用注释示例代码生成 4. 注意迭代与反馈原始代码反馈后生成优化代码 5. 结合生成的代码进行调试示例测试代码 其他功能定期优化生成的代码合作与分享结合其他工具 总结 活动介绍…

国产编辑器EverEdit - 复制为RTF

1 复制为RTF 1.1 应用背景 在写产品手册或者其他文档时,可能会用到要将产品代码以样例的形式放到文档中,一般的文本编辑器拷贝粘贴到Word中也就是普通文本,没有语法着色,这样感观上不是太好,为了让读者的感观更好一点…

Python毕业设计选题:基于python的酒店推荐系统_django+hadoop

开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 酒店客房管理 客房类型管理 客房预定管理 用户…

YoloV10改进策略:Neck层改进|EFC,北理提出的适用小目标的特征融合模块|即插即用

论文信息 论文题目:A Lightweight Fusion Strategy With Enhanced Interlayer Feature Correlation for Small Object Detection 论文链接:https://ieeexplore.ieee.org/abstract/document/10671587 官方github:https://github.com/nuliweixiao/EFC 研究贡献 为了解决上…

Re78 读论文:GPT-4 Technical Report

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:GPT-4 Technical Report 官方博客:GPT-4 | OpenAI appendix懒得看了。 文章目录 1. 模型训练过程心得2. scaling law3. 实验结果减少风险 1. 模型训练过程心得 模型结构还…

Linux中安装mysql8,很详细

一、查看系统glibc版本号,下载对应版本的MySQL 1、查看glibc版本号办法 方法一:使用ldd命令 在终端中输入ldd --version命令,然后按下回车键。这个命令会显示系统中安装的glibc版本号。例如,如果输出信息是ldd (GNU libc) 2.31&a…

springboot如何解析 Map 的泛型信息来确定要注入哪些 Bean?

我在学习策略模式的时候, 发现当SpringBoot注入一个Map的时候 ,value泛型为T,则注入后Spring会将实例化后的bean放入value ,key则为注入后bean的名字 Springboot如何解析Map中的Value Spring 通过解析 Map 的泛型信息来确定要注入哪些 Bean…

【NextJS】PostgreSQL 遇上 Prisma ORM

NextJS 数据库 之 遇上Prisma ORM 前言一、环境要求二、概念介绍1、Prisma Schema Language(PSL) 结构描述语言1.1 概念1.2 组成1.2.1 Data Source 数据源1.2.2 Generators 生成器1.2.3 Data Model Definition 数据模型定义字段(数据)类型和约束关系&…

一些常见的Java面试题及其答案

Java基础 1. Java中的基本数据类型有哪些? 答案:Java中的基本数据类型包括整数类型(byte、short、int、long)、浮点类型(float、double)、字符类型(char)和布尔类型(boo…

Vue2+OpenLayers实现折线绘制功能(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、初始变量 3.2、画一条折线 3.3、完整代码 四、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、代码实现 3.1、初始变量 关键代码: data() {return {map:null,// 定义路径坐…

【狂热算法篇】探秘图论之 Floyd 算法:解锁最短路径的神秘密码(通俗易懂版)

: 羑悻的小杀马特.-CSDN博客羑悻的小杀马特.擅长C/C题海汇总,AI学习,c的不归之路,等方面的知识,羑悻的小杀马特.关注算法,c,c语言,青少年编程领域.https://blog.csdn.net/2401_82648291?spm1010.2135.3001.5343 在本篇文章中,博主将带大家去学习所谓的…

【服务治理中间件】consul介绍和基本原理

目录 一、CAP定理 二、服务注册中心产品比较 三、Consul概述 3.1 什么是Consul 3.2 Consul架构 3.3 Consul的使用场景 3.4 Consul健康检查 四、部署consul集群 4.1 服务器部署规划 4.2 下载解压 4.3 启动consul 五、服务注册到consul 一、CAP定理 CAP定理&#xff…

Linux命令行工具-使用方法

参考资料 Linux网络命令:网络工具socat详解-CSDN博客 arm-linux-gnueabihf、aarch64-linux-gnu等ARM交叉编译GCC的区别_aarch64-elf-gcc aarch64-linux-gnu-CSDN博客 解决Linux内核问题实用技巧之-dev/mem的新玩法-腾讯云开发者社区-腾讯云 热爱学习地派大星-CS…

5-1 创建和打包AXI Interface IP

创建和打包AXI Interface IP的前流程和后流程 step 1 : 选择类型 1: 将当前的工程打包成IP 2: 将当前的BD工程打包成IP 3: 将指定的源码打包成IP 4: 创建一个新的AXI 接口IP 其中3和4是比较常用的,本次…