推荐系统-基于用户的最近邻协同过滤算法(MovieLens数据集)

本文采用用户最近邻算法对MovieLens数据集进行分析,通过计算用户间的相似性,预测用户对未评分电影的偏好,最终推荐高预测评分的电影。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于用户的最近邻算法(User-Based Neighbor Algorithms),是一种非概率性的协同过滤算法,也是推荐系统中最最古老,最著名的算法。

我们称那些兴趣相似的用户为邻居,如果用户n相似于用户u,我们就说n是u的一个邻居。起初算法,对于未知目标的预测是根据该用户的相似用户的评分作出预测的。

本文中运用的是MovieLens数据集,关于这个数据集的介绍可以参看http://www.grouplens.org/node/73

算法主要包括两个步骤:

(1). 找到与用户兴趣相似的用户(邻居)集合。

(2). 根据这个邻居集合,计算出该用户对未曾评分的物品的预测评分。并列出获得最高的预测评分N项物品,推荐给该用户。


本文,用皮尔逊相关系数(pearon correlation coefficient)计算用户之间的相似性。如formula1

计算用户u对物品i的预测值,使用的formula2 


formula1:

   


formula-2:



具体实现代码如下:

[python]  view plain copy print ?
  1. ''''' 
  2. Created on Nov 17, 2012 
  3.  
  4.  
  5. @Author: Dennis Wu 
  6. @E-mail: hansel.zh@gmail.com 
  7. @Homepage: http://blog.youkuaiyun.com/wuzh670 
  8.  
  9.  
  10. Data set download from : http://www.grouplens.org/system/files/ml-100k.zip 
  11.  
  12.  
  13. MovieLens data sets were collected by the GroupLens Research Project 
  14. at the University of Minnesota.The data was collected through the MovieLens web site 
  15. (movielens.umn.edu) during the seven-month period from September 19th, 
  16. 1997 through April 22nd, 1998. 
  17.  
  18.  
  19. This data set consists of: 
  20.     * 100,000 ratings (1-5) from 943 users on 1682 movies. 
  21.     * Each user has rated at least 20 movies. 
  22.     * Simple demographic info for the users  
  23.  
  24.  
  25. u.data     -- The full u data set, 100000 ratings by 943 users on 1682 items. 
  26.               Each user has rated at least 20 movies.  Users and items are 
  27.               numbered consecutively from 1.  The data is randomly 
  28.               ordered. This is a tab separated list of 
  29.               user id | item id | rating | timestamp. 
  30.               The time stamps are unix seconds since 1/1/1970 UTC 
  31. u.item     -- Information about the items (movies); this is a tab separated 
  32.               list of 
  33.               movie id | movie title | release date | video release date | 
  34.               IMDb URL | unknown | Action | Adventure | Animation | 
  35.               Children's | Comedy | Crime | Documentary | Drama | Fantasy | 
  36.               Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi | 
  37.               Thriller | War | Western | 
  38.               The last 19 fields are the genres, a 1 indicates the movie 
  39.               is of that genre, a 0 indicates it is not; movies can be in 
  40.               several genres at once. 
  41.               The movie ids are the ones used in the u.data data set. 
  42. '''  
  43.   
  44.   
  45. from operator import itemgetter, attrgetter  
  46. from math import sqrt  
  47.   
  48.   
  49. def load_data():  
  50.       
  51.     filename_user_movie = 'data/u.data'  
  52.     filename_movieInfo = 'data/u.item'  
  53.   
  54.   
  55.     user_movie = {}  
  56.     for line in open(filename_user_movie):  
  57.         (userId, itemId, rating, timestamp) = line.strip().split('\t')  
  58.         user_movie.setdefault(userId,{})  
  59.         user_movie[userId][itemId] = float(rating)  
  60.           
  61.     movies = {}  
  62.     for line in open(filename_movieInfo):  
  63.         (movieId, movieTitle) = line.split('|')[0:2]  
  64.         movies[movieId] = movieTitle  
  65.       
  66.     return user_movie, movies  
  67.   
  68.   
  69. def average_rating(user):  
  70.     average = 0  
  71.     for u in user_movie[user].keys():  
  72.         average += user_movie[user][u]  
  73.     average = average * 1.0 / len(user_movie[user].keys())  
  74.     return average  
  75.   
  76.   
  77. def calUserSim(user_movie):  
  78.   
  79.   
  80.     # build inverse table for movie_user  
  81.     movie_user = {}  
  82.     for ukey in user_movie.keys():  
  83.         for mkey in user_movie[ukey].keys():  
  84.             if mkey not in movie_user:  
  85.                 movie_user[mkey] = []  
  86.             movie_user[mkey].append(ukey)  
  87.   
  88.   
  89.     # calculated co-rated movies between users  
  90.     C = {}  
  91.     for movie, users in movie_user.items():  
  92.         for u in users:  
  93.             C.setdefault(u,{})  
  94.             for n in users:  
  95.                 if u == n:  
  96.                     continue  
  97.                 C[u].setdefault(n,[])  
  98.                 C[u][n].append(movie)  
  99.                   
  100.   
  101.   
  102.     # calculate user similarity (perason correlation)  
  103.     userSim = {}  
  104.     for u in C.keys():  
  105.           
  106.         for n in C[u].keys():  
  107.               
  108.             userSim.setdefault(u,{})  
  109.             userSim[u].setdefault(n,0)  
  110.           
  111.             average_u_rate = average_rating(u)  
  112.             average_n_rate = average_rating(n)  
  113.               
  114.             part1 = 0  
  115.             part2 = 0  
  116.             part3 = 0  
  117.             for m in C[u][n]:  
  118.   
  119.   
  120.                 part1 += (user_movie[u][m]-average_u_rate)*(user_movie[n][m]-average_n_rate)*1.0  
  121.                 part2 += pow(user_movie[u][m]-average_u_rate, 2)*1.0  
  122.                 part3 += pow(user_movie[n][m]-average_n_rate, 2)*1.0  
  123.                   
  124.             part2 = sqrt(part2)  
  125.             part3 = sqrt(part3)  
  126.             if part2 == 0:  
  127.                 part2 = 0.001  
  128.             if part3 == 0:  
  129.                 part3 = 0.001   
  130.             userSim[u][n] = part1 / (part2 * part3)     
  131.     return userSim  
  132.   
  133.   
  134. def getRecommendations(user, user_movie, movies, userSim, N):  
  135.     pred = {}  
  136.     interacted_items = user_movie[user].keys()  
  137.     average_u_rate = average_rating(user)  
  138.     sumUserSim = 0  
  139.     for n, nuw in sorted(userSim[user].items(),key=itemgetter(1),reverse=True)[0:N]:  
  140.         average_n_rate = average_rating(n)  
  141.         for i, nrating in user_movie[n].items():  
  142.             # filter movies user interacted before  
  143.             if i in interacted_items:  
  144.                 continue  
  145.             pred.setdefault(i,0)  
  146.             pred[i] += nuw * (nrating - average_n_rate)  
  147.         sumUserSim += nuw  
  148.   
  149.   
  150.     for i, rating in pred.items():  
  151.         pred[i] = average_u_rate + (pred[i]*1.0) / sumUserSim  
  152.           
  153.     # top-10 pred  
  154.     pred = sorted(pred.items(), key=itemgetter(1), reverse=True)[0:10]  
  155.     return pred    
  156.   
  157.   
  158. if __name__ == "__main__":  
  159.   
  160.   
  161.   
  162.   
  163.     # load data  
  164.     user_movie, movies = load_data()  
  165.   
  166.   
  167.     # Calculate user similarity  
  168.     userSim = calUserSim(user_movie)  
  169.   
  170.   
  171.     # Recommend  
  172.     pred = getRecommendations('182', user_movie, movies, userSim, 20)  
  173.   
  174.   
  175.     # display recommend result (top-10 results)  
  176.     for i, rating in pred:  
  177.         print 'film: %s,  rating: %s' % (movies[i], rating)  
  178.       
  179.       
  180.       

References

1. J.Ben Schafer, Dan Frankowski, Jon Herlocker, and Shilad Sen : Collaborative Filtering Recommender System 

2. 项亮: 推荐系统实践 2012

协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值