如何用NumPy计算欧几里德距离?

2024-04-25 22:27:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在3D中有两点:

(xa, ya, za)
(xb, yb, zb)

我想计算一下距离:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

对于NumPy或Python,最好的方法是什么?我有:

a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

Tags: 方法numpy距离distsqrtarrayzbya
3条回答

使用^{}

dist = numpy.linalg.norm(a-b)

背后的理论:如Introduction to Data Mining所述

这是因为欧氏距离l2范数,numpy.linalg.norm中的ord参数的默认值是2。

enter image description here

在SciPy中有一个函数。它叫Euclidean

示例:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

对于任何对同时计算多个距离感兴趣的人,我使用perfplot(我的一个小项目)做了一些比较。

第一个建议是组织数据,使数组具有维度(3, n)(显然是C-连续的)。如果加法是在连续的第一维中进行的,则速度更快,如果将sqrt-sumaxis=0一起使用,将linalg.normaxis=0一起使用,或者

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))

这是最快的一个变种。(实际上,只有一行也是如此。)

在第二个轴上加起来的变量axis=1都要慢得多。

enter image description here


复制绘图的代码:

import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data[0]
    return numpy.linalg.norm(a - b, axis=1)


def linalg_norm_T(data):
    a, b = data[1]
    return numpy.linalg.norm(a - b, axis=0)


def sqrt_sum(data):
    a, b = data[0]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))


def sqrt_sum_T(data):
    a, b = data[1]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))


def scipy_distance(data):
    a, b = data[0]
    return list(map(distance.euclidean, a, b))


def sqrt_einsum(data):
    a, b = data[0]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))


def sqrt_einsum_T(data):
    a, b = data[1]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))


def setup(n):
    a = numpy.random.rand(n, 3)
    b = numpy.random.rand(n, 3)
    out0 = numpy.array([a, b])
    out1 = numpy.array([a.T, b.T])
    return out0, out1


perfplot.save(
    "norm.png",
    setup=setup,
    n_range=[2 ** k for k in range(22)],
    kernels=[
        linalg_norm,
        linalg_norm_T,
        scipy_distance,
        sqrt_sum,
        sqrt_sum_T,
        sqrt_einsum,
        sqrt_einsum_T,
    ],
    logx=True,
    logy=True,
    xlabel="len(x), len(y)",
)

相关问题 更多 >