Python nltk.metrics.Distance中Jaccard距离度量的实现与数学定义不一致?

Python nltk.metrics.Distance中Jaccard距离度量的实现与数学定义不一致?,python,nlp,nltk,distance,metric,Python,Nlp,Nltk,Distance,Metric,我正试图使用内置于nltk.metrics.Distance中的Jaccard Distance metric函数Jaccard_Distance()完成NLP分配,这时我注意到它的结果在我预期的上下文中没有意义 当我检查中的jaccard_distance()的实现时,我注意到它与jaccard索引的实现不一致 具体而言,nltk中的实现是: return (len(label1.union(label2)) - len(label1.intersection(label2)))/len(la

我正试图使用内置于
nltk.metrics.Distance
中的Jaccard Distance metric函数
Jaccard_Distance()
完成NLP分配,这时我注意到它的结果在我预期的上下文中没有意义

当我检查中的
jaccard_distance()
的实现时,我注意到它与jaccard索引的实现不一致

具体而言,
nltk
中的实现是:

return (len(label1.union(label2)) - len(label1.intersection(label2)))/len(label1.union(label2))
但根据定义,分子项应仅涉及两个集合的交集,这意味着正确的实现应为:

return len(label1.intersection(label2))/len(label1.union(label2))
当我用后者编写自己的函数时,我确实得到了我作业的正确答案。例如,我的任务是使用单词三叉图上的Jaccard距离,从一个全面的单词库(内置
nltk
)中为拼写错误的单词cormulent推荐一个正确的拼写建议

当我使用
nltk
中的
jaccard\u distance()
时,我得到了太多完美的匹配(距离函数的结果是
1.0
),根本不正确

当我在后一个实现中使用自己的函数时,我能够得到一个拼写建议corpulent,与cormulent的Jaccard距离为0.4,这是一个不错的建议


nltk
中的
jaccard\u distance()
是否存在错误?

您引用的两个公式的作用并不完全相同,但它们在数学上是相关的。从NLTK包中引用的第一个定义称为Jaccard距离(DJaccard)。你引用的第二个被称为Jaccard相似性(SimJaccard)


数学上,djacard=1-SimJaccard。这里的直觉是,它们越相似(SimJaccard越高),距离就越低(因此,DJaccard)。

你确定没有将Jaccard的索引与Jaccard的距离混淆吗

第一个确实应该按照您的建议进行计算,而第二个是
1-Jaccard_索引(A,B)
,这与NLTK实现中的情况完全相同

通过以下更改,实现速度更快(0.83 vs.1.29s=~35%):

def jaccard_distance(label1, label2):
    len_union = len(label1.union(label2))
    return (len_union - len(label1.intersection(label2)))/len_union
您可以按以下方式重复我的测试(集合的结构将改变计时-这只是一个示例):


谢谢大家的帮助!我现在也理解了
jaccard_distance()
nltk
实现中的分子项,它源于执行1-jaccard相似性。
from timeit import timeit

a = {1,4,6,7,5,7,9,234}
b = {1,43,66,7,85,7,89,234}

def jaccard_distance(label1, label2):
    len_union = len(label1.union(label2))
    return (len_union - len(label1.intersection(label2))) / len_union

def jaccard_distance2(label1, label2):
    return (len(label1.union(label2)) - len(label1.intersection(label2))) / len(label1.union(label2))


s1 = """a = {1,4,6,7,5,7,9,234}
b = {1,43,66,7,85,7,89,234}
def jaccard_distance(label1, label2):
     len_union = len(label1.union(label2))
     return (len_union - len(label1.intersection(label2))) / len_union
for i in range(100000):
     jaccard_distance(a,b)"""

s2 = """a = {1,4,6,7,5,7,9,234}
b = {1,43,66,7,85,7,89,234}
def jaccard_distance2(label1, label2):
     return (len(label1.union(label2)) - len(label1.intersection(label2))) / len(label1.union(label2))
for i in range(100000):
     jaccard_distance2(a,b)"""

print(timeit(stmt=s1, number=10))
print(timeit(stmt=s2, number=10))