我有以下(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
...
答案 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?中显示的方法来计算相似度。