协同滤波模型的推荐算法(ACM暑校-案例学习)

2023-12-02 11:18

本文主要是介绍协同滤波模型的推荐算法(ACM暑校-案例学习),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于协同滤波的推荐技术可以细分为基于用户的协同过滤方法、基于产品的协同过滤方法、基于模型的协同过滤方法;本博文进行了一一测试。

1. 数据准备、评价指标

由于协同滤波模型需要用到用户的行为,这里选用MovieLen数据集进行测试研究。

MovieLen是明尼苏达大学计算机科学系GroupLens研究中心开发和维护的,也是最常用于测试协同滤波算法性能的公开数据集之一。Movielens提供了大量电影的用户评分。完整的版本包括超过了26000000的电影评分,他们来源于270000用户观看45000部电影的体会。GroupLens网站上提供的数据集不再提供用户人口统计信息。因此,这里使用Prajit-Datta在kaggle上提供的部分数据集。

  • 数据下载

下载地址:https://www.kaggle.com/prajitdatta/movielens-100k-dataset/data 

该数据集包括:1682部电影上943名用户的100000个评分(1-5)。每个用户至少为20部电影打分。该数据集也为用户提供简单的人口统计信息(年龄、性别、工作等)。这些数据是在1997年9月19日至1998年4月22日的七个月期间通过Movielens网站(movielens.umn.edu)收集的。此数据已被清除-从该数据集中删除了评分低于20或没有完整人口统计信息的用户。

  • 数据浏览

在解压文件中,只需要使用u.date/ u.user/ u.item三个文件。

① 查看用户图谱文件

import pandas as pd# load the u.user file into a dataframe
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
users = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.user', sep='|',names=u_cols, encoding='latin-1')
users.head()

可以看到,u.user文件中主要包含的用户图谱,如年龄,性别,职业,zip_code。

② 查看电影描述文件

i_cols = ['movie_id', 'title', 'release date', 'video release date', 'IMDB URL', 'unknow', 'Action', 'Adventure', 'Animation', 'Children\'s', 'Comedy', 'Crime', 'Documentary', 'Drama', 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War','Western']
movies = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.item',sep='|', names=i_cols, encoding='latin-1')
movies.head()

可以看出,u.item文件中主要提供了电影的名字、发行时间、IMDB URL和题材等信息。因为,本编博客主要研究的是协同滤波算法,因此,电影中的题材等是用不到的,只需要保留movie_id和title就好。

movies = movies[['movie_id', 'title']]
movies.head()

③ 查看用户对电影评分文件

r_cols = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_csv('C:/Users/Administrator/Desktop/RecoSys/data/movielens/u.data',sep='\t', names=r_cols, encoding='latin-1')
ratings.head()

  • 训练数据 training data & 测试数据 test data

DataFrame包含从1-5的用户对电影的评分。因此,可以将该问题建模为监督学习的实例,目的在于预测给定用户和电影的评分。虽然电影的分数只是1-5的五个离散值,其实质仍为回归问题。考虑用户对电影的真实评分是5:分类模型不能区分预测评分为1和4的情况。分类模型会将1-4的评分都视为错误分类。然而,回归模型却不是这样子,其对rating=4的惩罚远远大于rating=1的情况。

对于监督模型的学习,重要的一步在于训练集和测试集的划分。在本次试验中,用户评分数据中的75%用作模型训练,25%用于模型测试

from sklearn.model_selection import train_test_split
X = ratings.copy()
y = ratings['user_id']
# split into training and test datasets, stratified along user_id
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, stratify=y, random_state=42)>>> 
X_train.shape = (75000, 3)
X_test.shape = (25000, 3)
  • 评估方法

这里选用根均方差(RMSE=root-mean-square-error)对模型的推荐性能进行评估。其Python实现如下所示:

from sklearn.metrics import mean_squared_error
from numpy as npdef rmse(y_true, y_pred):return np.sqrt( mean_squared_error(y_true, y_pred) )# Function to compute the RMSE score obtained on the testing set by a model
def score(cf_model):# Construct a list of user-movie tuples from the testing datasetid_pairs = zip(X_test['user_id'], X_test['movie_id'])# Predict the rating for every user-movie tupley_pred = np.array([cf_model(user, movie) for (user, movie) in id_pairs])# Extract the actual ratings given by the users in the test datay_true = np.array(X_test['rating'])# Return the final RMSE scorereturn rmse(y_true, y_pred)

2. 基于用户的协同过滤推荐算法实例 Users-based

