不确定我的标题是否正确,但基本上我有一个(x,y,z)格式的参考坐标,并且也有该格式的大型坐标列表/数组。我需要获得两者之间的欧几里得距离,因此从理论上讲,使用numpy和scipy,我应该能够执行以下操作:
import numpy, scipy.spatial.distance
a = numpy.array([1,1,1])
b = numpy.random.rand(20,3)
distances = scipy.spatial.distance.euclidean(b, a)
但是我没有得到一个数组,而是得到了一个错误:ValueError: Input vector should be 1-D.
不确定如何解决此错误并获得我想要的内容,而不必求助于循环等,这与使用Numpy的目的相抵触。
长期来看,我想使用这些距离来计算真假掩码,以计算垃圾箱中的距离值。
我不确定我是在使用错误的函数还是使用错误的函数,我无法在文档中找到任何能更好地工作的东西。
答案 0 :(得分:3)
scipy.spatial.distance.euclidean
的{{3}}指出,仅允许将一维矢量作为输入。因此,您必须像这样遍历数组:
distances = np.empty(b.shape[0])
for i in range(b.shape[0]):
distances[i] = scipy.spatial.distance.euclidean(a, b[i])
如果要使用向量化的实现,则需要编写自己的函数。也许将np.vectorize
与正确的签名一起使用也可以,但是实际上这也是for循环的简捷方式,因此其性能与简单的for循环相同。
正如我对hannes wittingham的解决方案的评论中所述,我将发布一个侧重于性能的单线:
distances = ((b - a)**2).sum(axis=1)**0.5
写出所有计算将减少单独函数调用的次数,从而将中间结果分配给新数组。因此,对于b.shape == (20, 3)
的阵列形状,它比使用Hannes wittingham的解决方案快约22%,而对于形状为b.shape == (20000, 3)
的阵列,它要快约5%。
a = np.array([1, 1, 1,])
b = np.random.rand(20, 3)
%timeit ((b - a)**2).sum(axis=1)**0.5
# 5.37 µs ± 140 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit euclidean_distances(a, b)
# 6.89 µs ± 345 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
b = np.random.rand(20000, 3)
%timeit ((b - a)**2).sum(axis=1)**0.5
# 588 µs ± 43.2 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit euclidean_distances(a, b)
# 616 µs ± 36.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
:
scipy.spatial.distance
但是,您正在失去可以轻松更改为距离计算例程的灵活性。使用numba
模块时,您可以通过简单地调用其他方法来更改计算路由。
要进一步提高计算性能,可以对函数使用import numba as nb
@nb.njit
def euc(a, b):
return ((b - a)**2).sum(axis=1)**0.5
之类的jit(及时)编译器:
axis
对于小型阵列,这减少了大约70%的计算时间,对于大型阵列,减少了大约60%的计算时间。不幸的是,np.linalg.norm
还不支持numba
的{{1}}关键字。
答案 1 :(得分:3)
编写自己的函数来完成此操作实际上并不难-这是我的,欢迎您使用。
如果要在大量点上执行此操作,并且速度很重要,我想此功能将大大超越基于for循环的速度解决方案-numpy旨在提高执行操作时的效率在整个矩阵上。
import numpy
a = numpy.array([1,1,1])
b = numpy.random.rand(20,3)
def euclidean_distances(ref_point, co_ords_array):
diffs = co_ords_array - ref_point
sqrd_diffs = numpy.square(diffs)
sum_sqrd_diffs = numpy.sum(sqrd_diffs, axis = 1)
euc_dists = numpy.sqrt(sum_sqrd_diffs)
return euc_dists
答案 2 :(得分:1)
此代码将获得欧几里得范式,该范式在许多情况下都应该有效,并且相当快,而且只有一行。根据需要,其他方法会更高效或更灵活,我会根据所完成的工作赞成其他一些解决方案。
import numpy
a = numpy.array([1,1,1])
b = numpy.random.rand(20,3)
distances = numpy.linalg.norm(a - b, axis = 1)
答案 3 :(得分:1)
请注意[]
的定义中还有a
的集合
import numpy, scipy.spatial.distance
a = numpy.array([[1,1,1]])
b = numpy.random.rand(20,3)
distances = scipy.spatial.distance.cdist(b, a, metric='euclidean')