Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python:计算向量到矩阵每一行的欧几里德距离的最快方法?_Python_Numpy_Numba - Fatal编程技术网

python:计算向量到矩阵每一行的欧几里德距离的最快方法?

python:计算向量到矩阵每一行的欧几里德距离的最快方法?,python,numpy,numba,Python,Numpy,Numba,考虑这段python代码,我试图计算向量到矩阵每一行的欧氏距离。与使用Tullio.jl可以找到的最好的Julia版本相比,它的速度非常慢 python版本需要30s,而Julia版本只需要75ms 我确信我在Python方面做得不是最好的。有更快的解决方案吗?欢迎使用Numba和numpy解决方案 import numpy as np # generate a = np.random.rand(4000000, 128) b = np.random.rand(128) print(a.s

考虑这段python代码,我试图计算向量到矩阵每一行的欧氏距离。与使用Tullio.jl可以找到的最好的Julia版本相比,它的速度非常慢

python版本需要30s,而Julia版本只需要75ms

我确信我在Python方面做得不是最好的。有更快的解决方案吗?欢迎使用Numba和numpy解决方案

import numpy as np

# generate
a = np.random.rand(4000000, 128)

b = np.random.rand(128)

print(a.shape)
print(b.shape)



def lin_norm_ever(a, b):
    return np.apply_along_axis(lambda x: np.linalg.norm(x - b), 1, a)


import time
t = time.time()
res = lin_norm_ever(a, b)
print(res.shape)
elapsed = time.time() - t
print(elapsed)
朱莉娅·弗瑞恩斯酒店

using Tullio
function comp_tullio(a, c)
    dist = zeros(Float32, size(a, 2))
    @tullio dist[i] = (c[j] - a[j,i])^2

    dist
end
@time comp_tullio(a, c)

@benchmark comp_tullio(a, c) # 75ms on my computer

在本例中,我将使用Numba以获得最佳性能。我还从Divakars链接答案中添加了两种方法进行比较

代码

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

@nb.njit(fastmath=True,parallel=True,cache=True)
def dist_1(mat,vec):
    res=np.empty(mat.shape[0],dtype=mat.dtype)
    for i in nb.prange(mat.shape[0]):
        acc=0
        for j in range(mat.shape[1]):
            acc+=(mat[i,j]-vec[j])**2
        res[i]=np.sqrt(acc)
    return res

#from https://stackoverflow.com/a/52364284/4045774
def dist_2(mat,vec):
    return cdist(mat, np.atleast_2d(vec)).ravel()

#from https://stackoverflow.com/a/52364284/4045774
def dist_3(mat,vec):
    M = mat.dot(vec)
    d = np.einsum('ij,ij->i',mat,mat) + np.inner(vec,vec) -2*M
    return np.sqrt(d)
计时

#Float64
a = np.random.rand(4000000, 128)
b = np.random.rand(128)
%timeit dist_1(a,b)
#122 ms ± 3.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_2(a,b)
#484 ms ± 3.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_3(a,b)
#432 ms ± 14.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

#Float32
a = np.random.rand(4000000, 128).astype(np.float32)
b = np.random.rand(128).astype(np.float32)
%timeit dist_1(a,b)
#68.6 ms ± 414 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_2(a,b)
#2.2 s ± 32.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#looks like there is a costly type-casting to float64
%timeit dist_3(a,b)
#228 ms ± 8.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

在本例中,我将使用Numba以获得最佳性能。我还从Divakars链接答案中添加了两种方法进行比较

代码

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

@nb.njit(fastmath=True,parallel=True,cache=True)
def dist_1(mat,vec):
    res=np.empty(mat.shape[0],dtype=mat.dtype)
    for i in nb.prange(mat.shape[0]):
        acc=0
        for j in range(mat.shape[1]):
            acc+=(mat[i,j]-vec[j])**2
        res[i]=np.sqrt(acc)
    return res

#from https://stackoverflow.com/a/52364284/4045774
def dist_2(mat,vec):
    return cdist(mat, np.atleast_2d(vec)).ravel()

#from https://stackoverflow.com/a/52364284/4045774
def dist_3(mat,vec):
    M = mat.dot(vec)
    d = np.einsum('ij,ij->i',mat,mat) + np.inner(vec,vec) -2*M
    return np.sqrt(d)
计时

#Float64
a = np.random.rand(4000000, 128)
b = np.random.rand(128)
%timeit dist_1(a,b)
#122 ms ± 3.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_2(a,b)
#484 ms ± 3.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_3(a,b)
#432 ms ± 14.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

#Float32
a = np.random.rand(4000000, 128).astype(np.float32)
b = np.random.rand(128).astype(np.float32)
%timeit dist_1(a,b)
#68.6 ms ± 414 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dist_2(a,b)
#2.2 s ± 32.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#looks like there is a costly type-casting to float64
%timeit dist_3(a,b)
#228 ms ± 8.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

此外,如果您使用链接问答答案中的方法5,则在距离上使用
np.sqrt
。使用方法2,
cdist(矩阵,np.atleast_2d(search_vec)).ravel()
。您查看了链接的问答吗?方法5和方法2回答问题。如果没有,我错过了什么?如果你能证明这些不适合你,我很乐意重新打开。在我的(非常新的8核)计算机上
comp_tullio
需要>400毫秒。你在运行多少个线程?我有6个线程,我在一年多前从Jsut得到了一个i7,我在Windows 10上的Julia 1.5上。此外,如果你使用链接问答答案中的方法#5,请在距离上使用
np.sqrt
。使用方法2,
cdist(矩阵,np.atleast_2d(search_vec)).ravel()
。您查看了链接的问答吗?方法5和方法2回答问题。如果没有,我错过了什么?如果你能证明这些不适合你,我很乐意重新打开。在我的(非常新的8核)计算机上
comp_tullio
需要>400毫秒。你在运行多少个线程?我有6个线程,一年多前我从Jsut得到了一个i7。我在Windows10上运行Julia 1.5。