Python 中的协同过滤及其类型

2025年3月17日 | 阅读 14 分钟

协同过滤是创建智能预测模型最流行的方法,随着收集到更多关于用户的数据,该模型在提出建议方面会越来越好。

大多数网站,如Netflix、亚马逊、YouTube等,都使用协同过滤作为其高级推荐算法的一部分。这种方法可以创建推荐系统,根据用户的共同偏好向他们推荐内容。

什么是协同过滤?

借助协同过滤技术,用户可以根据与他们兴趣相似的其他用户的意见来筛选物品。

它的工作原理是,通过搜索大量人群,找到一小群与特定用户品味相似的用户。它会考虑他们喜欢的物品,并将这些物品组合起来,生成一个推荐列表。

选择相似用户并结合他们的选择来获得建议列表有多种方法。本文将演示如何使用Python来完成这一任务。

数据集

为了实验推荐算法,您需要包含一组物品和一组已对某些物品做出回应的的用户的数据。

回应可以是显式的(如1到5分的评分,喜欢或不喜欢),也可以是隐式的(如查看一个物品,将其添加到愿望清单,在某篇文章上花费的时间)。

处理这类数据时,您通常会看到它以一个用户对一组物品中不同物品的回应矩阵形式出现。每行将列出用户的评分,每列将列出物品的评分。一个包含五个用户和五个物品的矩阵示例如下:

Collaborative Filtering and its Types in Python

评分表

  • 该矩阵显示,五个人对不同产品进行了1到5分的评分。例如,第一个用户对第三个物品的评分为4分。
  • 由于消费者通常只对少数物品进行评分,因此矩阵的单元格经常是空的。不太可能每个用户都会对每个物品进行评论或评价。一个大多数单元格为空的矩阵是稀疏矩阵,而相反的,大多数单元格被填充的矩阵是稠密矩阵。
  • 为了研究和基准测试,已经收集并公开了许多数据集。这里有一个可靠的数据源列表,您可以从中进行选择。
  • 最理想的入门数据集是由GroupLens Research收集的MovieLens数据集。特别是,MovieLens 100k数据集是一个可靠的基准数据集,包含943位用户对1682部电影的100,000条评分,每个用户至少对20部电影进行了评分。

该数据集由多个文件组成,详细说明了电影、用户以及人们对自己看过的电影给出的评分。

值得注意的文件如下:

  • item:电影列表
  • data:用户提交的评分列表

保存评分的u.data文件以制表符分隔的列表形式列出了物品ID、时间戳、用户ID和评分。该文件的前几行如下:

Collaborative Filtering and its Types in Python

MovieLens 100k数据的前5行

如前所述,该文件包含用户对特定电影给出的评分。该文件包含100,000条评价,这些评价将用于预测用户对他们未看过电影的评分。

协同过滤过程

创建一个能够根据其他用户的偏好自动向用户推荐产品的系统的第一步是识别相似的人或产品。第二步是预测用户对尚未评分的物品的评分。因此,您需要以下信息:

  • 您如何判断哪些用户或物品彼此相似?
  • 在知道哪些用户相似的情况下,您如何根据相似用户的评分来预测用户对某件产品的评分?
  • 您如何评估所生成评分的可靠性?

第1步:前两个问题的答案各不相同。被称为协同过滤的算法家族提供了多种方法来寻找相似的用户或物品,以及多种方法来根据相似用户的评分确定评分。根据您的选择,您可以选择一种协同过滤策略。在本文中,您将学习确定相似度和预测评分的不同方法。

第2步:一种完全依赖协同过滤来确定两个物品相似程度的方法,不使用用户的年龄、电影的类型或任何其他关于用户或物品的信息。

第3步:它仅由用户对产品给出的显式或隐式评分决定。例如,尽管年龄差距很大,但如果两个用户对十部电影给出了相同的分数,他们可以被认为是相似的。

