经过一些在线研究(1、2、numpy、scipy、scikit、math),我找到了几种计算Python中欧氏距离的方法:
# 1
numpy.linalg.norm(a-b)
# 2
distance.euclidean(vector1, vector2)
# 3
sklearn.metrics.pairwise.euclidean_distances
# 4
sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
# 5
dist = [(a - b)**2 for a, b in zip(vector1, vector2)]
dist = math.sqrt(sum(dist))
# 6
math.hypot(x, y)
我想知道是否有人能提供一个洞察,在效率和精度方面,上面哪一个(或我没有发现的任何其他)被认为是最好的。如果有人知道任何资源讨论的主题也将是伟大的。
我感兴趣的上下文是计算数元组对之间的欧几里德距离,例如(52, 106, 35, 12)
和(33, 153, 75, 10)
之间的距离。
作为一般的经验法则,尽可能遵循
scipy
和numpy
实现,因为它们是矢量化的,并且比本机Python代码快得多。(主要原因是:在C中实现,矢量化消除了循环的类型检查开销。)(旁白:我的答案不包括精确性,但我认为同样的原则也适用于精确性和效率。)
作为一点额外的收获,我将提供一些关于如何配置代码以衡量效率的信息。如果您使用的是IPython解释器,那么秘诀就是使用
%prun
行魔术。%prun
所做的是告诉您一个函数调用需要多长时间才能运行,包括一些跟踪来找出瓶颈可能在哪里。在这种情况下,scipy.spatial.distance.euclidean
和numpy.linalg.norm
实现都非常快。假设您定义了一个函数dist(vect1, vect2)
,那么您可以使用相同的IPython magic调用进行分析。另一个额外的好处是,%prun
也可以在Jupyter笔记本中工作,您可以通过简单地将%%prun
设为该单元格的第一行来对整个代码单元格(而不仅仅是一个函数)进行%%prun
配置。这并不能完全回答这个问题,但可能值得一提的是,如果您对实际的欧几里德距离不感兴趣,而只想比较欧几里德距离,那么平方根就是单调函数,即x**(1/2)<;y**(1/2)当且仅当x<;y
所以,如果你不想要显式的距离,但例如只想知道向量1的欧几里德距离是否更接近一个向量列表,称为向量列表,你可以避免昂贵的(在精度和时间方面)平方根,但可以做一些类似的事情
min(vectorlist, key = lambda compare: sum([(a - b)**2 for a, b in zip(vector1, compare)])
结论一:
从使用
timeit
进行效率测试的结果中,我们可以得出关于效率的结论:Method5 (zip, math.sqrt)
>;Method1 (numpy.linalg.norm)
>;Method2 (scipy.spatial.distance)
>;Method3 (sklearn.metrics.pairwise.euclidean_distances )
虽然我并没有真正测试您的
Method4
,因为它不适合一般情况,并且通常相当于Method5
。对其他人来说,
Method5
是最快的。而对于使用Method1
的numpy
,正如我们所期望的,在C语言中经过了大量优化,是第二快的。对于
scipy.spatial.distance
,如果直接转到函数定义,您将看到它实际上正在使用numpy.linalg.norm
,除了它将在实际的numpy.linalg.norm
之前对两个输入向量执行验证。这就是它比tnumpy.linalg.norm
稍慢的原因。最后对于
sklearn
,根据文档:因为在您的问题中,您希望使用一组固定的数据,所以这个实现的优势没有得到体现。由于性能和精度之间的折衷,它也给出了所有方法中最差的精度。
关于精度,
Method5
=Metho1
=Method2
>;Method3
效率测试脚本:
效率测试输出:
精度测试脚本和结果:
相关问题 更多 >
编程相关推荐