我有两个向量,比如说
x=[2,4,6,7]
和 y=[2,6,7,8]
,我想找到每个对应对之间的欧几里得距离,或任何其他实现的距离(例如来自 scipy)。那将是
dist=[0, 2, 1, 1]
。
当我尝试时
dist = scipy.spatial.distance.cdist(x,y, metric='sqeuclidean')
或
dist = [scipy.spatial.distance.cdist(x,y, metric='sqeuclidean') for x,y in zip(x,y)]
我明白了
ValueError: XA must be a 2-dimensional array.
我应该如何计算 dist 以及为什么我必须为此目的重塑数据?
cdist 不计算对应对之间的距离列表,而是计算所有对之间的距离矩阵。
np.linalg.norm((np.asarray(x)-np.asarray(y))[:, None], axis=1)
对于 n 维点之间的欧几里得距离,id 通常是如何写的;但如果您只处理一维点,则 elpres 建议的绝对差异会更简单。
cdist
特别有用。
如果您需要仅比较 1 个向量与 1 个向量,或 1 个向量与多个向量进行比较,
np.linalg.norm
会更快:
>>> x: [1000, 5]
>>> %timeit np.linalg.norm(x - x[0], axis=-1)
29.7 µs ± 3.61 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
>>> %timeit scipy.spatial.distance.cdist(x, x[[0]])
47.3 µs ± 4.8 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
注意,无论如何你都需要向
cdist
传递一个 2d 数组,这可以通过 x[[0]]
来实现
>>> x: [1000, 5]
>>> y: [20, 5]
为此,numpy 有两种方法,循环和广播: 所有这些方法都会输出形状为
(x.shape[0], y.shape[0])
的二维数组
y.shape[0] < x.shape[0]
:>>> %%timeit
... res = np.empty((x.shape[0], y.shape[0]))
... for i in range(y.shape[0]):
... res[:, i] = np.linalg.norm(x - y[i], axis=-1)
745 µs ± 66.4 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
>>> %timeit np.linalg.norm(x[:, None] - y, axis=-1)
1.47 ms ± 161 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
使用
cdist
:
>>> %timeit scipy.spatial.distance.cdist(x, y)
95.5 µs ± 5.9 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
好处是显而易见的。
正如已接受答案的评论中提到的,您可以通过更改 numpy 中的
ord
和 scipy 中的 metric
来使用任何指标。