当前位置: 移动技术网 > IT编程>脚本编程>Python > Python实现协同过滤推荐

Python实现协同过滤推荐

2020年10月12日  | 移动技术网IT编程  | 我要评论
协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的信息来推荐相应的产品给客户,是一种智能的生活方式。之所以叫协同过滤,是因为在实现过滤推荐的时候是根据其他人的行为来做预测的,基于相似用户的喜好来实现用户的喜好预测。简要介绍: 通过找到兴趣相投,或者有共同经验的群体,来向用户推荐感兴趣的信息。举例,如何协同过滤,来对用户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,交叉处代表这个用户喜爱这部电影

如上表:

横坐标,假设有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文件

通过如下程序提取数据:

# -*- 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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网