Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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
Scipy CSR之间更快的Python余弦差异”;向量;_Python_Cython_Sparse Matrix_Jit_Numba - Fatal编程技术网

Scipy CSR之间更快的Python余弦差异”;向量;

Scipy CSR之间更快的Python余弦差异”;向量;,python,cython,sparse-matrix,jit,numba,Python,Cython,Sparse Matrix,Jit,Numba,这是一个经典的问题,但我相信很多人仍在寻找答案。 这个问题不同于,因为我的问题是两个稀疏向量(不是矩阵)之间的运算 我写了一篇关于余弦Scipy空间距离(SSD)在数据维度越来越高时变得越来越慢的文章(因为它在密集向量上工作)。这篇文章是用印尼语写的,但是代码、我的实验设置和结果应该很容易理解,不管是哪种语言(在文章的底部) 目前,此解决方案用于高维数据(与SSD相比)的速度快70多倍,并且内存效率更高: import numpy as np def fCosine(u,v):

这是一个经典的问题,但我相信很多人仍在寻找答案。 这个问题不同于,因为我的问题是两个稀疏向量(不是矩阵)之间的运算

我写了一篇关于余弦Scipy空间距离(SSD)在数据维度越来越高时变得越来越慢的文章(因为它在密集向量上工作)。这篇文章是用印尼语写的,但是代码、我的实验设置和结果应该很容易理解,不管是哪种语言(在文章的底部)

目前,此解决方案用于高维数据(与SSD相比)的速度快70多倍,并且内存效率更高:

    import numpy as np

    def fCosine(u,v): # u,v CSR vectors, Cosine Dissimilarity
        uData = u.data; vData = v.data
        denominator = np.sqrt(np.sum(uData**2)) * np.sqrt(np.sum(vData**2))
        if denominator>0:
            uCol = u.indices; vCol = v.indices # np array
            intersection = set(np.intersect1d(uCol,vCol))
            uI = np.array([u1 for i,u1 in enumerate(uData) if uCol[i] in intersection])
            vI = np.array([v2 for j,v2 in enumerate(vData) if vCol[j] in intersection])             
            return 1-np.dot(uI,vI)/denominator
        else:
            return float("inf")

是否有可能进一步改进该功能(Pythonic或通过JIT/Cython???。

这里有一个替代方案,
alt\u fCosine
,它(在我的机器上)对于大小为
10**5
10**4
非零元素的CSR向量,速度大约快3倍:

import scipy.sparse as sparse
import numpy as np
import math

def fCosine(u,v): # u,v CSR vectors, Cosine Dissimilarity
    uData = u.data; vData = v.data
    denominator = np.sqrt(np.sum(uData**2)) * np.sqrt(np.sum(vData**2))
    if denominator>0:
        uCol = u.indices; vCol = v.indices # np array
        intersection = set(np.intersect1d(uCol,vCol))
        uI = np.array([u1 for i,u1 in enumerate(uData) if uCol[i] in intersection])
        vI = np.array([v2 for j,v2 in enumerate(vData) if vCol[j] in intersection])             
        return 1-np.dot(uI,vI)/denominator
    else:
        return float("inf")

def alt_fCosine(u,v): 
    uData, vData = u.data, v.data
    denominator = math.sqrt(np.sum(uData**2) * np.sum(vData**2))
    if denominator>0:
        uCol, vCol = u.indices, v.indices 
        uI = uData[np.in1d(uCol, vCol)]
        vI = vData[np.in1d(vCol, uCol)]
        return 1-np.dot(uI,vI)/denominator
    else:
        return float("inf")

# Check that they return the same result
N = 10**5
u = np.round(10*sparse.random(1, N, density=0.1, format='csr'))
v = np.round(10*sparse.random(1, N, density=0.1, format='csr'))
assert np.allclose(fCosine(u, v), alt_fCosine(u, v))
alt\u fCosine
替换了两个列表理解,即调用
np.intersection1d
以及通过对
np.inad
和advanced的两次调用形成Python集 索引


对于
N=10**5

In [322]: %timeit fCosine(u, v)
100 loops, best of 3: 5.73 ms per loop

In [323]: %timeit alt_fCosine(u, v)
1000 loops, best of 3: 1.62 ms per loop

In [324]: 5.73/1.62
Out[324]: 3.537037037037037

太棒了,非常感谢。。。我想知道为什么math.sqrt比numpy.sqrt快?一般来说,数学对于简单域(标量/列表)更快吗?是的,
math.sqrt
对于标量更快。我怀疑
math
模块中的所有函数也是如此,因为与相应的NumPy函数不同,它们不必测试备用代码路径(如果array这样做,如果iterable这样做,等等)。