基于用户的最近邻算法(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:

具体实现代码如下:

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

References

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

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

基于用户的最近邻协同过滤算法(MovieLens数据集)的更多相关文章

  1. SVD++:推荐系统的基于矩阵分解的协同过滤算法的提高

    1.背景知识 在讲SVD++之前,我还是想先回到基于物品相似的协同过滤算法.这个算法基本思想是找出一个用户有过正反馈的物品的相似的物品来给其作为推荐.其公式为:

  2. 基于用户相似性的协同过滤——Python实现

    代码基本来自项亮的<推荐系统实践>,把书上的伪代码具体实现,还参考了https://www.douban.com/note/336280497/ 还可以加入对用户相似性的归一化操作,效果会 ...

  3. 【机器学习笔记一】协同过滤算法 - ALS

    参考资料 [1]<Spark MLlib 机器学习实践> [2]http://blog.csdn.net/u011239443/article/details/51752904 [3]线性 ...

  4. Slope one—个性化推荐中最简洁的协同过滤算法

    Slope One 是一系列应用于 协同过滤的算法的统称.由 Daniel Lemire和Anna Maclachlan于2005年发表的论文中提出. [1]有争议的是,该算法堪称基于项目评价的non ...

  5. Mahout实现基于用户的协同过滤算法

    Mahout中对协同过滤算法进行了封装,看一个简单的基于用户的协同过滤算法. 基于用户:通过用户对物品的偏好程度来计算出用户的在喜好上的近邻,从而根据近邻的喜好推测出用户的喜好并推荐. 图片来源 程序 ...

  6. 基于Python协同过滤算法的认识

    Contents    1. 协同过滤的简介    2. 协同过滤的核心    3. 协同过滤的实现    4. 协同过滤的应用 1. 协同过滤的简介 关于协同过滤的一个最经典的例子就是看电影,有时候 ...

  7. Spark 基于物品的协同过滤算法实现

    J由于 Spark MLlib 中协同过滤算法只提供了基于模型的协同过滤算法,在网上也没有找到有很好的实现,所以尝试自己实现基于物品的协同过滤算法(使用余弦相似度距离) 算法介绍 基于物品的协同过滤算 ...

  8. 基于物品的协同过滤算法(ItemCF)

    最近在学习使用阿里云的推荐引擎时,在使用的过程中用到很多推荐算法,所以就研究了一下,这里主要介绍一种推荐算法—基于物品的协同过滤算法.ItemCF算法不是根据物品内容的属性计算物品之间的相似度,而是通 ...

  9. 使用Python3.7配合协同过滤算法(base on user,基于人)构建一套简单的精准推荐系统(个性化推荐)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_136 时至2020年,个性化推荐可谓风生水起,Youtube,Netflix,甚至于Pornhub,这些在互联网上叱咤风云的流媒体 ...

随机推荐

  1. arm-linux-copydump 的使用

    生成可以执行的 2 进制代码 [arm@localhost gcc]#arm­linux­copydump ­O binary hello hello.bin

  2. log-slave-updates参数

    从库做为其他从库的主库时 log-slave-updates参数是必须要添加的,因为从库要作为其他从库的主库,必须添加该参数.该参数就是为了让从库从主库复制数据时可以写入到binlog日志,为什么要用 ...

  3. 既然 start() 方法会调用 run() 方法,为什么我们调用 start() 方法,而不直接调用 run() 方法?

    当你调用 start() 方法时,它会新建一个线程然后执行 run() 方法中的代码.如果直接调用 run() 方法,并不会创建新线程,方法中的代码会在当前调用者的线程中执行

  4. [转]Redis实现缓存,你应该懂的哪些思路!

    场景一:类似于微博,实现关注和被关注功能. 思路: 对每个用户使用两个集合类型键,用来存储关注别人的用户和被该用户关注的用户.当用户A关注用户B的时候,执行两步操作: sadd user:A B sa ...

  5. CSS3——2D变形和3D变形

    2D变形(CSS3) transform transform是CSS3中具有颠覆性的特征之一,可以实现元素的位移.旋转.倾斜.缩放,甚至支持矩阵方式,配合过渡和即将学习的动画知识,可以取代大量之前只能 ...

  6. 应用上云新模式,Aliware 全家桶亮相杭州云栖大会

    全面上云带来的变化,不仅是上云企业数量上的攀升,也是企业对云的使用方式的转变,越来越多的企业用户不仅将云作为一种弹性资源,更是开始在云上部署架构和应用,借助 Serverless 等技术,开发人员只需 ...

  7. thinkphp 伪静态

    URL伪静态通常是为了满足更好的SEO效果,ThinkPHP支持伪静态URL设置,可以通过设置URL_HTML_SUFFIX参数随意在URL的最后增加你想要的静态后缀,而不会影响当前操作的正常执行.例 ...

  8. 概率dp——逆推期望+循环迭代zoj3329

    首先要推出dp[i]的期望方程,会发现每一项都和dp[0]相关, 那我们将dp[i]设为和dp[0]有关的式子dp[i]=a[i]*dp[0]+b[i],然后再回代到原来的期望方程里 然后进行整理,可 ...

  9. 线性dp——cf1067A

    考虑三种情况,刷表dp+前缀和预处理即可 #include<bits/stdc++.h> using namespace std; ; ],f[][][],ans,s; int main( ...

  10. duilib教程之duilib入门简明教程9.界面布局

    上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayout,这样 ...