基于用户的协同推荐算法把主要的研究精力放在用户角度,实质上就是具有相同兴趣的用户群体进行聚类,然后对相同类群的用户进行产品推荐。核心在于对高度稀疏的用户-产品矩阵进行预测和填充。PANDAS提供了一个非常好用的函数pivot_table去构造rating矩阵:

# Build the ratings matrix using pivot_table function
r_matrix = X_train.pivot_table(values='rating', index='user_id', columns='movie_id')
r_matrix.head(5)

该矩阵就是推荐领域最最重要的了:①用户-产品矩阵是高度稀疏的;②实际应用过程中,从用户和产品两个维度考虑,评分矩阵是非常非常巨大的。

  • 均值Mean角度初步考虑

首先可以构建一个最简单的协同过滤算法,只需输入用户ID和电影ID,并输出所有看过的用户对该电影的平均评分。用户之间没有区别。换言之,每个用户的评分被赋予相等的权重。其中,有一种完全可能异常情况:有些电影只能在测试数据集进行访问,而在训练数据集不存在。该情况下,我们直接设置一个baseline,将其默认赋值为3.0。

# User Based Collaborative Filter using MEan Rating
def cf_user_mean(user_id, movie_id):# Check if movie_id exists in r_matrixif movie_id in r_matrix:# Compute the mean of all the ratings given to the moviemean_rating = r_matrix[movie_id].mean()else:# Default to a rating of 3.0 in the absence of any informationmean_rating = 3.0return mean_rating# Compute RMSE for the Mean model
score(cf_user_mean)>>> 1.0234701463131335

该方法仅仅适合讨论研究,是没有实际应用价值的:一方面,用户对产品的评分肯定会有偏好;另一方面,大部分少数群体的兴趣没有被认真关注。一种合适的改进方法是采用加权平均weighted mean。

  • 加权均值weighted mean角度考虑

在前面的模型中,我们为每一个用户分配了等同的权重。然而,与普通用户相比,对那些评分与所讨论问题相似的用户给予更多的关注。因此,在前面的模型中,比较合适的方案是为每一个用户分配一个合适的权重系数。数学可以表示为:

其中,r(u,m)表示为用户u对电影m的评分。对于相似度测量,同样采用余弦距离。

数据处理:将rating表中的NAN替换成0,然后用scikit-learn中的cosine_similarity函数进行处理。

r_matrix_dummy = r_matrix.copy().fillna(0)
r_matrix_dummy.head()
r_matrix_dummy.shape>>> (943, 1647)

from sklearn.metrics.pairwise import cosine_similarity
cosine_sim = cosine_similarity(r_matrix_dummy, r_matrix_dummy)
cosine_sim.shape>>> (943, 943)
# Convert into pandas dataframe
cosine_sim = pd.DataFrame(cosine_sim, index=r_matrix.index, columns=r_matrix.index)
cosine_sim.head()

# User Based Collabrative Filter using Weighted Mean Ratings
def cf_user_wmean(user_id, movie_id):# Check if movie_id exists in r_matrixif movie_id in r_matrix:sim_scores = cosine_sim[user_id]m_ratings = r_matrix[movie_id]idx = m_ratings[m_ratings.isnull()].indexm_ratings = m_ratings.dropna()sim_scores = sim_scores.drop(idx)wmean_rating = np.dot(sim_scores, m_ratings)/ sim_scores.sum()else:#Default to a rating of 3.0 in the absence of any informationwmean_rating = 3.0return wmean_ratingscore(cf_user_wmean)>>> 1.0174483808407588
  • 用户图谱demographics角度考虑

这是一种相对而言更加精细的处理方式。该算法的核心思想是,具有相同图谱的用户倾向于有相似的品味。因此,其有效性取决于这样的假设:女性、青少年或来自同一地区的人在电影选择时会有相同的品味。与前面的模型不同,该种算法不考虑用户对特定电影的评分。相反,算法只关注那些符合特定人群的用户。

3. 基于产品的协同过滤推荐算法实例 Items-based

Items-based和User-based方法本质是一致的,就相当于将第二节中的User变成Item。在基于产品的协同过滤中,我们计算库存中产品的成对相似性。然后,根据user_id和movie_id,计算用户对其所有评分产品的加权平均值。这个模型背后的基本思想是:一个特定的用户可能会对相似的两个产品有相似的评分。

4. 基于模型的方法 Model-based

到目前为止,上面的协同过滤算法被称为memory-based的过滤。因为他们只利用相似性度量来得出结果,并没有从数据中学习任何参数,或者为数据分配类/集群。并没有用到机械学习算法的威力。

  • 以聚类为核心的协同过滤算法 - Clustering

