欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python实现协同过滤推荐

程序员文章站 2022-08-06 20:33:04
协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的信息来推荐相应的产品给客户,是一种智能的生活方式。之所以叫协同过滤,是因为在实现过滤推荐的时候是根据其他人的行为来做预测的,基于相似用户的喜好来实现用户的喜好预测。简要介绍: 通过找到兴趣相投,或者有共同经验的群体,来向用户推荐感兴趣的信息。举例,如何协同过滤,来对用户A进行电影推荐?答:简要步骤如下找到用户A(user_id_1)的兴趣爱好找到与用户A(user_id_1)......

协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的信息来推荐相应的产品给客户,是一种智能的生活方式。之所以叫协同过滤,是因为在实现过滤推荐的时候是根据其他人的行为来做预测的,基于相似用户的喜好来实现用户的喜好预测。

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

举例,如何协同过滤,来对用户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,交叉处代表这个用户喜爱这部电影

Python实现协同过滤推荐

如上表:

横坐标,假设有10w部电影,所以横坐标有10w个movie_id,数据来源自数据库
纵坐标,假设有100w个用户,所以纵坐标有100w个user_id,数据也来自数据库
交叉处,“1”代表用户喜爱这部电影,数据来自日志
画外音:什么是“喜欢”,需要人为定义,例如浏览过,查找过,点赞过,反正日志里有这些数据

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

Python实现协同过滤推荐


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

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

Python实现协同过滤推荐


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

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

Python实现协同过滤推荐


如上表,具备相同喜好的用户群里{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文件

通过如下程序提取数据:

# -*- coding:utf-8 -*-

import pandas as pd

movies = pd.read_csv(r'E:\PycharmProjects\devTest\data\movies.csv')
ratings = pd.read_csv(r'E:\PycharmProjects\devTest\data\ratings.csv')
data = pd.merge(movies,ratings,on='MovieID')
data[['UserID','Rating','MovieID','Title']].sort_values('UserID').to_csv(r'E:\PycharmProjects\devTest\data\data.csv',index=False,header=None) 

推荐代码:

# -*- coding:utf-8 -*-

from math import sqrt

data = {}
with open(r'E:\PycharmProjects\devTest\data\data.csv', 'r', encoding='UTF-8') as fi:
    for line in fi:
        item = line.strip().split(',')
        if not item[0] in data.keys():
            data[item[0]] = {item[3]: item[1]}
        else:
            data[item[0]][item[3]] = item[1]

# print(data)


##皮尔逊相关系数
def pearson_sim(user1, user2):
    # 取出两位用户评论过的电影和评分
    user1_data = data[user1]
    user2_data = data[user2]
    distance = 0
    common = {}

    # 找到两位用户都评论过的电影
    for key in user1_data.keys():
        if key in user2_data.keys():
            common[key] = 1
    if len(common) == 0:
        return 0  # 如果没有共同评论过的电影,则返回0
    n = len(common)  # 共同电影数目
    # print(n, common)

    ##计算评分和
    sum1 = sum([float(user1_data[movie]) for movie in common])
    sum2 = sum([float(user2_data[movie]) for movie in common])

    ##计算评分平方和
    sum1Sq = sum([pow(float(user1_data[movie]), 2) for movie in common])
    sum2Sq = sum([pow(float(user2_data[movie]), 2) for movie in common])

    ##计算乘积和
    PSum = sum([float(user1_data[it]) * float(user2_data[it]) for it in common])

    ##计算相关系数
    num = PSum - (sum1 * sum2 / n)
    den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
    if den == 0:
        return 0
    r = num / den
    return r

##计算某个用户与其他用户的相似度
def top10_simliar(UserID):
    res = []
    for userid in data.keys():
        #排除与自己计算相似度
        if not userid == UserID:
            simliar = pearson_sim(UserID, userid)
            res.append((userid, simliar))
    res.sort(key=lambda val: val[1])
    return res[:4]


RES = top10_simliar('1')
print(RES)

##根据用户推荐给其他人
def recommend(user):
    top_sim_user = top10_simliar(user)[0][0]
    items = data[top_sim_user]
    recommendations = []
    for item in items.keys():
        if item not in data[user].keys():
            recommendations.append((item,items[item]))
    recommendations.sort(key=lambda val:val[1],reverse=True)
    return recommendations[:10]
Recommendations = recommend('1')
print(Recommendations) 

结果:

[('Nutty Professor II: The Klumps (2000)', '5'), ('"Patriot', '5'), ('"Silence of the Lambs', '5'), ('Titan A.E. (2000)', '5'), ('Almost Famous (2000)', '5'), ('Dinosaur (2000)', '5'), ('Mission: Impossible 2 (2000)', '5'), ('Star Wars: Episode I - The Phantom Menace (1999)', '5'), ('X-Men (2000)', '5'), ('Mission to Mars (2000)', '5')]


##其他计算相似距离的
##欧式距离
def Euclidean(user1,user2):
    #取出两位用户评论过的电影和评分
    user1_data=data[user1]
    user2_data=data[user2]
    distance = 0
    #找到两位用户都评论过的电影,并计算欧式距离
    for key in user1_data.keys():
        if key in user2_data.keys():
            #注意,distance越大表示两者越相似
            distance += pow(float(user1_data[key])-float(user2_data[key]),2)
 
    return 1/(1+sqrt(distance))#这里返回值越小,相似度越大

参考:https://blog.csdn.net/qq_25948717/article/details/81839463

相关标签: 推荐系统