一种计算两个单词之间编辑距离的算法



我正在尝试编写Python代码,该代码以一个单词作为输入(例如book),并输出具有相似性分数的最相似的单词。

我尝试过不同的现成编辑距离算法,如余弦、Levenstein和其他算法,但这些算法无法判断差异的程度。例如,(book,bouk)和(book,bo0k)。我正在寻找一种算法,可以为这两个例子给出不同的分数。我正在考虑使用fastText或BPE,但它们使用余弦距离。

有什么算法可以解决这个问题吗?

这是一个非常有趣的问题,可能有很多可能的答案。你可以添加双元(n-gram)分析来对字母在典型单词中相互关联的可能性进行排名。

假设你的系统不"知道"目标词,但有人键入了"bouk"。然后分析了所有的bigram:

bo,欧,英国

或三元图

bou,ouk

我想在这里,"bo"、"欧"、"布"会得分很高,因为它们很常见,但"英国"one_answers"欧"在英语中不太可能。因此,这可能只是一个3/5的分数,但实际上每个三元图都有自己的频率分数(概率),因此所提出的单词的总数可以非常精确。

然后将其与"bo0k"进行比较,你会看到所有的bigram:

bo,o0,0k

或三元图

bo0,o0k

现在你可以看到只有bo会在这里得分。所有其他的都不会在一个通用的n-gram语料库中找到。因此,这个词在可能性方面的得分将远低于"bouk",例如,与"bouk"的3/5相比,为1/5。

解决方案大致有三个部分:

你需要一个为该语言建立的n-gram频率的语料库。例如,我发现的这个随机博客讨论了:https://blogs.sas.com/content/iml/2014/09/26/bigrams.html

然后,你需要将输入的单词处理(标记和扫描)成n-gram,然后在语料库中查找它们的频率。你可以使用类似SK Learn、的东西

然后,你可以用任何你喜欢的方式对各个部分进行汇总,以确定单词的总分。

请注意,你可能会发现大多数自然语言的标记和n-gram处理都围绕着单词关系,而不是单词中的字母。人们很容易忘记这一点,因为通常情况下,图书馆专注于单词语法的事实并没有被明确提及,因为它是最常见的。我以前注意到过,但n-gram也用于其他各种数据集(时间序列、音乐、任何序列)。这个问题确实讨论了如何将SK Learn的矢量器转换为字母gram,但我自己没有尝试过:sklearn 中字母的n-gram

问题是"bo0k"one_answers"bouk"都是与"book"不同的一个字符,没有其他度量可以区分它们。

你需要做的是改变评分:如果是不同的字符类(即数字而不是字母),你可以给它一个更高的分数,而不是将不同的字符计算为编辑距离1。这样你的例子就会得到不同的分数。

不过,您可能还需要调整其他分数,以便替换/插入/删除仍然一致。

我有第二个想法,在有人在键盘上打字的情况下,它使用"领域知识"。它没有直接回答你的问题,但说明了实现最终目标可能有完全不同的方法(你没有直接描述过,即提供拼写检查器选项的用户界面?)。

我曾在大学写过一个算法,该算法使用键盘布局图(作为拼写检查器中的一种策略),在字典中找不到单词时,对周围的所有键进行迭代,以提出"胖手指"校正。

例如O被I90PLK包围,I被U89OK或U89OKJ包围。

因此,你可以通过用周围邻居的所有组合替换每个字母来变异每个输入单词。你最终会得到很多组合,但其中大多数都是完全伪造的单词。其中一个可能与字典中的单词完美匹配。

因此,你所需要做的就是生成所有可能的拼写错误邻居,并简单地在变体中查找所有字典单词,这应该是一个有效的查询。

例如,对于bo0k

bo0k
vo0k
go0k
ho0k
no0k
_o0k
bi0k
b90k
b00k
bp0k
bl0k
bk0k
bo9k
bo0k
bo-k
bopk
book       - bingo!
boik
bo0j
bo0u
bo0i
bo0o
bo0l
bo0,
bo0m

你可以在这里看到,在整个基本的拼写错误变体中,只有一个字典单词。

因此,这不使用任何相似算法,但在键盘打字错误的情况下,它可以找到更正。您甚至可以记录用户对这些建议的"接受程度",并形成自己的更正概率语料库。我猜很多错别字都很常见而且前后一致。

显然,这不包括拼写错误,尽管根据自然语言及其特定的怪癖和困难,可以采取类似的领域知识方法。

最新更新