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))