结论第一:
从使用timeit进行效率测试的测试结果,我们可以得出关于效率:
Method5 (zip, math.sqrt) > Method1 (numpy.linalg.norm) > Method2 (scipy.spatial.distance) > Method3 (sklearn.metrics.pairwise.euclidean_distances )
虽然我没有真正测试您的Method4,因为它不适合一般情况,它通常等同于Method5。
对于其余的,相当令人惊讶的是,Method5 是最快的。而对于使用numpy 的Method1,正如我们预期的那样,它在C 中进行了大量优化,是第二快的。
对于scipy.spatial.distance,如果你直接进入函数定义,你会看到它实际上是在使用numpy.linalg.norm,除了它会在实际numpy.linalg.norm之前对两个输入向量进行验证。这就是为什么它比numpy.linalg.norm 稍慢。
最后是sklearn,根据文档:
与其他计算距离的方法相比,此公式有两个优点。首先,它在处理稀疏数据时具有计算效率。其次,如果一个参数变化而另一个参数保持不变,则可以预先计算 dot(x, x) 和/或 dot(y, y)。
但是,这不是进行此计算的最精确方式,并且此函数返回的距离矩阵可能不是完全对称的要求
由于在您的问题中您想使用一组固定的数据,因此没有体现这种实现的优势。而且由于性能和精度之间的权衡,它也给出了所有方法中最差的精度。
关于精度,Method5=Metho1=Method2>Method3
效率测试脚本:
import numpy as np
from scipy.spatial import distance
from sklearn.metrics.pairwise import euclidean_distances
import math
# 1
def eudis1(v1, v2):
return np.linalg.norm(v1-v2)
# 2
def eudis2(v1, v2):
return distance.euclidean(v1, v2)
# 3
def eudis3(v1, v2):
return euclidean_distances(v1, v2)
# 5
def eudis5(v1, v2):
dist = [(a - b)**2 for a, b in zip(v1, v2)]
dist = math.sqrt(sum(dist))
return dist
dis1 = (52, 106, 35, 12)
dis2 = (33, 153, 75, 10)
v1, v2 = np.array(dis1), np.array(dis2)
import timeit
def wrapper(func, *args, **kwargs):
def wrapped():
return func(*args, **kwargs)
return wrapped
wrappered1 = wrapper(eudis1, v1, v2)
wrappered2 = wrapper(eudis2, v1, v2)
wrappered3 = wrapper(eudis3, v1, v2)
wrappered5 = wrapper(eudis5, v1, v2)
t1 = timeit.repeat(wrappered1, repeat=3, number=100000)
t2 = timeit.repeat(wrappered2, repeat=3, number=100000)
t3 = timeit.repeat(wrappered3, repeat=3, number=100000)
t5 = timeit.repeat(wrappered5, repeat=3, number=100000)
print('\n')
print('t1: ', sum(t1)/len(t1))
print('t2: ', sum(t2)/len(t2))
print('t3: ', sum(t3)/len(t3))
print('t5: ', sum(t5)/len(t5))
效率测试输出:
t1: 0.654838958307
t2: 1.53977598714
t3: 6.7898791732
t5: 0.422228400305
精度测试脚本和结果:
In [8]: eudis1(v1,v2)
Out[8]: 64.60650122085238
In [9]: eudis2(v1,v2)
Out[9]: 64.60650122085238
In [10]: eudis3(v1,v2)
Out[10]: array([[ 64.60650122]])
In [11]: eudis5(v1,v2)
Out[11]: 64.60650122085238