SciPyでの疎行列の扱い、保存など
Python、特にSciPyは日本語でのドキュメントが少ないので、メモがてら記述。
単語文書行列などでは大規模疎行列になることがよくある。
そこで格納方法の工夫などを行っていく必要がある。
最もスタンダードな方法としては圧縮行格納方式などがある。
基本的に疎行列の要素は0なので、非零の要素の位置だけ覚えておこうという発想。
もちろん(?)SciPyには疎行列を扱うモジュールsparseが用意されている。
lil_matrixにて疎行列を生成。引数には行列の大きさ(m, n)を指定。
from numpy import * from scipy import io, sparse A = sparse.lil_matrix((3, 3)) # 疎行列生成 A[0,1] = 3 A[1,0] = 2 A[2,2] = 5
【Aの型、中身】
3×3行列であること、および非零の位置のみ格納されていることが分かる。
>>> type(A) <class 'scipy.sparse.lil.lil_matrix'> >>> A <3x3 sparse matrix of type '<type 'numpy.float64'>' with 3 stored elements in LInked List format> >>> print A (0, 1) 3.0 (1, 0) 2.0 (2, 2) 5.0
通常の行列の形に戻すにはtodense()を使う。
>>> A.todense() # 行列の形に戻す matrix([[ 0., 3., 0.], [ 2., 0., 0.], [ 0., 0., 5.]])
matrixの保存にはio.savematを使う。
io.savemat("matrix_a", {"A":A})
これを実行すると「matrix_a.mat」というファイルが生成される。
保存する際には{"A":A}のように辞書のような形で書き込む。
なお、lil_matrix型でも保存できる。
また読み込みはio.loadmatを使う。
>>> A = io.loadmat("matrix_a")["A"] >>> A.todense() matrix([[ 0., 3., 0.], [ 2., 0., 0.], [ 0., 0., 5.]])
大規模疎行列の生成計算を一度きりにしたい場合は
lil_matrix型にて生成およびファイル保存を行い、使い回すと良い。
lil_matrix型とmatrix型における保存ファイルの容量の違いを見てみる。
from numpy import * from scipy import io, sparse A = sparse.lil_matrix((1000, 1000)) A.setdiag( ones(1000) ) # 対角要素を1にする B = A.todense() io.savemat("matrix_a", {"A":A}) # lil_matrix型で保存 io.savemat("martix_b", {"B":B}) # matrix型で保存
容量チェック
$ ls -lh -rw-r--r-- 1 billest billest 7.6M 9 7 05:23 martix_b.mat -rw-r--r-- 1 billest billest 23K 9 7 05:23 matrix_a.mat
これからも疎行列の格納にはlil_matrix型の方が良いことが分かる。当たり前ではあるが…