Python 为什么余弦距离比在scikitlearn中使用带DBSCAN算法的欧几里德距离慢得多
我将从packagePython 为什么余弦距离比在scikitlearn中使用带DBSCAN算法的欧几里德距离慢得多,python,scikit-learn,Python,Scikit Learn,我将从packagescikit learn中为DBSCAN算法使用两个度量(欧几里德距离和余弦相似性) 问题是,使用欧几里德距离比使用余弦相似性要快得多 守则: // using euclidean distance DBSCAN(eps=0.02, min_samples=5, metric="euclidean").fit(data) // using cosine similarity DBSCAN(eps=0.02, min_samples=5, metric=cosine_
scikit learn
中为DBSCAN算法使用两个度量(欧几里德距离和余弦相似性)
问题是,使用欧几里德距离比使用余弦相似性要快得多
守则:
// using euclidean distance
DBSCAN(eps=0.02, min_samples=5, metric="euclidean").fit(data)
// using cosine similarity
DBSCAN(eps=0.02, min_samples=5, metric=cosine_distance).fit(data)
有人知道余弦相似性导致速度差异的原因吗?我对scikit学习一无所知,但我可以从数学角度猜出为什么速度会慢一些
定义 假设有两个n维向量(A和B) 计算结果如下:
Sqrt((A_1 - B_1)^2 + (A_2 - B_2)^2 + ... + (A_N - B_N)^2)
其中A_m
是A中的第m
个元素。要计算它,需要计算n个差值、n个乘积和1平方根
定义为
cos(x) = A.B / |A||B|
在哪里
因此,A.B
的n次乘法和2.n次乘法得到|A
和|B
比较 欧几里德距离需要n次减法和n次乘法;余弦相似性需要3.n次乘法 假设减法在计算上是密集型的(几乎可以肯定的是,它的密集度会更低),那么欧几里德的减法是2.n,而余弦的减法是3.n
换句话说,得到余弦差至少比欧几里德距离慢50%。我不知道
scikit-learn
是如何使用这些指标的,也不知道您的n有多大,但这可能是您看到差异的原因。我对scikit-learn
一无所知,但我可以从数学角度猜出为什么它可能会慢一些
定义 假设有两个n维向量(A和B) 计算结果如下:
Sqrt((A_1 - B_1)^2 + (A_2 - B_2)^2 + ... + (A_N - B_N)^2)
其中A_m
是A中的第m
个元素。要计算它,需要计算n个差值、n个乘积和1平方根
定义为
cos(x) = A.B / |A||B|
在哪里
因此,A.B
的n次乘法和2.n次乘法得到|A
和|B
比较 欧几里德距离需要n次减法和n次乘法;余弦相似性需要3.n次乘法 假设减法在计算上是密集型的(几乎可以肯定的是,它的密集度会更低),那么欧几里德的减法是2.n,而余弦的减法是3.n
换句话说,得到余弦差至少比欧几里德距离慢50%。我不知道scikit learn如何使用这些指标,也不知道您的n有多大,但这可能是您看到差异的原因。假设
余弦距离
是一个Python函数:
虽然sklearn允许您指定自定义距离函数,但其性能并不是特别好。对于每一个距离,它都需要在Python解释器中设置一个回调。这自然比内置函数使用的编译本机代码慢得多
Python似乎无法很快解决这一开销。可能需要修改sklearn源代码(添加新的内置代码),或者使用类似Java的东西来实现良好的JIT(例如,ELKI可以通过这种方式扩展,并且对于自定义距离来说速度更快)
Jython听起来很酷(JVM上的Python),但据我所知,它不支持numpy,因此也不支持sklearn。我不知道它是否可以将Python编译成字节码,或者它是否只是一个解释器。假设
余弦距离
是一个Python函数:
虽然sklearn允许您指定自定义距离函数,但其性能并不是特别好。对于每一个距离,它都需要在Python解释器中设置一个回调。这自然比内置函数使用的编译本机代码慢得多
Python似乎并没有很快解决这种开销。可能需要修改sklearn源代码(添加新的内置代码),或者使用类似Java的东西来实现良好的JIT(例如,ELKI可以通过这种方式扩展,并且对于自定义距离来说速度更快)
Jython听起来很酷(JVM上的Python),但据我所知,它不支持numpy,因此也不支持sklearn。我不知道它是否能将Python编译成字节码,或者它只是一个解释器。函数cosine_距离是sklearn.metrics.pairwise的距离吗?这就是所谓的余弦距离,不是吗?函数余弦距离是来自sklearn.metrics.pairwise的吗?这就是所谓的余弦距离,不是吗?这很好&对一个例子来说是正确的,但大多数用例都是在一个对象和多个其他对象之间找到的,或者是重复的。在这种情况下,每个向量的范数可以与向量本身一起存储,因此可以为每个迭代保存每个向量的范数。在欧几里得距离中,您将无法添加此优化,因为整个计算都基于两个向量。这很好&正确,对于单个示例也是正确的,但大多数用例都是在一个对象和多个其他对象之间查找,或者重复。在这种情况下,每个向量的范数可以与向量本身一起存储,因此可以为每个迭代保存每个向量的范数。在欧几里得距离中,您将无法添加此优化,因为整个计算都基于两个向量