协同过滤:非个性化的物品间相似性
我正在尝试计算物品之间的相似度,类似于亚马逊的推荐方式:“查看/购买了X的顾客也查看/购买了Y和Z”。我看到的例子和参考资料大多是关于计算排名物品的相似度、寻找用户之间的相似度,或者根据当前用户的历史记录来推荐物品。我想先从一种不针对特定用户的方法开始,然后再考虑当前用户的偏好。
在查看了亚马逊推荐的白皮书后,他们在离线计算物品相似度时使用了以下逻辑:
For each item in product catalog, I1
For each customer C who purchased I1
For each item I2 purchased by customer C
Record that a customer purchased I1 and I2
For each item I2
Compute the similarity between I1 and I2
如果我理解得没错,当我们到达“计算I1和I2之间的相似度”时,我已经有了一份与单个值I1(外层循环)一起购买的物品列表(I2)。
这个计算是怎么进行的呢?
还有一个想法是,我可能想得太复杂了,其实没必要那么麻烦——只要对与I1一起购买的I2的数量做个前n名查询就够了吗?
我也希望能得到一些建议,看看这种方法是否正确。我的产品数据库里大约有15万个物品。由于我看到的大部分阅读材料都是关于用户-物品相似度或者用户-用户相似度的,我是否应该考虑走那条路呢?
我之前也用过相似度算法,但它们总是涉及到排名或评分。我觉得唯一可行的方法是建立一个顾客-产品矩阵,用0和1来表示未购买和已购买。考虑到购买历史和物品数量,这个矩阵可能会变得非常庞大。
补充:虽然我把python列为标签,但我更希望将逻辑放在数据库中,最好使用Oracle PL/SQL。
4 个回答
@Neil 或者将来看到这个问题的朋友:
选择相似度的计算方法是你自己的决定,你可能希望这个选择在未来可以灵活调整。可以先看看维基百科上关于弗罗贝尼乌斯范数的文章。或者你可以参考你提交的链接中的杰卡德系数 cos(I1,I2)
。
用户-物品、用户-用户、物品-物品之间的选择,或者其他组合,不能简单地给出一个标准答案。这取决于你能从用户那里获取什么样的数据,用户界面是如何提取这些信息的,你认为哪些数据是可靠的,以及你自己的时间限制(尤其是涉及混合方法时)。
因为很多人都在这些问题上写过硕士论文,所以你可能想从最简单的可实现方案开始,同时留出空间让算法在复杂性上逐步提升。
让我们来理解一下物品之间的协同过滤。假设我们有一个购买矩阵。
Item1 Item2 ... ItemN
User1 0 1 ... 0
User2 1 1 ... 0
.
.
.
UserM 1 0 ... 0
然后我们可以通过列向量来计算物品之间的相似度,比如使用余弦相似度。我们会得到一个物品相似度的对称矩阵,如下所示。
Item1 Item2 ... ItemN
Item1 1 1/M ... 0
Item2 1/M 1 ... 0
.
.
.
ItemN 0 0 ... 1
这可以理解为“查看或购买了X的顾客,也查看或购买了Y、Z……”(协同过滤)。因为物品的向量化是基于用户的购买记录。
亚马逊的逻辑和上面说的一样,目标是提高效率。正如他们所说:
我们可以通过遍历所有物品对,计算每对之间的相似度,来构建一个物品与物品之间的矩阵。然而,很多物品对没有共同的顾客,因此这种方法在处理时间和内存使用上都不够高效。迭代算法提供了一种更好的方法,通过计算一个单一产品与所有相关产品之间的相似度。
这方面有一本很不错的O'Reilly的书。虽然白皮书可能用伪代码的方式来展示逻辑,但我觉得这种方法不太适合大规模使用。这里的计算都是概率计算,所以像贝叶斯定理这样的东西就会被用来问:“如果A这个人买了X,那么他买Z的可能性有多大?”简单地遍历数据会让工作变得很繁琐,因为你得为每个人都处理一遍所有数据。