【问题标题】:Vectorize over only one axis in a 2D array with numpy vectorize使用 numpy vectorize 在二维数组中仅对一个轴进行矢量化
【发布时间】:2014-07-29 08:43:03
【问题描述】:

我有以下函数来获取两个向量ab 之间的欧几里得距离。

def distance_func(a,b):
    distance = np.linalg.norm(b-a)
    return distance

在这里,我希望 a 成为向量数组的一个元素。所以我使用 numpy vectorize 来遍历数组。 (为了获得比使用 for 循环迭代更好的速度)

vfunc = np.vectorize(distance_func)

我用它来得到一个欧几里得距离数组

a = np.array([[1,2],[2,3],[3,4],[4,5],[5,6]])
b = np.array([1,2])

vfunc(a,b)

但是这个函数返回:

数组([[ 0., 0.], [1., 1.], [2., 2.], [3., 3.], [4., 4.]])

这是对第二个向量单独执行np.linalg.norm(a-b) 操作的结果。 如何使用 numpy vectorize 以这种方式获取欧几里得距离数组?

【问题讨论】:

  • 来自vectorize 文档:The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.

标签: python arrays python-2.7 numpy vectorization


【解决方案1】:

你不需要使用vectorize,你可以这样做:

a = np.array([[1,2],[2,3],[3,4],[4,5],[5,6]])
b = np.array([1,2])

np.linalg.norm(a-b, axis=1)

给出:

[ 0.          1.41421356  2.82842712  4.24264069  5.65685425]

(我假设这是您想要的,但如果不是,请同时显示您对示例的期望结果。)

【讨论】:

  • 是的,这正是我所期望的。但这与我使用 for 循环遍历 a 并为 ab 中的每个向量获取 np.linalg.norm() 所需的时间相同。没有其他方法可以加快速度吗?
  • 这是矢量化的。 numpy 的大部分加速来自于处理更大的数组,事实上,对于非常小的数组,numpy 甚至可能会慢一些。这是(5x2)您实际想要使用的数组大小吗?
  • 没有。实际上我想在大型阵列上使用它。如(4000x3000)。
  • @maheshakya:那么你会发现这种方法比 python 循环要快得多。我不会运行时序测试,因为您已经有了自己喜欢的答案,但我怀疑您最初使用的 norm 方法在速度上与 @eikenberg 建议的方法相当(如果 norm 对您普遍的问题有效-- 我不确定你想如何将 (2x1)*(2x5) 的问题陈述扩展到 4000x3000)。
【解决方案2】:

如果您想计算所有数据点之间的欧几里德距离,您应该使用为此提供的函数之一

from sklearn.metrics import euclidean_distances
from scipy.spatial import distance_matrix

它们经过优化,可以以完全矢量化的方式计算几个点 a几个b 的距离。

import numpy as np
a = np.random.randn(100, 2)
b = np.random.randn(200, 2)

d1 = euclidean_distances(a, b)
d2 = distance_matrix(a, b, p=2)
print d1.shape  # yields (100, 200), one distance for each possible couple
print d2.shape

速度考虑

In [90]: %timeit d1 = euclidean_distances(a, b)
1000 loops, best of 3: 403 us per loop

In [91]: %timeit d2 = distance_matrix(a, b, p=2)
1000 loops, best of 3: 699 us per loop

【讨论】:

  • 我怀疑您能否从sklearn.metrics.euclidean_distances 获得很多速度。我试过了,但是numpy.linalg.norm 方法比 sklearns 的方法要快一些。
  • 您知道如何按照scipy.spacial.distance_matrix 的问题中描述的方式进行操作吗?这个版本你给了每对可能的返回距离。
  • 如果您将b 减少为一个向量(例如b = np.array([[0, 1]])),那么,如果我正确理解了这个问题,这应该会减少到您正在寻找的内容(到b 的距离为a 的每个向量,对吧?)
  • 是的。这正是我在问题中提到的。而且速度也更快。
猜你喜欢
  • 1970-01-01
  • 2018-01-09
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 2019-10-21
  • 1970-01-01
  • 2017-12-17
相关资源
最近更新 更多