2017-07-17 2 views
1
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 

Iは、スパース行列を使用していますが、それが唯一の入力としてnumpyの配列をとるようnumpy.allclose()関数がエラーを与えています。私はスパース行列を配列に変換し、スパース行列に戻すことを非効率にしたいので、もう一度やり直したくありません。 allclose()の2つのスパース行列を確認する別の方法はありますか?numpy.allclose()

+1

は、 'numpy'機能は' sparse'行列では動作しません。例外は通常、関数が行列メソッドにアクションを委譲するためです。私はスパース同等物を思い出すことはありませんが、ドキュメントをチェックしてください。 – hpaulj

+0

まず最初に 'shape'、' dtype'、 'nnz'を比較したいと思います。 'sim.indptr'属性を比較してください。それは整数であり、私は 'allclose'であるべきだと思います。そこから '.indices'属性と' data'属性を比較しなければなりません。しかし、最初にそれらが「cannonical」であることを確認する必要があるかもしれません。すべてのゼロは削除され、重複した合計と順番に列があります。確認することがたくさんあります。 – hpaulj

答えて

0

あなたは比較のためのアーキテクチャを設定した後、評価のために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_matrixc比較される2つの行列の違いを含めると、絶対差のいずれかの場合になりますがしきい値レベルを超えている場合、csr_allcloseFalseを返します。ただし、この実装にはnumpy.allcloseメソッドによって提供されるNaN機能は含まれていません。

+0

@ワーレン:それをキャッチするためにありがとう。アドレスエラーに更新されました。 –

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) 

は、同等の大きさ、緻密アレイ上の効果allcloseに、タイミングからtoarray()ステップを削除します。

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を使用する必要はありません。あるM.__abs__方法にPythonのabs代表者:一般的に

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