web-dev-qa-db-ja.com

Apacheでの効率的な文字列照合Spark

OCRツールを使用して、スクリーンショットからテキストを抽出しました(それぞれ約1〜5文)。ただし、抽出されたテキストを手動で確認すると、時々発生するいくつかのエラーに気付きました。

「Hello there ????!Spark❤️!」が本当に好きだ」というテキストを考えると、次のことに気付きました。

1)「I」、「!」、「l」などの文字は「|」に置き換えられます。

2)絵文字が正しく抽出されず、他の文字に置き換えられたり、省略されたりします。

3)空白は時々削除されます。

その結果、「Hello there 7l | real | y like Spark!」のような文字列になります。

私はこれらの文字列を正しいテキストを含むデータセットと照合しようとしているので(この場合は「こんにちは!?!Spark❤️!」が本当に好きです)、私は探していますSparkで文字列を照合する効率的な方法。

Sparkの効率的なアルゴリズムを提案できますか?これにより、抽出テキスト(〜100.000)とデータセット(〜1億)を比較できますか?

26
mrtnsd

そもそもSparkを使用しませんが、特定のスタックに本当にコミットしている場合は、多数のmlトランスフォーマーを組み合わせて最適な一致を得ることができます。Tokenizer(またはsplit):

import org.Apache.spark.ml.feature.RegexTokenizer

val tokenizer = new RegexTokenizer().setPattern("").setInputCol("text").setMinTokenLength(1).setOutputCol("tokens")

NGram(3グラムなど)

import org.Apache.spark.ml.feature.NGram

val ngram = new NGram().setN(3).setInputCol("tokens").setOutputCol("ngrams")

Vectorizer(たとえば、CountVectorizerまたはHashingTF):

import org.Apache.spark.ml.feature.HashingTF

val vectorizer = new HashingTF().setInputCol("ngrams").setOutputCol("vectors")

およびLSH

import org.Apache.spark.ml.feature.{MinHashLSH, MinHashLSHModel}

// Increase numHashTables in practice.
val lsh = new MinHashLSH().setInputCol("vectors").setOutputCol("lsh")

Pipelineと組み合わせる

import org.Apache.spark.ml.Pipeline

val pipeline = new Pipeline().setStages(Array(tokenizer, ngram, vectorizer, lsh))

サンプルデータに適合:

val query = Seq("Hello there 7l | real|y like Spark!").toDF("text")
val db = Seq(
  "Hello there ????! I really like Spark ❤️!", 
  "Can anyone suggest an efficient algorithm"
).toDF("text")

val model = pipeline.fit(db)

両方を変換:

val dbHashed = model.transform(db)
val queryHashed = model.transform(query)

そして参加する

model.stages.last.asInstanceOf[MinHashLSHModel]
  .approxSimilarityJoin(dbHashed, queryHashed, 0.75).show
+--------------------+--------------------+------------------+                  
|            datasetA|            datasetB|           distCol|
+--------------------+--------------------+------------------+
|[Hello there ????! ...|[Hello there 7l |...|0.5106382978723405|
+--------------------+--------------------+------------------+

Pysparkでも同じアプローチを使用できます

from pyspark.ml import Pipeline
from pyspark.ml.feature import RegexTokenizer, NGram, HashingTF, MinHashLSH

query = spark.createDataFrame(
    ["Hello there 7l | real|y like Spark!"], "string"
).toDF("text")

db = spark.createDataFrame([
    "Hello there ????! I really like Spark ❤️!", 
    "Can anyone suggest an efficient algorithm"
], "string").toDF("text")


model = Pipeline(stages=[
    RegexTokenizer(
        pattern="", inputCol="text", outputCol="tokens", minTokenLength=1
    ),
    NGram(n=3, inputCol="tokens", outputCol="ngrams"),
    HashingTF(inputCol="ngrams", outputCol="vectors"),
    MinHashLSH(inputCol="vectors", outputCol="lsh")
]).fit(db)

db_hashed = model.transform(db)
query_hashed = model.transform(query)

model.stages[-1].approxSimilarityJoin(db_hashed, query_hashed, 0.75).show()
# +--------------------+--------------------+------------------+
# |            datasetA|            datasetB|           distCol|
# +--------------------+--------------------+------------------+
# |[Hello there ????! ...|[Hello there 7l |...|0.5106382978723405|
# +--------------------+--------------------+------------------+

関連

29
hi-zir