在三维空间中有两个点
a = (ax, ay, az)
b = (bx, by, bz)
我想计算它们之间的距离:
dist = sqrt((ax-bx)^2 + (ay-by)^2 + (az-bz)^2)
我如何用NumPy做到这一点?我有:
import numpy
a = numpy.array((ax, ay, az))
b = numpy.array((bx, by, bz))
在三维空间中有两个点
a = (ax, ay, az)
b = (bx, by, bz)
我想计算它们之间的距离:
dist = sqrt((ax-bx)^2 + (ay-by)^2 + (az-bz)^2)
我如何用NumPy做到这一点?我有:
import numpy
a = numpy.array((ax, ay, az))
b = numpy.array((bx, by, bz))
当前回答
计算多维空间的欧氏距离:
import math
x = [1, 2, 6]
y = [-2, 3, 2]
dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
5.0990195135927845
其他回答
对于大量的距离,我能想到的最快的解决方案是使用numexpr。在我的机器上,它比使用numpy einsum更快:
import numexpr as ne
import numpy as np
np.sqrt(ne.evaluate("sum((a_min_b)**2,axis=1)"))
一个很好的句子:
dist = numpy.linalg.norm(a-b)
但是,如果速度是一个问题,我建议在您的机器上进行试验。我发现,在我的机器上,使用数学库的√rt和**运算符对平方进行运算要比使用一行NumPy解决方案快得多。
我用这个简单的程序进行了测试:
#!/usr/bin/python
import math
import numpy
from random import uniform
def fastest_calc_dist(p1,p2):
return math.sqrt((p2[0] - p1[0]) ** 2 +
(p2[1] - p1[1]) ** 2 +
(p2[2] - p1[2]) ** 2)
def math_calc_dist(p1,p2):
return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
math.pow((p2[1] - p1[1]), 2) +
math.pow((p2[2] - p1[2]), 2))
def numpy_calc_dist(p1,p2):
return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))
TOTAL_LOCATIONS = 1000
p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
for j in range(0, TOTAL_LOCATIONS):
dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
total_dist += dist
print total_dist
在我的机器上,math_calc_dist运行得比numpy_calc_dist快得多:1.5秒对23.5秒。
为了在fastst_calc_dist和math_calc_dist之间获得一个可测量的差异,我必须将TOTAL_LOCATIONS增加到6000。然后,fastst_calc_dist耗时约50秒,math_calc_dist耗时约60秒。
您也可以尝试使用numpy。SQRT和numpy。不过这两个运算都比我机器上的数学运算要慢。
我的测试使用Python 2.6.6运行。
首先求两个矩阵的差。然后,使用numpy的multiply命令应用元素乘法。然后,求元素与新矩阵相乘的和。最后,求求和的平方根。
def findEuclideanDistance(a, b):
euclidean_distance = a - b
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)
return euclidean_distance
其他答案适用于浮点数,但不能正确计算整数dtype的距离,因为整数dtype容易溢出和下溢。注意,即使scipy.distance.euclidean也有这个问题:
>>> a1 = np.array([1], dtype='uint8')
>>> a2 = np.array([2], dtype='uint8')
>>> a1 - a2
array([255], dtype=uint8)
>>> np.linalg.norm(a1 - a2)
255.0
>>> from scipy.spatial import distance
>>> distance.euclidean(a1, a2)
255.0
这是很常见的,因为许多图像库将图像表示为dtype="uint8"的ndarray。这意味着,如果你有一个由深灰色像素组成的灰度图像(比如所有像素的颜色都是#000001),你将它与黑色图像(#000000)进行区分,你最终可以在所有单元格中得到x-y为255的图像,这表明两张图像彼此相距很远。对于无符号整数类型(例如uint8),你可以安全地在numpy中计算距离:
np.linalg.norm(np.maximum(x, y) - np.minimum(x, y))
对于有符号整型,可以先转换为浮点类型:
np.linalg.norm(x.astype("float") - y.astype("float"))
对于图像数据,你可以使用opencv的norm方法:
import cv2
cv2.norm(x, y, cv2.NORM_L2)
从Python 3.8开始,math模块直接提供dist函数,它返回两点之间的欧几里得距离(以元组或坐标列表的形式给出):
from math import dist
dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845
如果你使用列表:
dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845