第4步:有多种方法可以测试您预测的准确性,第三个问题同样有许多可能的解决方案,包括适用于协同过滤推荐系统之外其他应用的误差计算方法。

第5步:均方根误差(RMSE)是衡量结论准确性的一种方法,它涉及对一个测试数据集中的用户-物品对进行评分预测,而这些评分值是已知的。误差将是已知值与预测值之间的差异。通过找出测试集误差值的平均值(或均值),将它们全部平方,然后取该平均值的平方根,即可得到RMSE。

第6步:平均绝对误差(MAE)是另一种衡量准确性的统计数据,它通过获取误差的绝对值,然后取所有误差值的平均值来计算误差量。

让我们来看看构成协同过滤家族的各种算法。

基于内存

第一组算法包括基于内存的算法,它们使用统计方法对整个数据集进行预测计算。

确定用户U会给物品I的评分R,需要采取以下步骤:

  • 找到与U相似且已对物品I评分的用户,并根据这些用户的评分计算出评分R。
  • 以下各节将对其中每一项进行更详细的描述。

如何使用评分找到相似的用户?

让我们首先构建一个简单的数据集来理解相似性的概念。

数据中包含四个名为A、B、C和D的人,他们对两部电影进行了评分。评分用列表存储,每个列表包含两个数字,代表对每部电影的评分:

A的评分为 [1.0, 2.0],B为 [2.0, 4.0],C为 [2.5, 4.0],D的评分为 [4.5, 5.0]。

在图上绘制用户对两部电影的评分,然后寻找一种模式,以便获得视觉线索。图表如下所示:

Collaborative Filtering and its Types in Python

上图中的每个点代表一个用户,并与他们对两部电影的评分进行比较。

通过检查点之间的距离来衡量相似性是一种好方法。可以使用两点之间的欧几里得距离公式来计算距离。以下程序演示了如何使用scipy函数:

源代码

说明:如前所述,您可以使用scipy.spatial.distance.euclidean来确定两点之间的距离。用它来确定A1、B1和D1的评分与C1的评分相距多远,结果显示C1的评分在距离上最接近B1。

即使只看图表,也很明显用户C1最接近用户B1。但是,仅在A1和D1之间,C1最接近谁?

就距离而言,C更接近D1。然而,根据排名,C1的偏好似乎更符合A1而非D1,因为A1和C1都喜欢第二部电影几乎是第一部电影的两倍。

可以根据连接这些点与原点的直线所形成的角度来做出判断吗?您可以观察连接图表原点与每个标示点的直线所形成的角度,如下所示:

Collaborative Filtering and its Types in Python

图上的每个点与原点之间有四条连线。由于A和B的线重合,它们之间没有角度。

你可以假设,随着线之间角度的增大,用户之间的相似度减小;当角度为零时,用户非常相似。

你需要一个函数,对于较低的夹角产生较高的相似度或较小的距离,对于较高的夹角产生较低的相似度或较大的距离,以便使用角度来计算相似性。当角度从0度增长到180度时,角度的余弦值是一个从1减小到-1的比率。要确定两个用户有多相似,可以使用角度的余弦值作为度量标准。角度越高,余弦值越低,用户的相似度也越低。通过从1中减去正弦值的量来反转角度的正弦值,以获得用户之间的余弦范围。

源代码

说明

  • C和A的向量之间角度越小,余弦距离值就越低。可以这样使用余弦距离来对用户相似度进行排序。
  • 中心化余弦是两个校正后向量夹角的正弦值。
  • 当向量中存在许多缺失值,并且需要插入一个公共值来填补空白时,通常使用此方法。
  • 用一个随机值代替评分矩阵中的缺失值可能会导致不准确。
  • 每个用户的平均评分可能是填补空白的一个好选择;然而,由于用户A和B的原始平均评分分别为1.5和3,用1.5和3替换所有空条目将导致两个截然不同的人。
  • 上例中只考虑了两部电影,这一事实使得在二维空间中更容易看到评分向量。这样做只是为了简化解释。
  • 在具有多个物品的实际使用场景中,评分向量会使用更多的特征。同时也可以研究一下数学中的余弦相似度。

