基于用户的协同过滤算法

本文数据集和代码参考该博客:https://blog.csdn.net/qq_25948717/article/details/81839463

算法思想:

1. 找到与目标用户兴趣相似的用户集合,计算用户——电影矩阵的行向量之间的欧式距离(或者皮尔逊系数、余弦相似度)

2. 找到这个集合中用户喜欢的、并且目标用户没有听说过的物品推荐给目标用户

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

数据集中本次用到的两个文件为 movies.csv和ratings.csv

基于用户的协同过滤算法_第1张图片

基于用户的协同过滤算法_第2张图片

使用pandas中的merge函数将两个文件按照userID合并到一起,生成data.csv

基于用户的协同过滤算法_第3张图片

import pandas as pd
# movies = pd.read_csv("F:\ml-latest-small\movies.csv")
# ratings = pd.read_csv("F:\ml-latest-small\\ratings.csv")##这里注意如果路径的中文件名开头是r,要转义。
# data = pd.merge(movies,ratings,on = 'movieId')#通过两数据框之间的movieId连接
# data[['userId','rating','movieId','title']].sort_values('userId').to_csv('F:\ml-latest-small\data.csv',index=False)
# left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
#                              'A': ['A0', 'A1', 'A2', 'A3'],
#                              'B': ['B0', 'B1', 'B2', 'B3']})
# right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
#                               'C': ['C0', 'C1', 'C2', 'C3'],
#                               'D': ['D0', 'D1', 'D2', 'D3']})
# data = pd.merge(left,right,on='key')
# print(left)
# print(data)
file = open("F:\ml-latest-small\data.csv", 'r',encoding='UTF-8')  # 记得读取文件时加‘r’, encoding='UTF-8'
##读取data.csv中每行中除了名字的数据
data = {}  ##存放每位用户评论的电影和评分
# for line in file.readlines()[1:100]:
#     # 注意这里不是readline()
#     line = line.strip().split(',')
#     # 如果字典中没有某位用户,则使用用户ID来创建这位用户
#     if not line[0] in data.keys():
#         data[line[0]] = {line[3]: line[1]}
#     # 否则直接添加以该用户ID为key字典中
#     else:
#         data[line[0]][line[3]] = line[1]


for line in file.readlines()[1:22]:
    line = line.strip().split(',')
    # 如果字典中没有某位用户,则使用用户ID来创建这位用户
    if not line[0] in data.keys():

        data[line[0]] = {line[3]: line[1]}
    # 否则直接添加以该用户ID为key字典中
    else:
        data[line[0]][line[3]] = line[1]

print(data)


"""计算任何两位用户之间的相似度,由于每位用户评论的电影不完全一样,所以兽先要找到两位用户共同评论过的电影
       然后计算两者之间的欧式距离,最后算出两者之间的相似度
"""
from math import *


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))  # 这里返回值越小,相似度越大


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


# 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)  # 按照评分排序
    # 返回评分最高的10部电影
    return recommendations[:10]


Recommendations = recommend('1')
print(Recommendations)

 

你可能感兴趣的:(基于用户的协同过滤算法)