転置行列の積の後であるため、[m, n]
の値は、基本的に元の行列の列m
とn
の内積になります。私は
a = np.array([[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]])
>>> np.dot(a.T, a)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2]])
おもちゃの例として、次の行列を使用するつもりです
それは形状(3, 12)
であり、7非ゼロのエントリがあります。その転置の生成物は、もちろん形状が(12, 12)
であり、非ゼロのエントリが16個あり、そのうち6個が対角線上にあるので、11個の要素の格納のみが必要である。
あなたの出力行列のサイズは、2つの方法のいずれかであることを行っているものの良いアイデアを得ることができます:あなたの元の行列がC
非ゼロの列がある場合
CSRのFORMAT
をあなたの新しい行列は最大でC**2
の非ゼロエントリーを持ち、そのうちC
は対角にあり、ゼロでないことが保証され、残りのエントリーのうち半分だけを保持する必要があるので、最大でも(C**2 + C)/2
です。ゼロ要素。もちろん、これらの多くはゼロになるので、おそらくこれは過大な過大評価です。
あなたのマトリックスはcsr
形式で格納されている場合、対応するscipy
オブジェクトのindices
属性は、すべての非ゼロ要素の列インデックスを持つ配列を有しているので、簡単に上記のように推定値を計算することができる:
>>> a_csr = scipy.sparse.csr_matrix(a)
>>> a_csr.indices
array([ 2, 11, 1, 7, 10, 4, 11])
>>> np.unique(a_csr.indices).shape[0]
6
だから、非ゼロのエントリで6列がある、ので、推定値は、実際の16
CSCのFORMATより方法より、せいぜい36非ゼロのエントリ、ためになる
ゼロ以外の要素の列インデックスの代わりに行インデックスがある場合、実際にはより良い見積もりを行うことができます。 2つの列のドット積が非ゼロであるためには、それらは同じ行に非ゼロ要素を持たなければならない。指定された行に0以外の要素がある場合は、R**2
以外の要素を製品に提供します。すべての行についてこれを合計すると、いくつかの要素を複数回カウントするようにバインドされているため、これも上限です。あなたの行列の非零要素の
行インデックスは、スパースCSCマトリックスのindices
属性であるので、次のように、この推定値を計算することができる。
>>> a_csc = scipy.sparse.csc_matrix(a)
>>> a_csc.indices
array([1, 0, 2, 1, 1, 0, 2])
>>> rows, where = np.unique(a_csc.indices, return_inverse=True)
>>> where = np.bincount(where)
>>> rows
array([0, 1, 2])
>>> where
array([2, 3, 2])
>>> np.sum(where**2)
17
これは、実際にとても近くに位置しています。 16!いずれの場合においても
>>> np.sum(np.dot(a.T,a),axis=None)
17
、次のコードは、あなたが推定はかなり良いであることを確認できるようにする必要があります:そしてそれは、この推定値は、実際と同じであることを実際に偶然ではないため
def estimate(a) :
a_csc = scipy.sparse.csc_matrix(a)
_, where = np.unique(a_csc.indices, return_inverse=True)
where = np.bincount(where)
return np.sum(where**2)
def test(shape=(10,1000), count=100) :
a = np.zeros(np.prod(shape), dtype=int)
a[np.random.randint(np.prod(shape), size=count)] = 1
print 'a non-zero = {0}'.format(np.sum(a))
a = a.reshape(shape)
print 'a.T * a non-zero = {0}'.format(np.flatnonzero(np.dot(a.T,
a)).shape[0])
print 'csc estimate = {0}'.format(estimate(a))
>>> test(count=100)
a non-zero = 100
a.T * a non-zero = 1065
csc estimate = 1072
>>> test(count=200)
a non-zero = 199
a.T * a non-zero = 4056
csc estimate = 4079
>>> test(count=50)
a non-zero = 50
a.T * a non-zero = 293
csc estimate = 294
謝罪遅延。助けてくれてありがとう!私は、「ストレージ要件」という語句が曖昧であると懸念していました。あなたが送った見積もりコードは、私が知りたいと思っていたものです。あなたの方法は、(およその数に関して)sedgewickとflajoletが行っていた分析的組合せ/漸近の仕事の一部に触発されていますか?参考文献: https://en.wikipedia.org/wiki/Analytic_combinatorics http://algo.inria.fr/flajolet/Publications/AnaCombi/ https://en.wikipedia.org/wiki/Asymptotic_theory ます。https: //en.wikipedia.org/wiki/Approximate_counting_algorithm –
@ct。残念ながら、私は学術界から遠く離れた土地に住んでいるので、あなたがリンクしたものは何も聞いたことがありませんでした。私のインスピレーションは、単に[CSR](http://en.wikipedia.org/wiki/Sparse_matrix#Compressed_sparse_row_.28CSR_or_CRS.29)と[CSC](http://en.wikipedia.org/wiki/Sparse_matrix #Compressed_sparse_column_.28CSC_or_CCS.29)形式を使用します。 – Jaime