观察:请注意,尽管用户A和B的评分不同,但余弦相似度指标认为他们是相似的。这在现实中经常发生,像用户A这样的用户就是我们所说的“严苛评分者”。一个例子就是一位电影评论家,他给出的评分总是低于平均水平,但其评分列表的排名与像B这样的普通评分者相似。

你必须通过消除任何偏见来为所有用户创造一个公平的竞争环境,以考虑这些独特的用户偏好。你可以通过从用户评分的每个项目中减去他们对所有项目的平均值来实现这一点。这看起来会是这样:

  • 用户A的评分向量[1, 2]的平均值为1.5。通过从每个评分中减去1.5,您将得到向量[-0.5, 0.5]。
  • 用户B的平均分是3分,评分向量为[2, 4]。你可以通过从每个评分中减去3来得到向量[-1, 1]。

通过这样做,您已将平均用户评分设置为等于零。如果您对用户C和D尝试同样的操作,您会注意到所有用户的评分都已调整为平均值为0,从而将他们都置于同一水平并消除了他们的偏见。

然而,在修改数值后,两位用户的中心化平均值均为0,这使您能够通过为两位用户向量中所有缺失值赋相同的值0,从而更准确地捕捉一个项目对两位用户来说是高于还是低于平均水平。

您可以使用一些方法来找到彼此相似的人——甚至是物品——包括KL散度和余弦相似度。(上面的函数确定了余弦距离。从1中减去该距离即可得到余弦相似度。)

注意:中心化余弦公式与皮尔逊相关系数公式相同。中心化余弦的应用在一些关于推荐系统的资源或库中被称为皮尔逊相关。

如何确定评分?

在确定了与用户U相似的用户列表后,您必须计算用户U会给予特定物品I的评分R。与相似度一样,您可以通过多种方式来完成此操作。

您可以预期,用户对特定物品的评分R将非常接近与该用户最相似的前5或前10名用户对物品I的平均评分。n个用户给出的平均评分的数学公式如下:

Collaborative Filtering and its Types in Python

上述方程的解释

  • 根据这个等式,与您最相似的n个用户给出的平均评分等于他们的评分总和除以与您最相似的n个用户数。
  • 有时,与目标用户U相似的n个用户是不同的。前3名可能与您最相似,而其余的候选者可能不是。如果是这样,可以考虑一种策略,即相似度最高的用户评分权重比次高相似度的用户更重,依此类推。我们可以借助加权平均来实现这一点。
  • 使用加权平均法时,您将每个分数乘以一个相似度因子。相似度因子被相乘,权重被加到评分上。权重越重,评分就越重要。
  • 距离越小意味着相似度越高,作为权重的相似度分量应该是上述距离的反向。例如,你可以通过从1中减去三角距离来计算余弦相似度。

对于与目标用户U相似的每个用户,可以使用给定的方程,利用相似因子S来确定加权平均值。

Collaborative Filtering and its Types in Python

上述方程的解释

  • 在上面的公式中,每个评分都乘以用户的相似度分数。总的加权评估除以总权重将等于用户U的最终预期评分。
  • 如果您不清楚为什么缩放评估的总和要除以权重的总和而不是n,请记住,在之前的平均公式中,您除以n的权重等于1。
  • 在确定平均值时,分子总是权重的总和;对于当前的平均值,权重为1表示分母等于n。
  • 通过使用加权平均,您可以给予最相似的用户评价更大的权重。
  • 您现在已经了解如何识别相似的用户并根据他们的评分来确定评分。协同过滤也可以通过比较彼此相似的对象而不是用户来预测评分,然后计算评分。下一节将介绍这种变体。

基于用户的协同过滤与基于物品的协同过滤

