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

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

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


formula-2:

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



具体实现代码如下:

[python]  view plain copy print ?
  1. ''''' 
  2. Created on Nov 17, 2012 
  3.  
  4.  
  5. @Author: Dennis Wu 
  6. @E-mail: [email protected] 
  7. @Homepage: http://blog.csdn.net/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

你可能感兴趣的:(推荐系统)