2025-04-17-用户协同过滤-阿里云

2025-04-17-用户协同过滤-阿里云

题目内容

你是一家视频网站的数据工程师,公司希望为用户提供个性化的电影推荐,以提升用户的观看体验。团队决定采用基于协同过滤的推荐算法,通过分析用户的历史评分数据,找出与目标用户兴趣相似的其他用户,进而推荐他们喜欢的电影。你的任务是编写一个程序,基于用户的评分数据,实现一个简单的用户协同过滤推荐系统。

请你帮助团队实现一个使用 N u m P y NumPy NumPy库的程序,基于协同过滤算法为指定用户生成电影推荐列表。具体要求如下:

  1. 读取输入数据集,包含 ( N ) (N) (N)个用户对 ( M ) (M) (M)部电影的评分矩阵,评分范围为 1 − 5 1-5 15的整数,未评分记为0。
  2. 读取目标用户的编号 ( U ) (U) (U),对其进行电影推荐。
  3. 计算用户之间的相似度,使用皮尔逊相关系数 ( P e a r s o n C o r r e l a t i o n C o e f f i c i e n t ) (PearsonCorrelationCoefficient) (PearsonCorrelationCoefficient)
  4. 根据相似度选取前 ( K ) (K) (K)个最相似的用户,默认 ( K = 3 ) (K=3) (K=3)
  5. 根据相似用户的评分,预测目标用户未评分电影的评分。

输出目标用户最有可能喜欢的前 ( T ) (T) (T)部电影的编号,按照预测评分从高到低排序,若评分相同则按电影编号从小到大排序。

注意:

  1. 在预测评分时,即使所有相似用户都未对某个电影评分,也不应忽略该电影,将预测评分设为目标用户的平均评分。
  2. 在计算相似度时,对于没有共同评分项目的用户,仍需将其相似度设为0,而非忽略,以免遗漏潜在的相似用户。

输入描述

  • 第一行包含两个整数 ( N ) (N) (N) ( M ) (M) (M),表示用户数量和电影数量。
  • 接下来的 ( N ) (N) (N)行,每行包含 ( M ) (M) (M)个整数,表示用户对电影的评分,未评分记为0,评分范围为 1 − 5 1-5 15
  • 接下来一行包含一个整数 ( U ) (U) (U),表示目标用户的编号(从0开始)。
  • 最后一行包含一个整数 ( T ) (T) (T),表示需要推荐的电影数量。

输出描述

  • 输出一行,包含 ( T ) (T) (T)个整数,表示推荐的电影编号(从0开始),按预测评分从高到低排序,编号之间用空格分隔。

补充说明

皮尔逊相关系数

两个用户 ( u ) (u) (u) ( v ) (v) (v)的相似度计算公式为:

s i m ( u , v ) = ∑ i ∈ I ( r u , i − r ˉ u ) ( r v , i − r ˉ v ) ∑ i ∈ I ( r u , i − r ˉ u ) 2 ∑ i ∈ I ( r v , i − r ˉ v ) 2 sim(u, v) = \frac{\sum_{i \in I} (r_{u,i} - \bar{r}_u)(r_{v,i} - \bar{r}_v)}{\sqrt{\sum_{i \in I} (r_{u,i} - \bar{r}_u)^2} \sqrt{\sum_{i \in I} (r_{v,i} - \bar{r}_v)^2}} sim(u,v)=iI(ru,irˉu)2 iI(rv,irˉv)2 iI(ru,irˉu)(rv,irˉv)

其中:

  • ( I ) (I) (I)为用户 ( u ) (u) (u) ( v ) (v) (v)都评分过的电影集合。
  • ( r u , i ) (r_{u,i}) (ru,i)为用户 ( u ) (u) (u)对电影 ( i ) (i) (i)的评分。
  • ( r ˉ u ) (\bar{r}_u) (rˉu)为用户 ( u ) (u) (u)的平均评分。

