【问题标题】:Efficient string matching in Apache SparkApache Spark 中的高效字符串匹配
【发布时间】:2017-10-11 19:53:55
【问题描述】:

我使用 OCR 工具从屏幕截图中提取了文本(每个大约 1-5 个句子)。但是,在手动验证提取的文本时,我注意到不时出现几个错误。

鉴于文本“Hello there ????!我真的很喜欢 Spark ❤️!”,我注意到:

1) “I”、“!”和“l”等字母被“|”替换。

2) 表情符号未正确提取并被其他字符替换或被遗漏。

3) 不时删除空格。

因此,我可能会得到这样的字符串:“Hello there 7l | real|y like Spark!”

由于我试图将这些字符串与包含正确文本的数据集进行匹配(在这种情况下“你好????!我真的很喜欢 Spark ❤️!”),我正在寻找一种有效的方法来匹配Spark 中的字符串。

谁能推荐一个有效的 Spark 算法,让我可以将提取文本(~100.000)与我的数据集(~1 亿)进行比较?

【问题讨论】:

  • 这似乎不是 Spark 问题,而是 OCR 问题,正如您在 (2) 中所说,某些字符未正确提取。所以任何匹配显然都会失败。建议将问题重写为如何通过显示屏幕截图、OCR 软件和配置的示例来改进 OCR 匹配。

标签: python apache-spark pyspark string-matching fuzzy-search


【解决方案1】:

我一开始不会使用 Spark,但如果您真的致力于特定堆栈,您可以组合一堆 ml 转换器以获得最佳匹配。你需要Tokenizer(或split):

import org.apache.spark.ml.feature.RegexTokenizer

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

NGram(例如 3-gram)

import org.apache.spark.ml.feature.NGram

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

Vectorizer(例如CountVectorizerHashingTF):

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|
# +--------------------+--------------------+------------------+

相关

【讨论】:

  • 这有多快?我有两个数据集,分别有 1000 万行和 7000 万行。我必须比较它们中的字符串。需要多长时间?正如这个答案中提到的,如果没有火花,你会怎么做?
  • @RaviRanjan 快和什么比较?
  • 我正在计算 1000 万到 7000 万行大小的表之间的 levenshtein 距离。这当然需要时间,这真的很多。我有两个问题:上面提到的算法有多快,如果不使用 spark 你会怎么做?
  • 似乎 numHashTables=5 需要为 python 版本明确设置
  • @hi-zir 对于我们在 PySpark 中处理的数据大小,这仍然很慢。你有没有机会知道更快的方法?
猜你喜欢
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
相关资源
最近更新 更多