推荐系统Python代码实现

协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的

信息来推荐相应的产品给客户,是一种智能的生活方式。之所以交协同过滤,是因为在实现过滤推荐的时候是根据

其他人的行为来做预测的,基于相似用户的喜好来实现用户的喜好预测。

简要介绍:         

通过找到兴趣相投,或者有共同经验的群体,来向用户推荐感兴趣的信息。

举例,如何协同过滤,来对用户A进行电影推荐?

答:简要步骤如下

找到用户A(user_id_1)的兴趣爱好

找到与用户A(user_id_1)具有相同电影兴趣爱好的用户群体集合Set<user_id>

找到该群体喜欢的电影集合Set<movie_id>

将这些电影Set<Movie_id>推荐给用户A(user_id_1)

具体实施步骤如何?

答:简要步骤如下

(1)画一个大表格,横坐标是所有的movie_id,纵坐标所有的user_id,交叉处代表这个用户喜爱这部电影

Move_id_1

Move_id_2

Move_id_3

Move_id_4

Move_id_5

……

Move_id_110w

User_id_1

1

1

1

User_id_2

1

1

1

1

User_id_3

1

1

1

1

………….

………….

User_id_10w

1

1

1

如上表:

横坐标,假设有10w部电影,所以横坐标有10w个movie_id,数据来源自数据库

纵坐标,假设有100w个用户,所以纵坐标有100w个user_id,数据也来自数据库

交叉处,“1”代表用户喜爱这部电影,数据来自日志

画外音:什么是“喜欢”,需要人为定义,例如浏览过,查找过,点赞过,反正日志里有这些数据

(2)找到用户A(user_id_1)的兴趣爱好

如上表,可以看到,用户A喜欢电影{m1, m2, m3}

(3)找到与用户A(user_id_1)具有相同电影兴趣爱好的用户群体集合Set<user_id>

如上表,可以看到,喜欢{m1, m2, m3}的用户,除了u1,还有{u2, u3}

(4)找到该群体喜欢的电影集合Set<movie_id>

如上表,具备相同喜好的用户群里{u2, u3},还喜好的电影集合是{m4, m5}

画外音:“协同”就体现在这里。

(5)未来用户A(use_id_1)来访问网站时,要推荐电影{m4, m5}给ta。

具体实现步骤:

第一步:计算两者之间的相似度

                       通常会先把二维表格绘制在一个图中总,每个用户数据表示一个点。

                       度量相似度计算的方法:a.曼哈顿距离计算(计算迅速,节省时间)

                                                               b.欧氏距离计算(计算两个点之间的直线距离)

数据预处理:

去网站:https://grouplens.org/datasets/movielens/           下载movieLen数据集

              或者

                      ml-latest-small(1MB): http://files.grouplens.org/datasets/movielens/ml-latest-small.zip
                      ml-latest(234.2MB): http://files.grouplens.org/datasets/movielens/ml-latest.zip

解压读取movies.csv和ratings.csv文件

两个文件的数据格式如下:


  
  
  1. 通过如下程序提取数据:
  2. #!/usr/bin/env python
  3. # encoding: utf-8
  4. """
  5. @Company:华中科技大学电气学院聚变与等离子研究所
  6. @version: V1.0
  7. @author: YEXIN
  8. @contact: [email protected] or [email protected] 2018--2020
  9. @software: PyCharm
  10. @file: recommend.py
  11. @time: 2018/8/19 17:32
  12. @Desc:读取用户的电影数据和评分数据
  13. """
  14. import pandas as pd
  15. movies = pd.read_csv( "E:\PycharmWorks\ML\CollaborativeFiltering\ml-latest\movies.csv")
  16. ratings = pd.read_csv( "E:\PycharmWorks\ML\CollaborativeFiltering\ml-latest\\ratings.csv") ##这里注意如果路径的中文件名开头是r,要转义。
  17. data = pd.merge(movies,ratings,on = 'movieId') #通过两数据框之间的movieId连接
  18. data[[ 'userId', 'rating', 'movieId', 'title']].sort_values( 'userId').to_csv( 'E:\PycharmWorks\ML\CollaborativeFiltering\ml-latest\data.csv',index= False)

结果:

