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,交叉处代表这个用户喜爱这部电影
 

如上表:

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

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,基于用户协同过滤算法可以分为以下几个步骤: 1. 数据处理,将用户和物品转化为数字标识,如1、2、3、4等。 2. 构建用户-物品评分矩阵,即将用户对物品的评分存储到一个矩阵中。 3. 计算用户之间的相似度,可以使用余弦相似度或皮尔逊相关系数等。 4. 预测用户对未评分物品的评分,计算方法为:对于用户u和物品i,找出与u最相似的k个用户计算这k个用户对i的评分的加权平均值,权重为相似度。 5. 推荐物品,根据预测的评分值对用户推荐物品。 下面是一个简单的基于用户协同过滤算法实现: ```python import numpy as np # 原始评分矩阵 R = np.array([ [5, 3, 0, 1], [4, 0, 0, 1], [1, 1, 0, 5], [1, 0, 0, 4], [0, 1, 5, 4], ]) # 用户相似度矩阵 sim_matrix = np.zeros((R.shape[0], R.shape[0])) for i in range(R.shape[0]): for j in range(i+1, R.shape[0]): # 计算余弦相似度 sim_matrix[i, j] = np.dot(R[i], R[j]) / (np.linalg.norm(R[i]) * np.linalg.norm(R[j])) sim_matrix[j, i] = sim_matrix[i, j] # 预测用户对未评分物品的评分 def predict(u, i, k=3): # 找出与u最相似的k个用户 sim_users = np.argsort(-sim_matrix[u])[:k] # 计算加权平均值 rating = np.dot(sim_matrix[u][sim_users], R[sim_users, i]) / np.sum(sim_matrix[u][sim_users]) return rating # 推荐物品 def recommend(u, k=3): # 找出用户u未评分的物品 unrated_items = np.where(R[u] == 0)[0] # 预测用户对未评分物品的评分 ratings = [predict(u, i, k) for i in unrated_items] # 对预测评分排序,推荐评分最高的物品 recommended_item = unrated_items[np.argmax(ratings)] return recommended_item # 测试推荐结果 print(recommend(0, 3)) ``` 这里的数据是一个5x4的评分矩阵,其中5个用户对4个物品进行评分。首先计算用户之间的相似度,然后对于每个用户,预测他对未评分物品的评分,最后推荐评分最高的物品。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值