使用numpy在多维数据上矢量化欧几里德距离的外环

时间:2016-03-30 04:56:33

标签: python arrays numpy

我有一个二维值矩阵。每行都是一个数据点。

data = np.array(
   [[2, 2, 3],
    [4, 2, 4],
    [1, 1, 4]])

现在,如果我的测试点是单个1D numpy数组,如:

test = np.array([2,3,3])

我可以做一些简单的事情,比如np.sqrt(np.sum((test-data)**2,axis=1))来计算测试点相对于所有三个数据点的距离。

但是,如果测试本身是要测试的2D点阵,那么上面的工作并没有用,我一直在使用类似的东西:

test = np.array([[2,3,3],[4,1,2]])    
for i in range(len(test)):
    print np.sqrt(np.sum((test[i]-data)**2,axis=1))

>>> [ 1.          2.44948974  2.44948974]
    [ 2.44948974  2.23606798  3.60555128]

为了计算我的测试集中针对数据集中所有点的每个点。看起来应该有一种方法可以对整个操作进行矢量化,这样我就可以得到一个相应距离的(2,3)矩阵,而没有外部的FOR循环

(注意:虽然这个特殊的例子是关于欧几里德距离的,但我发现自己有类似的类型操作,我想对一个矩阵的所有元素和另一个矩阵的各个元素执行一个操作,所以我' m希望有一种使用Numpy设置这种性质问题的通用方法。)

3 个答案:

答案 0 :(得分:2)

使用broadcasting来执行此操作:

from numpy.linalg import norm
norm(data-test[:,None],axis=2)

[ 1.          2.44948974  2.44948974]
[ 2.44948974  2.23606798  3.60555128]

一些解释。例如,用不同的形状,四点和两点来理解它更容易:

ens1 = np.array(
   [[2, 2, 3],
    [4, 2, 4],
    [1, 1, 4],
    [2, 4, 5]])


ens2 = np.array([[2,3,3],
                 [4,1,2]])  


In [16]: ens1.shape
Out[16]: (4, 3)

In [17]: ens2.shape
Out[17]: (2, 3)   

然后:

In [21]: ens2[:,None].shape 
Out[21]: (2, 1, 3) 

添加新维度。现在我们可以进行2X4 = 8次减法:

In [22]: (ens1-ens2[:,None]).shape
Out[22]: (2, 4, 3)       

并沿着最后一个轴取标准,持续8个距离:

In [23]: norm(ens1-ens2[:,None],axis=2)
Out[23]: 
array([[ 1.        ,  2.44948974,  2.44948974,  2.23606798],
       [ 2.44948974,  2.23606798,  3.60555128,  4.69041576]])     

答案 1 :(得分:1)

np.meshgrid怎么样?

import numpy as np

data = np.array(
   [[2, 2, 3],
    [4, 2, 4],
    [1, 1, 4]])


test = np.array([[2,3,3],
                 [4,1,2]])   


d = np.arange(0,3)
t = np.arange(0,2)
d, t = np.meshgrid(d, t)

# print test[t]
# print data[d]
print np.sqrt(np.sum((test[t]-data[d])**2,axis=2))  

输出:

[[ 1.          2.44948974  2.44948974]
 [ 2.44948974  2.23606798  3.60555128]]

答案 2 :(得分:-2)

您可以使用列表理解:

result = np.array([np.sqrt(np.sum((t - data)**2, axis=1)) for t in test])