52

だから、私は非常にまばらなnumpy配列を使用していくつかのKmeans分類を行っています-たくさんのゼロ。ストレージのオーバーヘッドを削減するために scipy の「スパース」パッケージを使用すると考えましたが、行列ではなく配列を作成する方法について少し混乱しています。

スパース行列の作成方法に関するこのチュートリアルを実行しました: http://www.scipy.org/SciPy_Tutorial#head-c60163f2fd2bab79edd94be43682414f18b90df7

配列を模倣するために、1xN 行列を作成するだけですが、ご想像のとおり、2 つの 1xN 行列を掛けることができないため、Asp.dot(Bsp) はまったく機能しません。各配列を Nx1 に転置する必要がありますが、内積計算ごとにこれを行うことになるため、これはかなり不自由です。

次に、列 1 == 行 1 の NxN 行列を作成しようとしました (2 つの行列を乗算して、左上隅を内積として取得できるようにするため)。

numpy の array() の代わりに scipy の sparse パッケージを魔法のように使いたいと思っていますが、どうすればよいかわかりません。

何かアドバイス?

4

3 に答える 3

35

scipy.sparse行または列ベースのフォーマットを使用してください:csc_matrixおよびcsr_matrix.

これらは内部で効率的な C 実装 (乗算を含む) を使用し、転置はtranspose(copy=False)numpy 配列と同様にノーオペレーションです (特に を呼び出す場合)。

編集: ipythonによるいくつかのタイミング:

import numpy, scipy.sparse
n = 100000
x = (numpy.random.rand(n) * 2).astype(int).astype(float) # 50% sparse vector
x_csr = scipy.sparse.csr_matrix(x)
x_dok = scipy.sparse.dok_matrix(x.reshape(x_csr.shape))

現在x_csr、 とx_dokは 50% 疎です:

print repr(x_csr)
<1x100000 sparse matrix of type '<type 'numpy.float64'>'
        with 49757 stored elements in Compressed Sparse Row format>

そしてタイミング:

timeit numpy.dot(x, x)
10000 loops, best of 3: 123 us per loop

timeit x_dok * x_dok.T
1 loops, best of 3: 1.73 s per loop

timeit x_csr.multiply(x_csr).sum()
1000 loops, best of 3: 1.64 ms per loop

timeit x_csr * x_csr.T
100 loops, best of 3: 3.62 ms per loop

だから私は嘘をついたようです。転置非常に安価ですが、(最新の scipy 0.9.0 では) csr * csc の効率的な C 実装はありません。各呼び出しで新しい csr オブジェクトが構築されます :-(

ハックとして (最近の scipy は比較的安定していますが)、スパース データに対して直接ドット積を実行できます。

timeit numpy.dot(x_csr.data, x_csr.data)
10000 loops, best of 3: 62.9 us per loop

この最後のアプローチは、再びnumpy密な乗算を行うことに注意してください。スパース性は 50% であるため、実際にdot(x, x)は 2 倍より高速です。

于 2011-07-19T22:23:11.117 に答える
1

それが実際にはるかに優れているか高速であるかはわかりませんが、転置の使用を避けるためにこれを行うことができます:

Asp.multiply(Bsp).sum()

これは、2 つの行列の要素ごとの積を取り、積を合計するだけです。上記のステートメントを内積として持つ、使用している行列形式のサブクラスを作成できます。

ただし、それらを転置する方がおそらく簡単です。

Asp*Bsp.T

それほど大したことではないように思えますが、サブクラスを作成してmul () メソッドを変更することもできます。

于 2010-03-29T18:59:31.123 に答える
1

既存の 2 次元スパース配列の 1 つのサブクラスを作成できます

from scipy.sparse import dok_matrix

class sparse1d(dok_matrix):
    def __init__(self, v):
        dok_matrix.__init__(self, (v,))
    def dot(self, other):
        return dok_matrix.dot(self, other.transpose())[0,0]

a=sparse1d((1,2,3))
b=sparse1d((4,5,6))
print a.dot(b)
于 2010-03-29T18:16:22.250 に答える