01基于用户的协同过滤算法

it2025-04-21  4

协同推荐(Collaborative recommendation) 方法的主要思想是利用关于过去行为的信息或现有用户所处社交区域的动态来预测系统的当前用户最可能喜欢或感兴趣的产品。这类系统如今在工业上被广泛使用,特别是作为在线零售网站中的工具,以根据特定客户的需求定制内容,从而促进额外的产品的销售以增加销售额。 多年来,古圣先贤们已经提出了各种算法和技术,并成功地对真实世界和人工测试数据进行了评估。 纯协同方法以用户商品评分矩阵作为唯一输入,通常产生以下输出: 1.数字预测,表明当前用户喜欢或不喜欢某一商品的程度。 2.包含n个推荐商品的列表。此top-N列表不应该包含当前用户已经购买过的项目。

2.1 User-based nearest neighbor recommendation

基于用户的最邻近推荐是最早的方法之一,其基本思想是:给定一个评级数据库和目前(活跃)用户的ID作为输入,*识别 * 与活跃用户过去的偏好相似的其它用户(有时称为 peer users 或者 nearest neighbors ),随后,对于活跃用户尚未看到的某个产品p,基于 peer users 的对p的评级来进行计算做预测。 The underlying assumptions of such methods are that: (a).如果用户之间在过去有着相似的喜好,那么在未来他们也有着相似的喜好。 (b).随着时间的推移,用户的偏好保持稳定和一致。

2.1.1 First example
Table 2.1 Ratings database for collaborative recommendation Item1Item2Item3Item4Item5Alice5344?User131233User243435User333154User415521

表2.1显示了当前用户Alice和其它用户的一个评分数据库。Alice在5分制的评分范围中给产品1打了5分,这就意味着她非常喜欢这个产品。 在这个简单的例子之中,推荐系统的任务是确定Alice是否会喜欢她尚未评分或至今没有见过的“产品5”。如果我们可以预测Alice会非常喜欢“产品5”,那么此产品就应该包括在Alice的推荐列表中。为此,我们需要搜素Alice喜好相似的那些用户,并利用这些用户对“产品5”的评分来预测Alice是否会喜欢这个产品.这个过程分为三步: (1)使用推荐系统常用度量之一皮尔逊相关系数计算用户之间的相似度,来确定相似用户集合。 另外,皮尔逊相关系数还考虑了这样一个事实:即用户关于如何解释评分标准方面是不同的。有些用户倾向于只给高评分,而其他用户则永远不会给任何产品5分。基于此,皮尔逊相关系数在计算中考虑了用户打分平均值,以使用户之间具有可比性—也就是说,尽管Alice和用户1的评分绝对值差异很大,但评分之间存在相当明显的线性相关性,因此用户之间的相似性可以被检测到。 由上式可得:Alice与User1到User4的相似度分别为0.85、0.70、0.00、-0.79. (2)得到N个最相似用户集合。在这个例子中,基于相似度的数值,我们可以观察到用户1和用户2在过去与Alice有着相似的评分行为。 (3)计算用户评分。 预测用户a对产品p评分的计算公式: 在本例中,基于相似用户1和用户2的评分,预测Alice对产品5的评分为4.87. 给定这些计算方案,我们现在可以计算爱丽丝尚未看到的所有项目的评分预测,并将预测值最高的项目包括在推荐列表中。在这个例子中,将产品5包含在推荐列表中很可能是一个很好的选择。上面显示的示例评级数据库当然是现实世界的理想化。在现实世界的应用中,评级数据库要大得多,可以包含数千甚至数百万的用户和产品,这意味着我们必须考虑计算的复杂性。此外,评分矩阵通常非常稀疏,这意味着每个用户将只对可用产品的非常小的子集进行评分。 最后,我们还不清楚可以向新用户推荐产品,或者我们如何处理没有评分的新产品。

2.1.2 Better similarity and weighting metrics

上述例子中,我们使用Pearson’s correlation coefficient 来衡量来衡量用户之间的相似性。在文献中,还提出了其他度量标准来衡量用户之间的相似度,例如 adjusted cosine similarity、Spearman’s rank correlation coefficient 、squared difference measure. 实证分析表明: 基于用户的推荐系统中皮尔逊系数优于其他比较用户相似度的指标。 基于物品的推荐系统中余弦相似度度量始终优于皮尔逊相关度量。

2.1.3 Neighborhood selection