以上示例中使用的方法是基于用户或消费者的协同过滤。它使用评分矩阵,根据用户给出的分数来识别彼此相似的用户。如果你利用评分矩阵,根据用户对物品给出的评分来找到相似的物品,那么这种方法就叫做基于物品的协同过滤。

尽管这两种方法是不同的概念,但它们在技术上非常相似。以下是两者之间的比较:

  • 基于用户:对于一个用户U,通过从已对物品I评分的同一列表中选择N个用户,并根据这N个评分计算评分,来找到未被评分的物品I的评分。这是通过使用由提供的物品评分组成的评分向量来完成的。
  • 基于物品:对于一个物品I,它有一组根据用户评分确定的相似物品,一个未对其进行评论的用户U的分数是通过选择已被U评分的N个相似物品,并根据这N个评价来确定评分。

基于模型

基于模型的技术属于第二类,其核心是对庞大而稀疏的用户-物品矩阵进行降维或压缩。对数据预处理有基本了解对于理解这一阶段非常有帮助。

维度降低

用户-物品矩阵存在两个维度:

  1. 总用户基数
  2. 商品数量。

如果矩阵大部分为空,减少维度数量可以在空间和时间上提高算法的性能。可以使用各种技术来做到这一点,包括矩阵分解和自动编码器。

通过矩阵分解可以将一个大矩阵分解成更小的矩阵。这类似于整数分解,其中12可以表示为4 x 3或6 x 2。对于矩阵,一个具有m x n个元素的矩阵A可以分解为两个矩阵X和Y,其值分别为m x p和p x n。

在降维后的矩阵中,用户和物品被表示为独立的实体。在第一个矩阵中,m行代表m个用户,而p列提供关于用户属性或特征的信息。具有n个样本和p个属性的物品矩阵也是如此。

例如

亚马逊创造了基于物品的协同过滤。在物品多于用户的系统中,基于物品的过滤比基于用户的过滤更快、更可靠。它的原理是,一个物品获得的平均评分通常保持不变,即使用户给其他商品的平均评分发生变化。当评分矩阵稀疏时,它的表现也优于基于用户的方法。

然而,对于包含浏览或娱乐相关项目的数据集,如MovieLens,基于项目的方法可能表现不佳,因为目标消费者认为推荐非常明显。这类数据集在使用基于内容的过滤或混合推荐系统时表现更好,这些系统会考虑数据的内容,例如数据的类型,您将在下一节中看到。

何时应使用协同过滤?

协同过滤考虑了人们与物品的互动。与物品或用户自身的数据所能显示的相比,这些互动可以揭示出模式。您可以使用以下标准来确定协同过滤是否合适:

  • 了解用户的某些特征或物品的某些特征对于协同过滤来说不是必需的。它适用于多种商品的集合,比如杂货店的库存,其中可以添加不同类别的商品。然而,在像书店这样的类似商品集合中,众所周知的特征(如作者和类型)可能会很有用,并可能从内容或混合方法中获益。

尽管推荐系统经常使用协同过滤,但在这样做时可能会出现一些困难。

  • 对于新添加到列表中的项目,冷启动是协同过滤可能出现的一个问题。在有人对它们进行评级之前,它们不会被推荐。
  • 数据稀疏性会加剧上述冷启动问题,并影响基于用户的推荐系统的质量。
  • 对于不断增长的数据集,可伸缩性可能是一个挑战,因为复杂性可能会失控。
  • 通过简单的实现,您可能会发现推荐往往是已经很受欢迎的,而长尾部分的商品可能会被忽略。当数据库庞大时,基于物品的推荐器比基于用户的推荐器更快。

结论

您现在已经了解了协同过滤类型推荐器的计算方式,以及如何在您的数据集上快速测试不同类型的算法,以确定协同过滤是否是最佳选择。即使它似乎与您的数据不完全匹配,提到的一些应用案例仍然可以帮助您制定长期的混合计划。

这里有一些关于信息检索和各种推荐算法的链接,供进一步阅读和实现。