如何在Apache Spark中的MovieLens数据集上运行余弦相似度(DIMSUM)?

时间:2018-07-10 12:37:40

标签: java scala apache-spark apache-spark-mllib cosine-similarity

我在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

0 个答案:

没有答案