在上述的例子中,我们直觉地决定不考虑所有相似用户(相似用户选择)。而在计算产品评分预测时,我们只选择那些与活跃用户有正相关性的产品(当然,也包括我们正在寻找的需要预测的产品)。如果我们将相似性程度一般的所有用户都包括在内,这不仅会对所需计算时间的性能产生负面影响,还会影响推荐的准确性,因为会考虑到其他不具有真正相关性的用户的评分。 减小相似用户集合大小的常用方法是: 1.定义用户相似性的特定最小阈值。 2.将相似用户集合大小限制为一个固定的数字,只考虑k个最近的用户。 这两种方法存在的问题是:如果相似性阈值太高,对于许多用户来说,相似用户集合的大小将非常小,这又意味着对于许多产品来说,无法进行预测(覆盖范围减小)。相比之下,当阈值太低时,相似用户集合的大小不会显著减小。 k值的选择(即相似用户集合的大小)应该不影响覆盖范围。然而,找到一个好的k值仍然存在问题:当考虑的相似用户数k太高时,太多相似度有限的用户会给预测带来额外的“噪声”。当k太小时(低于10时)预测的质量可能会受到负面影响。 古圣先贤们对电影数据集的分析表明,“在大多数现实世界的情况下,20到50个相似用户似乎是合理的”。

UserCF编程的简单实现 – 基于上述第一个示例

# 1.建立数据表¶ #在实际情况中,我们知道用户对物品的打分情况并不会很完整,会存在大量的空值,所以矩阵会很稀疏。故采用字典形式来存储。 # 第一个字典是物品-用户的评分映射,键是物品1-5,用A-E来表示;键对应的值又是一个字典,表示的是每个用户对该物品的评分。 # 第二个字典是用户-物品的评分映射,键是五个用户,用1-5表示;键对应的值是该用户对每个物品的打分。 # 导入所需库 import numpy as np import pandas as pd #定义数据集 def loadData(): items = {'A':{1:5,2:3,3:4,4:3,5:1}, 'B':{1:3,2:1,3:3,4:3,5:5}, 'C':{1:4,2:2,3:4,4:1,5:5}, 'D':{1:4,2:3,3:3,4:5,5:2}, 'E':{2:3,3:5,4:4,5:1} } users = {1:{'A':5,'B':3,'C':4,'D':4}, 2:{'A':3,'B':1,'C':2,'D':3,'E':3}, 3:{'A':4,'B':3,'C':4,'D':3,'E':5}, 4:{'A':3,'B':3,'C':1,'D':5,'E':4}, 5:{'A':1,'B':5,'C':5,'D':2,'E':1} } return items,users items,users = loadData() item_df = pd.DataFrame(items).T user_df = pd.DataFrame(users).T # 2.计算用户相似矩阵¶ ## 5 * 5 的共现矩阵,行代表每个用户,列代表每个用户,值代表用户和用户的相关性。 # 计算用户相似性矩阵 similarity_matrix = pd.DataFrame(np.zeros((len(users),len(users))),index=[1,2,3,4,5],columns=[1,2,3,4,5]) # 遍历每条用户-物品评分数据 for userID in users: for otheruserId in users: vec_user = [] vec_otheruser = [] if userID != otheruserId: for itemId in items: # 遍历物品-用户评分数据 itemRatings = items[itemId] # 这也是个字典,每条数据为所有用户对当前物品的评分 if userID in itemRatings and otheruserId in itemRatings: #说明两个用户都对该物品评过分 vec_user.append(itemRatings[userID]) vec_otheruser.append(itemRatings[otheruserId]) similarity_matrix[userID][otheruserId] = np.corrcoef(np.array(vec_user),np.array(vec_otheruser))[0][1] #similarity_matrix[userID][otheruserId] = cosine_similarity(np.array(vec_user),np.array(vec_otheruser))[0][1] # 3. 计算前n个相似的用户 n = 2 similarity_users = similarity_matrix[1].sort_values(ascending=False)[:n].index.tolist() # 4.计算最终得分 """计算最终得分""" base_score = np.mean(np.array([value for value in users[1].values()])) base_score weighted_scores = 0.0 corr_values_sum = 0.0 for user in similarity_users: corr_value = similarity_matrix[1][user] #两个用户之间的相似性 mean_user_score = np.mean(np.array([value for value in users[user].values()])) #每个用户的打分平均值 weighted_scores += corr_value * (users[user]['E'] - mean_user_score) corr_values_sum += corr_value final_scores = base_score + weighted_scores / corr_values_sum print('用户Alice对产品5的打分:',final_scores) user_df.loc[1]['E'] = final_scores user_df #---运行结果:用户Alice对产品5的打分: 4.871979899370592
最新回复(0)