sciPy稀疏矩阵上的numpy.allclose()

时间:2017-07-17 01:29:52

标签: python numpy scipy sparse-matrix

def simrank_sparse(A,c,maxiter,eps=1e-4):

    if not sp.issparse(A):
        raise Exception("Input is not a sparse matrix ")

    n=sp.csr_matrix.get_shape(A)[0]
    Q=misc.get_column_normalized_matrix(A)
    sim=sp.eye(n)
    I=sp.eye(n)
    sim_prev=sp.csr_matrix(sim)

    for t in range(maxiter):

        if sc.allclose(sim,sim_prev,atol=eps):
            break
        sim_prev=sc.copy(sim)
        sim=c*(Q.T*sim_prev*Q)+(1-c)*I

    print("Converge after %d iterations (eps=%f)." % (t, eps))
    return sim

我使用的是稀疏矩阵,但numpy.allclose()函数给出了错误,因为它只需要将numpy数组作为输入。我不想将稀疏矩阵转换为数组并再次转换回稀疏矩阵,因为它效率低下。还有另一种检查allclose()的两个稀疏矩阵的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以设置比较架构,然后使用numpy进行评估:

def csr_allclose(a, b, rtol=1e-5, atol = 1e-8):
    c = np.abs(np.abs(a - b) - rtol * np.abs(b))
    return c.max() <= atol

csr_matrix c将包含所比较的两个矩阵的差异,如果任何绝对差异大于您的阈值水平,csr_allclose将返回False }。但是,此实现并未包含NaN方法提供的numpy.allclose功能。

答案 1 :(得分:0)

如果你知道矩阵匹配稀疏度 - 非零数和匹配的非零指数,你可以只比较data

np.allclose(sim.data,sim_prev.data,atol=eps)

如果矩阵以相同的方式构造,或者一个是稀疏性保留另一个矩阵的推导,则为真。

一些时间测试:

In [153]: M = sparse.random(1000,1000,.2, 'csr')
In [154]: M
Out[154]: 
<1000x1000 sparse matrix of type '<class 'numpy.float64'>'
    with 200000 stored elements in Compressed Sparse Row format>

另一种形状相同但稀疏程度不同的矩阵

In [155]: M1 = sparse.random(1000,1000,.2, 'csr')
In [156]: 
In [156]: timeit np.abs(M-M1).max()
12.3 ms ± 339 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [157]: timeit np.abs(M.A-M1.A).max()
24.4 ms ± 624 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

如果矩阵匹配稀疏,我们可以比较data属性,节省大量时间:

In [158]: M2 = M.copy()
In [159]: M2.data += np.random.rand(M2.data.shape[0])*.001
In [160]: timeit np.abs(M.data-M2.data).max()
2.77 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

对稀疏性进行初步检查可以节省大量时间(前提是我们不担心epsilon大小非零值):

In [170]: timeit np.allclose(M.indptr,M1.indptr)
97.8 µs ± 2.29 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

从时间上移除toarray()步骤,在等效大小的密集阵列上生效allclose

In [164]: %%timeit Ma=M.A; M1a=M1.A
     ...: np.abs(Ma-M1a).max()
     ...: 
14.8 ms ± 31 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

稀疏矩阵的减法比我预期的要好。

实际上我不需要使用np.abs; Python abs委托给M.__abs__方法,即:

def __abs__(self):
    return self._with_data(abs(self._deduped_data()))