Spark RowMatrix列的相似性保留原始索引

时间:2019-02-12 10:39:52

标签: scala apache-spark dataframe vector apache-spark-mllib

我有以下(df的Scala Spark DataFrame String, Array[Double]:注意id的类型为String(A64哈希)

id, values
"a", [0.5, 0.6]
"b", [0.1, 0.2]
...

数据集很大(45k),我想使用org.apache.spark.mllib.linalg.distributed.RowMatrix执行成对的余弦相似度以提高性能。这可行,但是由于索引已变成整数(输出列i和j),因此我无法识别成对相似性。如何使用IndexedRowMatrix保留原始索引?

val rows = df.select("values")
            .rdd
            .map(_.getAs[org.apache.spark.ml.linalg.Vector](0))
            .map(org.apache.spark.mllib.linalg.Vectors.fromML)

val mat = new RowMatrix(rows)

val simsEstimate = mat.columnSimilarities()

理想情况下,最终结果应如下所示:

id_x, id_y, similarity
"a", "b", 0.9
"b", "c", 0.8
...

1 个答案:

答案 0 :(得分:0)

columnSimilarities()计算RowMatrix之间的相似度,而不是行之间的相似度,因此在这种情况下,您具有的“ id”是没有意义的,索引是每个特征向量中的索引

此外,这些方法是为较长,狭窄和数据而设计的,因此,一种明显的方法-用id编码StringIndexer,创建IndedxedRowMatrix,转置,计算相似度,然后返回(使用IndexToString)根本不会。

您最好的选择是crossJoin

df.as("a").crossJoin(df.as("b")).where($"a.id" <= $"b.id").select(
  $"a.id" as "id_x", $"b.id" as "id_y", cosine_similarity($"a.values", $b.values")
)

其中

val cosine_similarity = udf((xs: Array[Double], ys: Array[Double]) => ???)

这是您必须实现的事情。

或者您可以爆炸数据:

import org.apache.spark.sql.functions.posexplode

val long = ds.select($"id", posexplode($"values")).toDF("item", "feature", "value")

,然后使用Spark Scala - How to group dataframe rows and apply complex function to the groups?中显示的方法来计算相似度。