提高性能的方法
使用 Levenshtein 距离的模糊匹配永远不会超快,但您的代码中有几件事可以优化:
-
将字符串和列表传递给 process.extractOne 时,它将通过小写这些字符串、删除非字母数字字符和修剪空格来预处理这些字符串。由于您每次都重复使用相同的英语:西班牙语映射,因此您应该提前进行一次此预处理。
-
即使使用 python-Levenshtein FuzzyWuzzy 在很多地方都没有真正优化。您应该将其替换为 RapidFuzz,它实现了具有相似接口的相同算法,但主要用 C++ 实现,并附带一些额外的算法改进,使其速度更快。
-
默认情况下,process.extractOne 内部使用fuzz.WRatio 比较字符串。这是多种字符串匹配算法的组合。因此,通过传递例如选择更快的算法scorer=fuzz.ratio 到 process.extractOne 提高了性能。但是请记住,这会改变比较字符串的方式,因此根据您的数据,您可能不想这样做。
利用1和2的实现
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')
利用1、2、3实现
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?', 'good morning':'¡Buenos días!'}
query= 'How old are you?'
match, _ = process.extractOne(
utils.default_process(query),
sentencePairs.keys(),
processor=None,
scorer=fuzz.ratio)
print(match, sentencePairs[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?'
下表显示了不同解决方案在我的计算机上需要多长时间
| Implementation | Runtime |
|------------------------------------------|----------------|
| Your current implementation | 18.98 seconds |
| Implementation making use of 1 and 2 | 1.4 seconds |
| Implementation making use of 1, 2 and 3 | 0.4 seconds |