计算两个三维矩阵之间的元素方向的欧氏距离的有效方法

时间:2018-03-26 08:49:25

标签: python-3.x numpy scipy

我有两个3D矩阵。 matrix1=dim(15,3)matrix2=dim(23,3)

例如:

matrix1=[[5,7,8],
[10,6,8],
...
...
...,
[11,14,78]]

matrix2=[[3,7,9],
[12,11,18],
...,
...,
[78,99,10]]

输出是什么?

matrix_distance=dim(15,23) 为了便于说明,我们只考虑第一个通道和第一行:

matrix_distance[:,:,0]=[(5-3)^2, (5-12)^2, ..., (5-78)^2]

计算它的有效和矢量化方法是什么?

EDIT1:

非矢量化解决方案

for i in np.arange(len(matrix1)):
    for j in np.arange(len(matrix2)):
        for channel in np.arange(matrix1[0,0,:]):
            matrix_distance[i,:,p]=(matrix1[i,:,p]-matrix2[j,:,p])^2

A = [[5,7,8]]

B = [[3,7,9],[3,7,9],[78,99,10]]

然后

c=[[(5-3)^2,(7-7)^2,(8-9)^2],[(5-3)^2,(7-7)^2,(8-9)^2],[(5-78)^2,(7-99)^2,(8-10)^2]]

2 个答案:

答案 0 :(得分:1)

使用scipy' cdist

In [8]: cdist(matrix1,matrix2).shape
Out[8]: (15, 23)

答案 1 :(得分:1)

作为scipy的cdist的替代品,你也可以使用Numba,它可以提供更好的性能。如果满足您的精度要求,也可以考虑仅使用32位浮点数进行计算。

import numpy as np
import numba as nb
import time
from scipy.spatial.distance import cdist

#Maybe calculation with 32bit floats is sufficient?
#creating random 32bit floats
vec_1=np.array(np.random.rand(10000,3),dtype=np.float32)
vec_2=np.array(np.random.rand(20000,3),dtype=np.float32)


@nb.njit(fastmath=True,parallel=True)
def calc_distance(vec_1,vec_2):
    assert vec_1.shape[1]==3 #Enable SIMD-Vectorization (adding some performance)
    assert vec_2.shape[1]==3 #Enable SIMD-Vectorization (adding some performance)

    res=np.empty((vec_1.shape[0],vec_2.shape[0]),dtype=vec_1.dtype)
    for i in nb.prange(vec_1.shape[0]):
        for j in range(vec_2.shape[0]):
            res[i,j]=np.sqrt((vec_1[i,0]-vec_2[j,0])**2+(vec_1[i,1]-vec_2[j,1])**2+(vec_1[i,2]-vec_2[j,2])**2)

    return res

t1=time.time()
res=calc_distance(vec_1,vec_2)
print(time.time()-t1)
t1=time.time()
A=cdist(vec_1,vec_2) #cdist approach
print(time.time()-t1)

这是一个四核i7-4.Gen 0.25s(Numba),1.3s cdist。用64位精度计算得到0.44s(Numba)。