采用python字典来表示每位用户评论的电影和评分
  
  

  
  
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. @Company:华中科技大学电气学院聚变与等离子研究所
  5. @version: V1.0
  6. @author: YEXIN
  7. @contact: [email protected] or [email protected] 2018--2020
  8. @software: PyCharm
  9. @file: movie_rating_user.py
  10. @time: 2018/8/19 17:50
  11. @Desc:采用python字典来表示每位用户评论的电影和评分
  12. """
  13. file = open( "E:\PycharmWorks\ML\CollaborativeFiltering\ml-latest\data.csv", 'r', encoding= 'UTF-8') #记得读取文件时加‘r’, encoding='UTF-8'
  14. ##读取data.csv中每行中除了名字的数据
  15. data = {} ##存放每位用户评论的电影和评分
  16. for line in file.readlines()[ 1: 100]:
  17. #注意这里不是readline()
  18. line = line.strip().split( ',')
  19. #如果字典中没有某位用户,则使用用户ID来创建这位用户
  20. if not line[ 0] in data.keys():
  21. data[line[ 0]] = {line[ 3]:line[ 1]}
  22. #否则直接添加以该用户ID为key字典中
  23. else:
  24. data[line[ 0]][line[ 3]] = line[ 1]
  25. print(data)

结果(部分):

计算任何两位用户之间的相似度,由于每位用户评论的电影不完全一样,所以兽先要找到两位用户共同评论过的电影

然后计算两者之间的欧式距离,最后算出两者之间的相似度。


  
  
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. @Company:华中科技大学电气学院聚变与等离子研究所
  5. @version: V1.0
  6. @author: YEXIN
  7. @contact: [email protected] or [email protected] 2018--2020
  8. @software: PyCharm
  9. @file: movie_rating_user.py
  10. @time: 2018/8/19 17:50
  11. @Desc:采用python字典来表示每位用户评论的电影和评分
  12. """
  13. file = open( "E:\PycharmWorks\ML\CollaborativeFiltering\ml-latest\data.csv", 'r', encoding= 'UTF-8') #记得读取文件时加‘r’, encoding='UTF-8'
  14. ##读取data.csv中每行中除了名字的数据
  15. data = {} ##存放每位用户评论的电影和评分
  16. for line in file.readlines()[ 1: 100]:
  17. #注意这里不是readline()
  18. line = line.strip().split( ',')
  19. #如果字典中没有某位用户,则使用用户ID来创建这位用户
  20. if not line[ 0] in data.keys():
  21. data[line[ 0]] = {line[ 3]:line[ 1]}
  22. #否则直接添加以该用户ID为key字典中
  23. else:
  24. data[line[ 0]][line[ 3]] = line[ 1]
  25. #print(data)
  26. """计算任何两位用户之间的相似度,由于每位用户评论的电影不完全一样,所以兽先要找到两位用户共同评论过的电影
  27. 然后计算两者之间的欧式距离,最后算出两者之间的相似度
  28. """
  29. from math import *
  30. def Euclidean(user1,user2):
  31. #取出两位用户评论过的电影和评分
  32. user1_data=data[user1]
  33. user2_data=data[user2]
  34. distance = 0
  35. #找到两位用户都评论过的电影,并计算欧式距离
  36. for key in user1_data.keys():
  37. if key in user2_data.keys():
  38. #注意,distance越大表示两者越相似
  39. distance += pow(float(user1_data[key])-float(user2_data[key]), 2)
  40. return 1/( 1+sqrt(distance)) #这里返回值越小,相似度越大
  41. #计算某个用户与其他用户的相似度
  42. def top10_simliar(userID):
  43. res = []
  44. for userid in data.keys():
  45. #排除与自己计算相似度
  46. if not userid == userID:
  47. simliar = Euclidean(userID,userid)
  48. res.append((userid,simliar))
  49. res.sort(key= lambda val:val[ 1])
  50. return res[: 4]
  51. RES = top10_simliar( '1')
  52. print(RES)

用户之间相似度结果:0表示两位的影评几乎一样,1表示没有共同的影评

根据相似度来推荐用户:


  
  
  1. ########################################################################
  2. #根据用户推荐电影给其他人
  3. def recommend(user):
  4. #相似度最高的用户
  5. top_sim_user = top10_simliar(user)[ 0][ 0]
  6. #相似度最高的用户的观影记录
  7. items = data[top_sim_user]
  8. recommendations = []
  9. #筛选出该用户未观看的电影并添加到列表中
  10. for item in items.keys():
  11. if item not in data[user].keys():
  12. recommendations.append((item,items[item]))
  13. recommendations.sort(key= lambda val:val[ 1],reverse= True) #按照评分排序
  14. #返回评分最高的10部电影
  15. return recommendations[: 10]
  16. Recommendations = recommend( '1')
  17. print(Recommendations)

推荐结果:

==================================================================================

但有时我们会碰到因为两个用户之间数据由于数据膨胀,一方数据大,一方数据小,但是两者称明显的线性关系

我们引入Pearson相关系数来衡量两个变量之间的线性相关性。

Pearson:-1~1   -1:完全负相关  1:完全正相关  0:不相关              

相关系数 0.8-1.0 极强相关

0.6-0.8 强相关

0.4-0.6 中等程度相关

0.2-0.4 弱相关

0.0-0.2 极弱相关或无相关

公式:

python代码:


  
  
  1. #########################################################################
  2. ##计算两用户之间的Pearson相关系数
  3. def pearson_sim(user1,user2):
  4. # 取出两位用户评论过的电影和评分
  5. user1_data = data[user1]
  6. user2_data = data[user2]
  7. distance = 0
  8. common = {}
  9. # 找到两位用户都评论过的电影
  10. for key in user1_data.keys():
  11. if key in user2_data.keys():
  12. common[key] = 1
  13. if len(common) == 0:
  14. return 0 #如果没有共同评论过的电影,则返回0
  15. n = len(common) #共同电影数目
  16. print(n,common)
  17. ##计算评分和
  18. sum1 = sum([float(user1_data[movie]) for movie in common])
  19. sum2 = sum([float(user2_data[movie]) for movie in common])
  20. ##计算评分平方和
  21. sum1Sq = sum([pow(float(user1_data[movie]), 2) for movie in common])
  22. sum2Sq = sum([pow(float(user2_data[movie]), 2) for movie in common])
  23. ##计算乘积和
  24. PSum = sum([float(user1_data[it])*float(user2_data[it]) for it in common])
  25. ##计算相关系数
  26. num = PSum - (sum1*sum2/n)
  27. den = sqrt((sum1Sq-pow(sum1, 2)/n)*(sum2Sq-pow(sum2, 2)/n))
  28. if den == 0:
  29. return 0
  30. r = num/den
  31. return r
  32. R = pearson_sim( '1', '3')
  33. print(R)

pearson系数结果:

注意:通过Pearson系数得到用户的相似度和通过欧式距离得到结果可能不一样

猜你喜欢

转载自blog.csdn.net/xiaozhaoshigedasb/article/details/85810467
今日推荐