我编写了一个Spark程序用于生成推荐。然后我使用了ALS.recommendation库。我用以下名为trainData的数据集进行了一个小测试:
(u1, m1, 1)(u1, m4, 1)(u2, m2, 1)(u2, m3, 1)(u3, m1, 1)(u3, m3, 1)(u3, m4, 1)(u4, m3, 1)(u4, m4, 1)(u5, m2, 1)(u5, m4, 1)
第一列包含用户,第二列包含用户评分的项目,第三列包含评分。
我在Scala中编写的代码中使用以下方式训练模型:
myModel = ALS.trainImplicit(trainData, 3, 5, 0.01, 1.0)
我尝试使用以下指令为u1检索一些推荐:
recommendations = myModel.recommendProducts(idUser, 2)
其中idUser包含分配给用户u1的ID。作为推荐,我得到的是:
(u1, m1, 1.0536233346170754)(u1, m4, 0.8540954252858661)(u1, m3, 0.09069877419040584)(u1, m2, -0.1345521479521654)
如您所见,前两行显示推荐的项目是u1已经评分过的项目(m1和m4)。无论我选择哪个用户来获取推荐,结果总是相同的(首先推荐的是用户已经评分过的项目)。
我觉得这很奇怪!有什么问题吗?
回答:
我认为这是使用recommendProducts
的预期行为,当您训练像ALS这样的矩阵分解算法时,您试图找到将每个用户与每个项目相关的评分。
ALS基于用户已经评分的项目来做这件事,因此当您为给定用户寻找推荐时,模型对它已经看到的评分最有把握,所以它大多数时候会推荐已经评分过的产品。
您需要做的是保留每个用户评分过的产品列表,并在进行推荐时过滤掉这些产品。
编辑:
我深入研究了一些源代码和文档,以确保我所说的是正确的。
ALS.recommendProducts
是在类MatrixFactorizationModel(源代码)中实现的。您可以看到,模型在进行推荐时并不关心用户是否已经对该项目进行了评分。
您应该注意,如果您使用的是隐式评分,那么您肯定希望推荐用户已经隐式评分过的产品:想象一下,您的隐式评分是用户在线商店中查看产品的页面浏览量,而您希望用户购买该产品的情况。
我没有访问那本《使用Spark进行高级分析》的书,所以我无法评论那里的解释和例子。
文档: