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()
的两个稀疏矩阵的方法吗?
答案 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()))