对于目标用户 ( u ) (u) (u)未评分的电影 ( j ) (j) (j),预测评分的计算公式为:

r ^ u , j = r ˉ u + ∑ v ∈ K s i m ( u , v ) ( r v , j − r ˉ v ) ∑ v ∈ K ∣ s i m ( u , v ) ∣ \hat{r}_{u,j} = \bar{r}_u + \frac{\sum_{v \in K} sim(u, v) (r_{v,j} - \bar{r}_v)}{\sum_{v \in K} |sim(u, v)|} r^u,j=rˉu+vKsim(u,v)vKsim(u,v)(rv,jrˉv)

其中:

  • ( K ) (K) (K)为与用户 ( u ) (u) (u)最相似的前 ( K ) (K) (K)个用户集合。
  • ( r v , j ) (r_{v,j}) (rv,j)为用户 ( v ) (v) (v)对电影 ( j ) (j) (j)的评分。

样例1

输入:
5 5
5 3 0 1 0
4 0 0 1 0
1 1 0 5 0
0 0 5 4 0
0 0 5 4 0
0 
2 

输出:
2 4

说明

  • 目标用户为编号0的用户
  • 计算用户之间的相似度,找到与目标用户最相似的3个用户。
  • 预测目标用户未评分的电影2和4的评分。
  • 推荐评分最高的前2部电影,分别是电影编号2和4。
import numpy as np
n,m = map(int, input().split())
scores = []
for _ in range(n):
    scores.append(list(map(int, input().split())))
u = int(input())
t = int(input())
scores = np.array(scores)
scores
array([[5, 3, 0, 1, 0],
       [4, 0, 0, 1, 0],
       [1, 1, 0, 5, 0],
       [0, 0, 5, 4, 0],
       [0, 0, 5, 4, 0]])
# 计算平均得分
mean_scores = []
for score in scores:
    nonzero = score[score > 0]
    if len(nonzero) > 0:
        mean_scores.append(np.mean(nonzero))
    else:
        mean_scores.append(0.0)
mean_scores = np.array(mean_scores)

array([3.        , 2.5       , 2.33333333, 4.5       , 4.5       ])
user1 = scores[1]
user2 = scores[2]
(user1 != 0) & (user2!=0) 
array([ True, False, False,  True, False])
def sim(i, j):
    user1 = scores[i]
    user2 = scores[j]
    mask = (user1 != 0) & (user2 != 0)
    if not np.any(mask):
        return 0.0
    ru = user1[mask] - mean_scores[i]
    rv = user2[mask] - mean_scores[j]
    return np.sum(ru * rv)/(np.sqrt(np.sum(ru ** 2)) * np.sqrt(np.sum(rv ** 2)))
sim(0,1)
1.0
# 计算相似度
similaritys = [0.0] * n
similaritys[u] = 1.0
for i in range(n):
    if i != u:
        s = sim(u, i)
        similaritys[i] = s
similaritys = np.array(similaritys)
top_k = np.argsort(-similaritys)[:3]
top_k
array([0, 1, 3])
# 对 u 未评分的电影进行评分预测
preds = np.zeros(m)
for j in range(m):
    if scores[u, j] > 0:
        # 已评分电影跳过
        preds[j] = -np.inf
        continue
    # 收集相似用户对电影 j 的评分偏差
    temp1 = 0.0
    temp2 = 0.0
    for v in top_k:
        if similaritys[v] == 0:
            continue
        if scores[v, j] > 0:
            temp1 += similaritys[v] * (scores[v, j] - mean_scores[v])
            temp2 += abs(similaritys[v])
    # 如果没有用户提供评分,则使用目标用户的平均评分
    if temp2 == 0.0:
        preds[j] = mean_scores[u]
    else:
        preds[j] = mean_scores[u] + temp1 / temp2

# 按预测评分排序,取前 T 个电影编号
# 若预测相同,则电影编号小的优先
result = np.argsort(-preds, kind='stable')[:t]
print(" ".join(map(str, list(result))))
2 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨落俊泉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值