Jaccard Сходство между строками текста Apache Spark - PullRequest
0 голосов
/ 04 ноября 2018

Мне нужно вычислить сходство Жакара всех пар строк текста. Я буду хотеть в выводе только пары со сходством выше 80%. В прошлом я изучал фреймворк Hadoop MapReduce, и именно так я решил бы это с помощью map и уменьшил функции:

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 голосов
/ 05 ноября 2018

Если ваши данные не очень большие, самый простой и легкий подход также может быть самым быстрым. Давайте разделим и победим проблему:

  1. Получить кадр данных всех пар линий, используя crossJoin.

  2. Удалите строки, в которых левая линия совпадает с правой линией, так как вы не заботитесь о самосравнениях.

  3. Используйте простую jaccard UDF (слева, справа), чтобы вернуть сходство Jaccard.

  4. Фильтр по сходству> 0,8

Я использую Spark через Scala, поэтому я дам вам код 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)
...