Python中的字符串相似性度量
我想找出两个字符串之间的相似性。佩奇有一些例子。Python实现了。在这些限制条件下,是否有更好的算法(希望还有python库)Python中的字符串相似性度量,python,algorithm,string,levenshtein-distance,Python,Algorithm,String,Levenshtein Distance,我想找出两个字符串之间的相似性。佩奇有一些例子。Python实现了。在这些限制条件下,是否有更好的算法(希望还有python库) 我想在字符串之间进行模糊匹配。例如,匹配('Hello,All you peopl','Hello,All you peopl')应该返回True 假阴性是可以接受的,假阳性是可以接受的,但极少数情况除外 这是在非实时设置下完成的,因此速度不太重要 [编辑]我正在比较多字字符串 对于我的情况,除了Levenshtein距离(或Levenshtein比率)之外的其他算法
>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
['apple', 'ape']
>>> import keyword
>>> get_close_matches('wheel', keyword.kwlist)
['while']
>>> get_close_matches('apple', keyword.kwlist)
[]
>>> get_close_matches('accept', keyword.kwlist)
['except']
< P> >谢菲尔德大学的字符串相似性度量有很大的资源。它有一个各种指标的列表(不仅仅是Levenshtein),并且有它们的开源实现。看起来它们中的许多应该很容易适应Python 以下是列表的一部分:
- 汉明距离
- Levenshtein距离
- Needleman-Wunch距离算法
- 还有更多
- 我意识到这不是一回事,但这已经足够接近了:
>>> import difflib
>>> a = 'Hello, All you people'
>>> b = 'hello, all You peopl'
>>> seq=difflib.SequenceMatcher(a=a.lower(), b=b.lower())
>>> seq.ratio()
0.97560975609756095
你可以把它作为一个函数
def similar(seq1, seq2):
return difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() > 0.9
>>> similar(a, b)
True
>>> similar('Hello, world', 'Hi, world')
False
我会使用Levenshtein距离,或所谓的Damerau距离(考虑了换位),而不是difflib,原因有两个:(1)“足够快”(动态编程算法)和“嗖嗖”(位碰撞)C代码可用;(2)众所周知的行为,例如Levenshtein满足三角形不等式,因此可用于Burkhard-Keller树 阈值:仅当距离小于(1-X)*max(len(string1)、len(string2))时,才应将其视为“正”,并调整X(相似系数)以适合自己。选择X的一种方法是获得一个匹配样本,计算每个匹配的X,忽略X<例如0.8或0.9的情况,然后按X的降序对剩余部分进行排序,并对它们进行观察,插入正确的结果,计算不同级别X的一些错误成本度量
注意,你的ape/apple示例的距离为2,因此X为0.6。。。如果我在拼命寻找某个东西,并且有很高的假阴性惩罚,我只会使用低至0.75的阈值我知道这是不一样的,但你可以调整比率以过滤出不够相似的字符串,并返回与你要找的字符串最接近的匹配项 也许您会对语义相似性度量更感兴趣 我知道你们说过速度不是问题,但若你们正在为你们的算法处理大量的字符串,下面的内容是非常有用的
def spellcheck(self, sentence):
#return ' '.join([difflib.get_close_matches(word, wordlist,1 , 0)[0] for word in sentence.split()])
return ' '.join( [ sorted( { Levenshtein.ratio(x, word):x for x in wordlist }.items(), reverse=True)[0][1] for word in sentence.split() ] )
它比difflib快20倍左右
导入Levenshtein此代码段将计算两个字符串的difflib、Levenshtein、Sørensen和Jaccard相似性值。在下面的代码片段中,我迭代了一个tsv,其中感兴趣的字符串占据了tsv的
[3]
和[4]
列。(pip-install-python-Levenshtein
和pip-install-distance
):
关于第2点:阅读以下内容:。根据你的第2点,最好的相似性度量是只调用相同的字符串。任何模糊的东西都会有误报。。那么,接近人类的智慧,没有错误是我所寻找的。人类可以得出结论,阿佩尔和苹果是完全一样的,但猿不是。很可能我没有把我的观点说清楚。(1)“没有错误”是不可能的,即使是精确匹配。“苹果”(水果)!=“苹果”(计算机等制造商)。(2) 如果“接近人类的智能”是可用的,它既不是在一个完整的代码屏幕上,也不是免费的。(3)考虑使用一种允许换位的方法,它将Appel/Apple比猿/苹果和猿/ APP高。谢谢。这可能会给我一些好主意,但不是我想要的
get_close_matches('appel',['ape','peach','puppy'))
get me ape。我可以设置截止值,但从一些快速实验来看,误报太常见了。运行此操作时,我遇到了“IndexError:list index out-range”错误。为什么我会得到它?@FeyziBagirov你能用你的脚本和输入发布github的要点吗?
import codecs, difflib, Levenshtein, distance
with codecs.open("titles.tsv","r","utf-8") as f:
title_list = f.read().split("\n")[:-1]
for row in title_list:
sr = row.lower().split("\t")
diffl = difflib.SequenceMatcher(None, sr[3], sr[4]).ratio()
lev = Levenshtein.ratio(sr[3], sr[4])
sor = 1 - distance.sorensen(sr[3], sr[4])
jac = 1 - distance.jaccard(sr[3], sr[4])
print diffl, lev, sor, jac