Python中的多维欧几里得距离
Posted
技术标签:
【中文标题】Python中的多维欧几里得距离【英文标题】:Multidimensional Euclidean Distance in Python 【发布时间】:2012-03-13 22:58:10 【问题描述】:我想计算 2 个数组之间的多维(24 维)欧几里得距离。我正在使用 numpy-Scipy。
这是我的代码:
import numpy,scipy;
A=numpy.array([116.629, 7192.6, 4535.66, 279714, 176404, 443608, 295522, 1.18399e+07, 7.74233e+06, 2.85839e+08, 2.30168e+08, 5.6919e+08, 168989, 7.48866e+06, 1.45261e+06, 7.49496e+07, 2.13295e+07, 3.74361e+08, 54.5, 3349.39, 262.614, 16175.8, 3693.79, 205865]);
B=numpy.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151246, 6795630, 4566625, 2.0355328e+08, 1.4250515e+08, 3.2699482e+08, 95635, 4470961, 589043, 29729866, 6124073, 222.3]);
但是,我使用scipy.spatial.distance.cdist(A[numpy.newaxis,:],B,'euclidean')
来计算欧几里登距离。
但它给了我一个错误
raise ValueError('XB must be a 2-dimensional array.');
我好像不明白。
我查了scipy.spatial.distance.pdist
但是不明白怎么用?
还有其他更好的方法吗?
【问题讨论】:
或许scipy.spatial.distance.euclidean
?
那么,你有 2、24 维点?在这种情况下,@Mr.E 的回答是最好的选择。但是,当你有超过 2 个点时,各种scipy.spatial.distance
函数会更高效。
我想也许我错过了什么。如果可以解决您的问题,则作为答案发布。
我想谈谈你很久以前收到的错误,它可能会帮助其他有需要的人。从文档中读取数组 A 和 B 需要具有相同的维度。这意味着如果您的第一个数组 A 具有二维形状(就像您使用 A[numpy.newaxis,:]
定义的那样),那么您的第二个数组也需要具有相同的维度。因此,写B[numpy.newaxis,:]
应该可以解决错误。
@JoeKington 谁是 Mr.E!? :)
【参考方案1】:
编写自己的自定义平方根和平方并不总是安全的
您可以使用 math.hypot、numpy.hypot 或 scipy 距离函数,而不是编写 numpy.sqrt(numpy.sum((A - B)**2))
或 (i**2 + j**2)**0.5
。在您的情况下,它们可能会溢出
refer
速度方面
%%timeit
math.hypot(*(A - B))
# 3 µs ± 64.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
numpy.sqrt(numpy.sum((A - B)**2))
# 5.65 µs ± 50.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
安全方面
下溢
i, j = 1e-200, 1e-200
np.sqrt(i**2+j**2)
# 0.0
溢出
i, j = 1e+200, 1e+200
np.sqrt(i**2+j**2)
# inf
没有下溢
i, j = 1e-200, 1e-200
np.hypot(i, j)
# 1.414213562373095e-200
无溢出
i, j = 1e+200, 1e+200
np.hypot(i, j)
# 1.414213562373095e+200
【讨论】:
【参考方案2】:从Python 3.8
开始,您可以使用标准库的math
模块及其新的dist
函数,该函数返回两点之间的欧几里得距离(以坐标列表或元组形式给出):
from math import dist
dist([1, 0, 0], [0, 1, 0]) # 1.4142135623730951
【讨论】:
而且它明显比 scipy 的欧几里得函数快! +1【参考方案3】:也许是scipy.spatial.distance.euclidean
?
例子
>>> from scipy.spatial import distance >>> distance.euclidean([1, 0, 0], [0, 1, 0]) 1.4142135623730951 >>> distance.euclidean([1, 1, 0], [0, 1, 0]) 1.0
【讨论】:
【参考方案4】:由于以上所有答案都涉及到 numpy 和/或 scipy,我只想指出,这里的 reduce 可以完成一些非常简单的事情
def n_dimensional_euclidean_distance(a, b):
"""
Returns the euclidean distance for n>=2 dimensions
:param a: tuple with integers
:param b: tuple with integers
:return: the euclidean distance as an integer
"""
dimension = len(a) # notice, this will definitely throw a IndexError if len(a) != len(b)
return sqrt(reduce(lambda i,j: i + ((a[j] - b[j]) ** 2), range(dimension), 0))
这将对维度数中的所有 j 求和所有 (a[j] - b[j])^2 对(请注意,为简单起见,这不支持 n
【讨论】:
【参考方案5】:除了已经提到的计算欧几里得距离的方法之外,还有一种与您的原始代码接近的方法:
scipy.spatial.distance.cdist([A], [B], 'euclidean')
或
scipy.spatial.distance.cdist(np.atleast_2d(A), np.atleast_2d(B), 'euclidean')
这将返回一个 1×1 np.ndarray
保持 L2 距离。
【讨论】:
【参考方案6】:A
和 B
是 24 维空间中的 2 个点。你应该使用scipy.spatial.distance.euclidean
。
Doc here
scipy.spatial.distance.euclidean(A, B)
【讨论】:
【参考方案7】:使用任一
numpy.sqrt(numpy.sum((A - B)**2))
或者更简单
numpy.linalg.norm(A - B)
【讨论】:
以上是关于Python中的多维欧几里得距离的主要内容,如果未能解决你的问题,请参考以下文章