计算欧几里得距离的python方法的精度有啥不同吗?

Posted

技术标签:

【中文标题】计算欧几里得距离的python方法的精度有啥不同吗?【英文标题】:Is there any difference of precision in python methods to calculate euclidean distance?计算欧几里得距离的python方法的精度有什么不同吗? 【发布时间】:2020-05-15 07:50:18 【问题描述】:

我正在一个 numpy 数组中逐个数组计算欧几里得距离数组。我对此使用了np.linalg.norm(v1-v2)。由于我打算使用其他距离度量,因此我将其更改为 scipy.spatial.distance.euclidean(v1,v2) 以在我的代码中保留一个模式。

我注意到每个场景的最后一位数字都有所不同。我认为它不会因为 scipy euclidean 版本使用来自 numpy 核心的函数,如 dotsqrt。我在 Python 中尝试了其他方法来计算要比较的欧几里得距离,对于一个具体的例子,我得到了这些结果。

>>> math.sqrt(sum([(a-b)**2 for a,b in zip(v1,v2)]))
1.0065822095995844
>>> numpy.linalg.norm(v1-v2)
1.0065822095995838
>>> sklearn.metrics.pairwise.euclidean_distances(v1.reshape(1,-1),v2.reshape(1,-1))[0,0]
1.0065822095995838
>>> scipy.spatial.distance.euclidean(v1,v2)
1.006582209599584  

仅作记录,在我的示例中,v1 和 v2 是标准化直方图。 为什么精度会有这种差异?这应该发生吗?

【问题讨论】:

部分原因可能是求和算法不同。我认为numpy 使用pairwise summation,不确定默认的python sumsklearn 有趣。但即便如此,如果numpy 使用成对求和,scipy 使用numpy 核心函数,那么结果会是一样的,对吧?为什么不呢? 查看源代码,scipy.spatial.distance.euclidean 调用 minkowski,后者调用 scipy.linalg.norm,最后调用 blas 函数 nrm2(可能取决于 scipy 版本)。这与numpy 不同。从广义上讲,我认为从这些实现中接收略有不同的浮点输出似乎是正常的。 我倾向于认为这个问题是关于浮点计算不一致的一般问题的一个特例。 This 是一个稍微沉重但非常彻底的讨论。但 TLDR 是,在浮点运算中,计算相同值的不同方法会经常给出稍微不同(但非常接近)的结果。 【参考方案1】:

浮点数以分数形式存储在计算机中,用 53 位表示分子。因此,您无法获得精度超过 15 位有效数字的浮点答案。 https://docs.python.org/3/tutorial/floatingpoint.html

【讨论】:

以上是关于计算欧几里得距离的python方法的精度有啥不同吗?的主要内容,如果未能解决你的问题,请参考以下文章

识别差异的最佳方法:欧几里得距离、余弦距离还是简单减法?

欧几里得距离(python3,sklearn):有效地计算最近的对及其对应的距离

相似系数常用的有哪几种

计算两个python数组之间的欧几里得距离

在Python中使用欧几里得距离确定最近的位置

在Python中获取两个向量的欧几里得距离[重复]