import pandas as pd
from math import *
import numpy as np
"""
读取movies文件,设置列名为’videoId', 'title', 'genres'
读取ratings文件,设置列名为'userId', 'videoId', 'rating', 'timestamp'
通过两数据框之间的 videoId 连接
保存'userId', 'rating', 'videoId', 'title'为data数据表
"""
movies = pd.read_csv("D:/Datamovies/ml-latest-small/movies.csv", names=['videoId', 'title', 'genres'])
ratings = pd.read_csv("D:/Datamovies/ml-latest-small/ratings.csv",names=['userId', 'videoId', 'rating', 'timestamp'])
data = pd.merge(movies, ratings, on='videoId')
data[['userId', 'rating', 'videoId', 'title']].sort_values('userId').to_csv('D:/Datamovies/ml-latest-small/data.csv',index=False)
"""
新建一个data字典存放每位用户评论的电影和评分, 如果字典中没有某位用户,则使用用户ID来创建这位用户,否则直接添加以该用户ID为key字典中
"""
file = open("D:/Datamovies/ml-latest-small/data.csv",'r', encoding='UTF-8')
data = {}
for line in file.readlines():
line = line.strip().split(',')
if not line[0] in data.keys():
data[line[0]] = {line[3]:line[1]}
else:
data[line[0]][line[3]] = line[1]
"""
找到两位用户共同评论过的电影,然后计算两者之间的欧式距离,最后算出两者之间的相似度,欧式距离越小两者越相似
"""
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 += pow(float(user1_data[key]) - float(user2_data[key]), 2)
return 1 / (1 + sqrt(distance))
"""
计算某个用户与其他用户的相似度
"""
def top_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])
return res[:4]
"""
从控制台输入需要推荐的用户ID,如果用户不在原始数据集中则报错,重新输入
"""
getIdFlag = 0
while not getIdFlag:
inputUid = str(input("请输入用户ID\n"))
try:
uid = data[inputUid]
getIdFlag = 1
except Exception:
print("用户ID错误,请重新输入\n")
欧式距离的电影推荐算法怎样构建评估模型,怎样计算其准确率,召回率和F1
"""
根据与当前用户相似度最高的用户评分记录,按降序排列,推荐出改用户还未观看的评分最高的10部电影
"""
def recommend(user):
top_sim_user = top_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]
"""
根据输入的用户ID,输出为他推荐的影片
"""
Recommendations = recommend(inputUid)
print("为用户" + inputUid + "推荐下列评分最高的十部影片\n")
for video in Recommendations:
print(video)
欧式距离电影推荐算法
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
3条回答 默认 最新
关注引自免费微信小程序:皆我百晓生
针对您提供的欧式距离电影推荐算法,评估其性能主要通过离线评估方法,如计算准确率、召回率以及F1值。但是,这些指标在协同过滤场景下通常不直接适用,因为没有明确的正负样本标签。为了进行评估,我们通常采用如下方式进行:
-
划分数据集:将用户的历史行为数据划分为训练集和测试集。训练集用于计算用户间的相似度并生成推荐列表,而测试集用来验证推荐结果的好坏。
-
定义评价指标:在这种场景下,可以使用
Precision@k(精确率)、Recall@k(召回率)以及F1@k来评估推荐效果。例如,对于给定用户,查看在推荐列表前k个电影中有多少是用户实际喜欢的(在测试集中出现过的),从而计算精确率;召回率则是看推荐列表中包含了用户实际喜欢的电影的比例。 -
实施评估:
- 精确率(Precision@k): 推荐出的前k部电影中有多少被用户真正喜欢了。
- 召回率(Recall@k): 用户真正喜欢的电影有多少出现在推荐的前k部电影中。
- F1@k:是精确率和召回率的调和平均数,衡量推荐系统的综合表现。
以下是简化的示例代码片段以展示如何计算 Precision@k 和 Recall@k,假设已有一个函数
evaluate_recommendations(user, ground_truth, recommendations),其中ground_truth是用户在测试集中的实际评分记录,recommendations是为该用户生成的推荐列表:def precision_at_k(ground_truth, recommendations, k): relevant_items = set(item for item, _ in ground_truth[:k]) recommended_items = set(item for item, _ in recommendations[:k]) return len(relevant_items & recommended_items) / k def recall_at_k(ground_truth, recommendations, k): relevant_items = set(item for item, _ in ground_truth) recommended_items = set(item for item, _ in recommendations[:k]) return len(relevant_items & recommended_items) / len(relevant_items) # 假设我们已经从测试集中获取了用户的实际评分记录 test_user_ratings = [(movie_id, rating) for movie_id, rating in test_data if test_data['userId'] == inputUid] # 对于某个用户,获取推荐列表 recs = recommend(inputUid)[:k] # k是我们需要评估的前k个推荐项 # 计算Precision@k和Recall@k precision = precision_at_k(test_user_ratings, recs, k) recall = recall_at_k(test_user_ratings, recs, k) # 计算F1@k (这里省略了F1的计算细节,通常可通过调和平均数公式得出) f1 = 2 * precision * recall / (precision + recall)注意,在实际应用中,由于你的代码尚未实现数据集划分和上述评估指标的计算,你需要补充这部分逻辑,并根据实际情况调整代码来适应这一评估流程。同时,基于欧式距离的推荐系统可能对用户间的相似度计算不够精准,实际生产环境中可能会考虑其他相似度计算方式或结合其他推荐策略。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报 编辑记录-