2016-07-26 8 views
1

私は推薦システムを使用していますが、scipyスパース行列のアクセス時間に苦労しています。スパース行列での効率的なアクセス

この場合、TrustSVDを実装していますので、列と行(CSR、CSC)の両方で動作する効率的な構造が必要です。私は両方の構造体、辞書を使用することについて考えてきましたが、どちらの方法でも、これは常に遅すぎる、特にnumpyの行列演算に比べて遅いです。

for u, j in zip(*ratings.nonzero()): 
    items_rated_by_u = ratings[u, :].nonzero()[1] 
    users_who_rated_j = ratings[:, j].nonzero()[0] 
    # More code... 

エクストラ: 各ループは約0.033sを取るので、35,000評価を通じて一回反復して反復(SGD)あたり、我々は8時間の話をしている25回の反復の最低19minを待つことを意味します。さらに、ここではアクセスについて話していますが、因数分解部分を含めると約2日間かかります。

+0

使用しているマトリックスは帯状になっていますか?もしそうなら、それを利用することは非常に役に立ちます。そうでない場合、リスト実装のリストはどうですか? m * n行列の場合、これはアクセス時間〜log(n)を持ち、かなり効率的です。 –

+0

私はあなたが2つのバージョンのマトリックス(トランスポーズ)を必要とし、基礎となるデータ構造に直接アクセスする必要があると思われます。 – hpaulj

+0

いいえ、行列は束縛されません。格付けはマトリックス内に均等に分散しています(実際にはいくつかの項目は他の項目よりも格付けが高い傾向がありますが、ここでは関係ありません)。もう一つは、この種のデュアルまたは事前計算された構造メモリを使用して速度を上げることです。しかし、私は、まばらな行列もかなり遅いので、配列の2つの辞書(軸ごとに1つ)を使用すると考えていることに気付きました。あなたはより速い解決策を思いついていますか? –

答えて

2

スパース行列のインデックスを作成するときは、特に行または列を求めるだけでなく、値を選択するだけでなく、新しいスパース行列を作成する必要があります。 np.ndarray構築はコンパイルされたコードで行われますが、疎構造のほとんどは純粋なPythonです。 nonzero()[1]構成では、マトリックスをcooフォーマットに変換し、rowcol属性(コードを参照)を選択する必要があります。

は、私はあなたがrowslil形式の属性、またはその転置を見ることで、より速く、あなたの行の列にアクセスすることができると思う:あなたはまた、csr形式でこれらの値にアクセスすることができ

In [418]: sparse.lil_matrix(np.matrix('0,1,0;1,0,0;0,1,1')) 
Out[418]: 
<3x3 sparse matrix of type '<class 'numpy.int32'>' 
    with 4 stored elements in LInked List format> 
In [419]: M=sparse.lil_matrix(np.matrix('0,1,0;1,0,0;0,1,1')) 
In [420]: M.A 
Out[420]: 
array([[0, 1, 0], 
     [1, 0, 0], 
     [0, 1, 1]], dtype=int32) 
In [421]: M.rows 
Out[421]: array([[1], [0], [1, 2]], dtype=object) 
In [422]: M[1,:].nonzero()[1] 
Out[422]: array([0], dtype=int32) 
In [423]: M[2,:].nonzero()[1] 
Out[423]: array([1, 2], dtype=int32) 
In [424]: M.T.rows 
Out[424]: array([[1], [0, 2], [2]], dtype=object) 

が、それは少しですより複雑になる

In [425]: M.tocsr().indices 
Out[425]: array([1, 0, 1, 2], dtype=int32) 
+0

ありがとうございました。これにより、コードがx2-2.5を中心に高速化されるため、最終的なソリューションはこれに加えて軸(ユーザー、アイテム)ごとのキャッシュです。 –

関連する問題