执行余弦相似时,Pyspark过滤前三个匹配

时间:2016-08-09 19:46:46

标签: apache-spark pyspark

我有两个文件集。我计算了每对笛卡尔积之间的余弦相似度,得到了形式的RDD

(k1,(k2,c))

其中k1是第一个集合中的文档,k2是第二个集合中的一个,c是它们之间的余弦相似度。

我有兴趣为第一个集合中的每个文档k1获取与第二个集合中最相似的三个文档。我按键执行了一组:

grouped = (pairRddWithCosine
         .groupByKey()
         .map(lambda (k, v): (k, sorted(v, key=lambda x: -x[1])))
         .map(lambda (x,y): (x, y[0][0],y[0][1], y[1][0], y[1][1],         y[2][0] , y[2][1]))
      )

事实证明,这一组表现非常糟糕。你能告诉我如何调整它甚至更好,使用不会改变数据的东西?

3 个答案:

答案 0 :(得分:1)

如果要获取键的值/计数/部分值,则应避免使用groupByKey,因为groupByKey会对所有数据进行洗牌,以便给定键的所有值最终都在同一个reducer中。对于大型数据集,这非常昂贵。相反,您应该使用reduceByKey或combineByKey。对于这些操作,您可以指定用于在每个分区上累积数据的函数以及来自不同分区的累加器之间的合并函数。您可以阅读此内容以获取更多详细信息:https://databricks.gitbooks.io/databricks-spark-knowledge-base/content/best_practices/prefer_reducebykey_over_groupbykey.html

答案 1 :(得分:0)

我认为您应该尝试reduceByKey,因为您只对部分价值感兴趣

k_with_top_c = rdd.reduceByKey(lambda v: sorted(v, key=lambda x: -x[1])[:3])

reduceByKey会首先尝试本地缩减,因此它的运行速度比groupByKey快。但是,在这种情况下,我不认为你可以避免洗牌。

答案 2 :(得分:0)

或者,我认为如果我们采取

smallRdd = pairRddWithCosine.map(lambda (k1,(k2,c)))

然后

Combined = (smallRdd
        .combineByKey(lambda value: [value],
                      lambda x, value: x + [value],
                      lambda x, y : max(x,y))
        .map(lambda (x,y): (x,y[0]))
        .map(lambda x: (x,0))
       )

后面的连接将提供第一场比赛。我们可以通过执行leftOuterJoin()从pairRddWithCosine获取不是最佳匹配的所有元素 与最佳匹配,以获得第二好。