我正在寻找一个库或一个使用现有库(^{query
)中字符串(query
)的最接近匹配
我开发了一种基于difflib
的方法,在这个方法中,我将corpus
分成大小为n
(长度为query
)的ngram。在
import difflib
from nltk.util import ngrams
def get_best_match(query, corpus):
ngs = ngrams( list(corpus), len(query) )
ngrams_text = [''.join(x) for x in ngs]
return difflib.get_close_matches(query, ngrams_text, n=1, cutoff=0)
当查询和匹配字符串之间的差异只是字符替换时,它的工作方式与我希望的一样。在
^{pr2}$但当区别是字符删除时,就不是了。在
query = "ipsum dolor"
corpus = "lorem 1psum dlr sit amet"
match = get_best_match(query, corpus)
# match = "psum dlr si"
# expected_match = "1psum dlr"
有没有一种方法可以获得更灵活的结果大小(对于expected_match
)?在
我现在使用的解决方案是用(n-k)-grams for k = {1,2,3}
扩展ngram,以防止3个删除。它比第一个版本好得多,但是在速度方面没有效率,因为我们要检查的ngram数量是ngram的3倍多。这也是一个不可归纳的解决方案。在
求解的主要途径是使用某种有限状态自动机(FSA)。如果您想获得主题的详细摘要,请查看此dissertation页(PDF链接)。基于误差的模型(包括Levenshtein自动机和传感器,Sergei提到了前者)是解决这一问题的有效方法。然而,随机模型,包括与FSAs集成的各种机器学习方法,是目前非常流行的。在
由于我们关注的是编辑距离(实际上是拼写错误的单词),Levenshtein方法很好而且相对简单。This paper(以及论文;也是PDF)给出了一个不错的基本思想大纲,并明确提到了在OCR任务中的应用。不过,我将回顾一下下面的一些要点。在
基本思想是,您希望构建一个FSA来计算有效字符串和所有字符串,直到某个错误距离(k)。在一般情况下,这个k可能是无限大的,或者是文本的大小,但这对OCR来说基本上是无关的(如果您的OCR甚至可以返回
bl*h
,其中*是整个文本的其余部分,我建议您找到一个更好的OCR系统)。因此,我们可以从搜索字符串blah
的有效答案集中限制regex的类似bl*h
。对于您的上下文,一个通用、简单和直观的k可能是字符串的长度(w)减去2。这允许b h
成为blah
的有效字符串。它也允许bla h
,但没关系。另外,请记住,错误可以是您指定的任何字符,包括空格(因此“多字”输入是可解决的)。在下一个基本任务是建立一个简单的加权传感器。任何OpenFST Python端口都可以做到这一点(here's one)。逻辑很简单:插入和删除增加了权重,而相等增加了输入字符串中的索引。你也可以像Sergei评论链接里的人那样手工编码。在
一旦有了权重和权重的相关索引,就只需排序并返回。计算复杂度应为O(n(w+k)),因为我们将针对文本中每个字符(n)预测最坏情况下的w+k字符。在
从这里,你可以做任何事情。你可以把传感器转换成DFA。您可以通过将文本分解为w+k-gram来并行化系统,这些w+k-gram被发送到不同的进程。您可以开发一个语言模型或混淆矩阵,定义输入集中每个字母存在哪些常见错误(从而限制有效转换的空间和相关FSA的复杂性)。文献是庞大的,而且还在不断增长,所以可能会有很多修改和解决方案(如果不是更多的话)。在
希望它能回答你的一些问题,而不需要给出任何代码。在
我将尝试从查询字符串构建正则表达式模板。然后可以使用模板在语料库中搜索可能与查询匹配的子字符串。然后使用difflib或fuzzyfuzzy检查子字符串是否与查询匹配。在
例如,一个可能的模板将匹配查询的前两个字母中的至少一个,以及查询的最后两个字母中的至少一个,并且在这两个字母之间有大约正确的数量:
输出:
^{pr2}$另一个想法是在构建regex时使用ocr的特性。例如,如果ocr总是正确地获得某些字母,那么当这些字母中有任何一个在查询中时,就在正则表达式中使用其中一些。或者“ocr”混合了,'l'和'i',但从不替换其他字母,那么如果查询中有一个字母,请在regex中使用
[1!il]
。在此函数用于查找可变长度的最佳匹配子字符串。在
该实现将语料库视为一个长字符串,因此避免了对空格和未分隔词的关注。在
代码摘要:1.以
step
为步长扫描语料库中的匹配值,以找到最大匹配值的近似位置pos
。 2.通过调整子串的左/右位置,找到匹配值最高的pos
附近的子串。在示例:
^{pr2}$一些好的启发性建议是始终保持}。我还增加了区分大小写的功能,以防这很重要。当您开始使用step和flex值时,它非常有效。较小的步长值可以获得更好的结果,但计算时间较长。flex控制结果子字符串的长度允许的灵活性。在
step < len(query) * 3/4
,和{需要注意的是:这只会找到第一个最佳匹配项,因此如果有多个同样好的匹配项,则只返回第一个匹配项。为了允许多个匹配,更改
index_max()
以返回输入列表中n
最高值的索引列表,并在该列表中的值的adjust_left_right_positions()
上循环。在相关问题 更多 >
编程相关推荐