ALS的Pyspark实施如何处理每个用户项目组合的多个评级?
我观察到,到ALS的输入数据不需要每个用户项目组合都具有唯一的评分。
这是一个可再现的例子。
# Sample Dataframe
df = spark.createDataFrame([(0, 0, 4.0),(0, 1, 2.0),
(1, 1, 3.0), (1, 2, 4.0),
(2, 1, 1.0), (2, 2, 5.0)],["user", "item", "rating"])
df.show(50,0)
+----+----+------+
|user|item|rating|
+----+----+------+
|0 |0 |4.0 |
|0 |1 |2.0 |
|1 |1 |3.0 |
|1 |2 |4.0 |
|2 |1 |1.0 |
|2 |2 |5.0 |
+----+----+------+
如您所见,每个用户项目组合只有一个评分(理想的情况)。 如果我们将此数据框传递到ALS,它将为您提供以下预测:
# Fitting ALS
from pyspark.ml.recommendation import ALS
als = ALS(rank=5,
maxIter=5,
seed=0,
regParam = 0.1,
userCol='user',
itemCol='item',
ratingCol='rating',
nonnegative=True)
model = als.fit(df)
# predictions from als
all_comb = df.select('user').distinct().join(broadcast(df.select('item').distinct()))
predictions = model.transform(all_comb)
predictions.show(20,0)
+----+----+----------+
|user|item|prediction|
+----+----+----------+
|0 |0 |3.9169915 |
|0 |1 |2.031506 |
|0 |2 |2.3546133 |
|1 |0 |4.9588947 |
|1 |1 |2.8347554 |
|1 |2 |4.003007 |
|2 |0 |0.9958025 |
|2 |1 |1.0896711 |
|2 |2 |4.895194 |
+----+----+----------+
到目前为止,一切对我来说都是有意义的。但是,如果我们有一个包含多个用户项目额定组合的数据框架,如以下所示,
# sample daataframe
df = spark.createDataFrame([(0, 0, 4.0), (0, 0, 3.5),
(0, 0, 4.1),(0, 1, 2.0),
(0, 1, 1.9),(0, 1, 2.1),
(1, 1, 3.0), (1, 1, 2.8),
(1, 2, 4.0),(1, 2, 3.6),
(2, 1, 1.0), (2, 1, 0.9),
(2, 2, 5.0),(2, 2, 4.9)],
["user", "item", "rating"])
df.show(100,0)
+----+----+------+
|user|item|rating|
+----+----+------+
|0 |0 |4.0 |
|0 |0 |3.5 |
|0 |0 |4.1 |
|0 |1 |2.0 |
|0 |1 |1.9 |
|0 |1 |2.1 |
|1 |1 |3.0 |
|1 |1 |2.8 |
|1 |2 |4.0 |
|1 |2 |3.6 |
|2 |1 |1.0 |
|2 |1 |0.9 |
|2 |2 |5.0 |
|2 |2 |4.9 |
+----+----+------+
您可以在上面的数据框架中看到,有一个用户项目组合的多个记录。例如 - 用户'0'对项目'0'额定额定级,分别为4.0,3.5和4.1。
如果我将此输入数据框传递给ALS怎么办?这个可以吗? 我最初认为它应该不起作用,因为ALS应该每个用户项目组合获得唯一的评分,但是当我运行此功能时,它可以奏效并使我感到惊讶!
# Fitting ALS
als = ALS(rank=5,
maxIter=5,
seed=0,
regParam = 0.1,
userCol='user',
itemCol='item',
ratingCol='rating',
nonnegative=True)
model = als.fit(df)
# predictions from als
all_comb = df.select('user').distinct().join(broadcast(df.select('item').distinct()))
predictions = model.transform(all_comb)
predictions.show(20,0)
+----+----+----------+
|user|item|prediction|
+----+----+----------+
|0 |0 |3.7877638 |
|0 |1 |2.020348 |
|0 |2 |2.4364853 |
|1 |0 |4.9624424 |
|1 |1 |2.7311888 |
|1 |2 |3.8018093 |
|2 |0 |1.2490809 |
|2 |1 |1.0351425 |
|2 |2 |4.8451777 |
+----+----+----------+
为什么起作用?我认为它会失败,但也没有失败,也给了我预测。
我尝试查看研究论文,有限的ALS源代码以及Internet上的可用信息,但找不到任何有用的东西。 是否平均将这些不同的评分拿到ALS或其他任何评分?
有人遇到过类似的事情吗?还是关于ALS如何在内部处理此类数据的任何想法?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在Spark组中实现的矩阵分解的平行化方法实际上是通过(用户,项目)对的,并添加了用户对同一项目的不同评分。您可以在Spark的GitHub中的Scala代码中自己验证此事,第1377行:
de seqop确定如何添加两个评分对象的位置。
The parallelized method to matrix factorization implemented in Spark actually groups by (user,item) pairs and adds the different ratings a user made for the same item. You can verify this by yourself in the Scala Code in Spark's github, line 1377:
where de seqOp determines how to add up two rating objects.
https://github.com/apache/spark/blob/master/mllib/src/main/scala/org/apache/spark/ml/recommendation/ALS.scala