文本行之间的Jaccard相似性Apache Spark

时间:2018-11-04 18:27:58

标签: python apache-spark pyspark mapreduce similarity

我需要计算所有成对的文本行的Jaccard相似度。我只希望输出相似度高于80%的线对。 过去,我研究了Hadoop MapReduce框架,这就是我将如何使用map和reduce函数解决此问题的方法:

map(lineID, text):
    for each word in text:
         emit(word, (len(text), lineID))

reduce(word, list(v)):
    if len(list(v)) < 2:
        do nothing
    else 
        for each pair ((len1, 1), (len2, 2)):
             emit ((1, 2, len, len2), 1)

map(k, v):
    emit (k, v)

reduce(k, v):
    similarity = len(v)/(k[2]+k[3]-len(v))
    if similarity > 0.80
         emit((k[0], k[1]), similarity)

现在,我需要在PySpark中实现此伪代码,但是我有些卡住了。我要做的只是第一张地图,例如:

def mapping(line):
    length = len(line.split())-1
    jobID = line.split()[0]
    return (length, jobID)

c = textFile.map(lambda line: [(c, (mapping(line))) for c in line.split()[1:]])

我不考虑第一个单词,因为该单词是lineID。我还有另一个疑问,如何获取输入文本行的索引? 任务如何分配给工人?我对Apache Spark的工作方式非常困惑。

您对我可以使用哪些方法以及在MapReduce中获得结果的顺序有何建议?

1 个答案:

答案 0 :(得分:0)

除非您的数据非常大,否则最简单,最简单的方法也可能是最快的。让我们分而治之:

  1. 使用crossJoin获取所有线对的数据框。

  2. 由于您不在乎自我比较,因此删除左手线与右手线相同的行。

  3. 使用简单的UDF jaccard(左,右)返回Jaccard相似度。

  4. 按相似度> 0.8过滤

我通过Scala使用Spark,因此我将为此提供Scala代码。 Python DSL应该非常相似。

val lines = spark.read.text(...)
lines.alias("lhs").crossJoin(lines.alias("rhs"))
  .where($"lhs.value" =!= $"rhs.value")
  .withColumn("similarity", jaccard($"lhs.value", $"rhs.value"))
  .where($"similarity" > 0.8)