scipyの疎行列(Sparse matrix)をmatplotlibで描画する
サンプルデータのダウンロード
元データはSuiteSparse Matrix Collectionより
import pyodide import os import tarfile URL = "https://data.arakaki.tokyo/static/blog/20220301/" FILES = [ "bcsstm22.tar.gz", "lns_3937.tar.gz", "orani678.tar.gz", "memplus.tar.gz" ] paths = list() for file in FILES: # 疎行列データ(tar.gz)ダウンロード with open(file, "w") as f: f.write(pyodide.open_url(f'{URL}{file}').read()) # tarファイルの展開 tar = tarfile.open(file) for path in tar.getnames(): paths.append(path) tar.extract(path) print(path)import matplotlib.pyplot as plt import scipy.io as scioMatrix Market filesの読み込み
まずはscipy
でMatrix Market(MM) fileを読み込みます。
scipy
の疎行列クラスはいくつか種類がありますが、MMファイルで疎行列を表すフォーマットは座標形式(COO)のようなので、coo_matrix
オブジェクトとして読み込まれます。
疎行列取り扱い注意❗
で、とりあえずこの疎行列がどんな形なのか確認したくなるわけですが、普通にmatplotlib
で描画しようにも以下のような問題に直面します。
- 判読できない縮尺になる
- 安易にndarray化するとメモリを食い尽くす
縮尺
bcsstm22とorani678を例に見てみましょう。
縦横のサイズが100程度のbcsstm22は程よく描画されていますが、2500を超えるorani678は単色で塗りつぶされてしまっています。
メモリ使用量
上の時点でもうお手上げなんですが、ダメ押しでndarray化した場合のメモリ使用量も確認してみます。
def size(v): 'format size in human-readable' unit = ["B", "KB", "MB", "GB"] for u in unit: if(v > 1024): v /= 1024 else: return f'{v:5.1f} {u:2}'sparse(coo)インスタンスの占有メモリ
for k,v in data.items(): print(f'{k:10}: {size(v.data.nbytes + v.row.nbytes + v.col.nbytes)}')ndarray換算にすると
foo = data[k].dtype for k,v in data.items(): print(f'{k:10}: {size(v.dtype.itemsize * v.shape[0] * v.shape[1])}')ブラウザ上ではmemplusをndarray化しようとするだけでエラーが出てしまいます。
通常のPython環境でもndarrayで扱おうとするとなかなか困難な戦いを強いられます。
解決策:spy
を使う
単に形を確認するだけならpyplot.spy一発です。
markersize
で粒度を指定できます。
より詳細に確認したければfigsize
を大きく、markersize
を小さくすればよいでしょう。
以上❗