weighted mean-based 的滤波算法,考虑到了每一位用户的评分,最后进行加权;相反,demographic-based滤波算法仅仅考虑了‘某个圈子’的用户,最后进行平均。通常来说,weighted mean-based取得的结果会好于demographic-based,因为考虑的相对来说更广一点。但是,这两种方法仅仅用到了最直接、最粗浅的信息,一种解决方案是进行多维度用户刻画,进行利用机器学习算法解决高纬度数据处理问题。简单说,精准的推荐结果不一定唯一依赖考虑所有用户的感受!

demographic-based算法的缺点来源于他的假设:来自某个相同图谱的用户具有相同的想法和评分。这种极端的思考模式造成了算法的粗浅。Clustering-based方法,如k-means, 就是为了改善这种情况:将用户分组到一个群集中,然后在预测评分时只考虑来自同一个群集中的用户。下面以KNN-based clustering为例,构建相关的协同过滤算法。步骤如下 ①找出与用户u对电影m评分最相似的k个最近邻;②输出k个用户对电影m评分的平均值。

可以直接采用Python中的surprise(Simple Python Recommandation System Engine)库实现。Windows 平台下下载方式为:pip install scikit-surprise.

# Import the required classes and methods from the surprise library
from surprise import Reader, Dataset, KNNBasic, evaluate
# Define a Reader object - The Reader object helps in parsing the file or dataframe containing ratings
reader = Reader()
# Create the dataset to be used for building the filter
data = Dataset.load_from_df(ratings, reader)
# Define the algorithm object
knn = KNNBasic()
# Evaluate the performance in terms of RMSE
evaluate(knn, data, measures=['RMSE'])

从输出结果中,我们能够看出来。surprise库将所有的评分数据划分为5个文件包,其中4个文件包用于算法训练,第5个文件包用于模型测试。这样的过程重复了5次。

  • 监督学习和降维方法

对于mxn大小的评分矩阵,每一行代表m个用户中的一个对所有电影的评分;每一列代表n个电影中的一个接受所有用户的评分。前面已经看到了,该评分矩阵是非常稀疏的。通过监督学习的方法,我们可以尝试将这个高度稀疏的矩阵补全。

最简单的思考是,我们可以利用mx(n-1)的评分矩阵进行模型的监督训练,然后对m*1的未知评分进行预测。如此重复n次,那么评分矩阵将有可能完全被填充。理想是丰满的,现实的骨感的。因为,一开始我们用的mx(n-1)的模型训练矩阵就是高度稀疏的~~~(目前也没办法解决这个事,工程上的一种处理手段是用所属的列的均值或中值来填充缺失值,但是考虑到rating矩阵高达90%的系数,计算的均值和中位数一定会引进很大的偏差;同时降维技术,PCA/SVD也不能处理如此稀疏的情况

可以借鉴的一种思路是,Simon Funk在处理Netflix Problem时,将mx(n-1)的模型训练矩阵压缩到了更低的维度mxd (d << n),这种处理方式称为SVD-like,其实效果也比较一般。

  • 火极一时的推荐算法-奇异值分解 Singular-value decomposition

本质上,奇异值分解是一种矩阵因子技术,其输入为大型矩阵A,输出为小矩阵U和V。其中,Σ为对角矩阵用于吃调整数据的尺度。对于U矩阵,其实质表征的是用户主成分,英文专有名词对应user-embedding矩阵;V矩阵,其实质表征的是产品主成分,英文专有名词对应item-embedding矩阵。

和大多数机器学习算法一样,传统的SVD矩阵对极其稀疏的评分矩阵是没有效益的。然而,SimonFunk找到了解决这个问题的方法,他的解决方案(SVD++)促成了了推荐系统领域最著名的算法之一。该方法可以利用高度稀疏的评分矩阵A,生成两个非常稠密的user-embedding矩阵U和item-embedding矩阵V。这些稠密的矩阵(U,V)直接解决了原始数据A高度稀疏的难题。surprise库也集成了该算法,调用如下:

#Import SVD
from surprise import SVD
#Define the SVD algorithm object
svd = SVD()
#Evaluate the performance in terms of RMSE
evaluate(svd, data, measures=['RMSE'])

 

这篇关于协同滤波模型的推荐算法(ACM暑校-案例学习)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/445133

相关文章

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

shell脚本自动删除30天以前的文件(最新推荐)

《shell脚本自动删除30天以前的文件(最新推荐)》该文章介绍了如何使用Shell脚本自动删除指定目录下30天以前的文件,并通过crontab设置定时任务,此外,还提供了如何使用Shell脚本删除E... 目录shell脚本自动删除30天以前的文件linux按照日期定时删除elasticsearch索引s

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee