我在Spark中编写了一个推荐引擎,该引擎在MovieLens数据集上运行ALS。这是现有的偏好条目数据框的结构:
scala> prefDF.printSchema()
root
|-- user_id: integer (nullable = true)
|-- item_id: integer (nullable = true)
|-- value: double (nullable = true)
一些示例数据:
scala> prefDF.show()
+-------+-------+--------------------+
|user_id|item_id| value|
+-------+-------+--------------------+
| 42| 31| 2.657132896188778|
| 54| 31| 2.7133420465155758|
| 8| 5| 2.673484848484849|
| 8| 9| 2.870155746742124|
| 8| 29| 3.308295945823149|
| 29| 31| 3.0303355105678635|
| 62| 30| 3.761003678085673|
... ... ... ... ... ... ... ... ... ..
现在,我也想从此数据框中生成一些用户和项目相似性。
例如,要使用DIMSUM基于首选项找出用户相似性,首先需要创建一个RowMatrix。到目前为止,据我了解,我必须为每个用户创建商品偏好向量,并从那里建立矩阵。如何有效地从上面显示的数据帧(在Scala中,最好在Java中)导出RowMatrix?
我用连续的整数重新映射了所有用户和商品ID。对于特定用户,是否必须为整个项目集创建矢量,如果缺少当前用户的偏好值,则该条目将填充0?
我到目前为止所做的事情:
我可以生成一个数据框,该数据框基本上是按item_id排序的每个use_id的优先级排序列表。
var mergeList = udf{(strings: Seq[String]) => strings.mkString(",")}
var userVectors = prefDF.withColumn("collected", collect_list($"value").over(Window.partitionBy("user_id").orderBy("item_id")))
.groupBy("user_id").agg(max($"collected").as("collected"))
.withColumn("vector", mergeList($"collected")).select("user_id", "vector")
模式:
scala> userVectors.printSchema()
root
|-- user_id: integer (nullable = true)
|-- vector: string (nullable = true)
样本数据(JSON):
{"user_id":26,"vector":"3.036363636363636,2.396951390503973,3.0715119811560987"}
{"user_id":27,"vector":"3.1695021519708826"}
{"user_id":12,"vector":"2.753030303030303,2.297655772005772"}
{"user_id":22,"vector":"2.7868523254712514,2.606755312072601,2.6950413929208046"}
但是我认为这不足以进行余弦相似性,因为这些向量中不存在缺失项的偏好值。
我想知道的事情:
假设我们有以下数据
+-------+-------+--------------------+
|user_id|item_id| value|
+-------+-------+--------------------+
| 1| 2| 2.65|
| 2| 2| 2.71|
| 1| 1| 2.67|
| 3| 3| 2.87|
| 1| 3| 3.30|
| 2| 1| 3.03|
| 3| 2| 3.76|
+-------+-------+--------------------+
我想生成这样的东西:
{"user_id":1,"vector":"2.67,2.65,3.30"}
{"user_id":2,"vector":"3.03,2.71,0.00"} // since no preference for item 3
{"user_id":3,"vector":"0.00,3.76,2.87"} // since no preference for item 1