问题描述
我有一本非常大的词典,其中存储了大量的英语句子及其西班牙语翻译。当给定一个随机的英语句子时,我打算使用Python的fuzzywuzzy库在字典中找到最接近的匹配项。我的代码:
from fuzzywuzzy import process
sentencePairs = {'How are you?':'¿Cómo estás?','Good morning!':'¡Buenos días!'}
query= 'How old are you?'
match = process.extractOne(query,sentencePairs.keys())[0]
print(match,sentencePairs[match],sep='\n')
在现实生活中,sentencePairs
词典非常大,至少存储了一百万个项目。因此,即使安装了python-Levenshtein来提供加速效果,也要花很长时间才能获得fuzzywuzzy的结果。
那么,有没有更好的方法来获得更好的性能呢?我的目标是在不到几秒钟的时间内甚至实时获得结果。
解决方法
如何提高性能
使用Levenshtein距离进行模糊匹配永远不会很快,但是您可以优化代码中的几件事:
-
在将字符串和列表传递给process.extractOne时,它将通过对它们进行小写,删除非字母数字字符并修剪空格来对这些字符串进行预处理。由于您每次都重复使用相同的English:Spanish映射,因此您应该提前进行一次预处理。
-
即使在使用python-Levenshtein时,FuzzyWuzzy在很多地方也没有真正进行优化。您应该将其替换为RapidFuzz,该实现可以通过相似的接口实现相同的算法,但是主要是在C ++中实现的,并且还进行了一些其他算法上的改进,从而使其运行速度更快。
-
内部
a b c d <dbl> <dbl> <dbl> <dbl> 1 1 0.924 1 0.924 2 2 0.661 3 0.402 3 3 0.402 3 0.402 4 4 0.637 3 0.402 5 5 0.353 1 0.924
在默认情况下使用process.extractOne
比较字符串。这是多个字符串匹配算法的组合。所以通过例如选择更快的算法fuzz.WRatio
到process.extractOne可以提高性能。但是请记住,这会更改比较字符串的方式,因此根据您的数据,您可能不希望这样做。
使用1和2的实现
scorer=fuzz.ratio
使用1、2和3的实现
from rapidfuzz import process,utils
# english sentences are already lower cased
# and without special characters like question marks
sentencePairs = {'how are you':'¿Cómo estás?','good morning':'¡Buenos días!'}
query= 'How old are you?'
match,_ = process.extractOne(
utils.default_process(query),sentencePairs.keys(),processor=None)
print(match,sentencePairs[match],sep='\n')
基准
为了提供一些时间比较,我生成了一百万个句子:
from rapidfuzz import process,utils,fuzz
# english sentences are already lower cased
# and without special characters like question marks
sentencePairs = {'how are you':'¿Cómo estás?',processor=None,scorer=fuzz.ratio)
print(match,sep='\n')
下表显示了我的计算机上不同解决方案所需的时间
import string
import random
random.seed(18)
sentencePairs = {
''.join(random.choice(string.ascii_lowercase + string.digits)
for _ in range(15)
): "spanish text"
for s in range(1000000)
}
query= 'How old are you?'
,
可能有更好的解决方案,但我想到的就是分区。
您可以创建26个不同的字典,每个字典代表一个英文字母。然后,您可以使用以相应字母开头的所有键加载所有这些词典。 例如。 adict,bdict ... zdict等 所以。 hdict将包含以h开头的Key的Key值。就像key =“你好吗?”
通过这种方式,您只需要查询与起始字母匹配的字典即可。