web-dev-qa-db-ja.com

PythonおよびNumPyを使用した非常に大きな行列

NumPy は非常に便利なライブラリであり、それを使用することで、非常に大きい(10000 x 10000)行列を簡単に処理できることがわかりましたが、もっと大きなものに苦労し始めています( 50000 x 50000の行列を作成すると失敗します)。明らかに、これは大量のメモリ要件のためです。

NumPyにネイティブに巨大なマトリックスを作成する方法はありますか?

82
Peter

PyTablesとNumPyがその方法です。

PyTablesは、オプションの圧縮を使用して、HDF形式でディスクにデータを保存します。多くの場合、データセットは10倍の圧縮を取得します。これは、数千または数億行を処理する場合に便利です。また、非常に高速です。私の5歳のラップトップは、1,000,000行/秒でSQLのようなGROUP BY集計を実行してデータを処理できます。 Pythonベースのソリューションとしては悪くありません!

NumPy再配列としてのデータへのアクセスは、次のように簡単です:

data = table[row_from:row_to]

HDFライブラリは、関連するデータチャンクの読み取りとNumPyへの変換を処理します。

89
Stephen Simmons

numpy.arraysは、メモリ内に住むことを意図しています。 RAMよりも大きな行列を使用する場合は、回避する必要があります。あなたが従うことができる少なくとも2つのアプローチがあります:

  1. マトリックスが持つ特別な構造を活用する、より効率的なマトリックス表現を試してください。たとえば、他の人がすでに指摘しているように、 scipy.sparse.csc_matrix
  2. 部分行列で動作するようにアルゴリズムを変更します。現在計算で使用されているマトリックスブロックのみをディスクから読み取ることができます。クラスター上で実行するように設計されたアルゴリズムは、通常、ブロック単位で機能します。これは、データが異なるコンピューターに分散され、必要な場合にのみ通過するためです。たとえば、 行列乗算のFoxアルゴリズム(PDFファイル) です。
54

Numpy.memmapを使用して、ディスク上のファイルをメモリマップできる必要があります。新しいpythonおよび64ビットマシンでは、すべてをメモリにロードすることなく、必要なアドレススペースを確保する必要があります。OSは、ファイルの一部のみをメモリに保持します。

30
DopplerShift

スパース行列を処理するには、scipyの上にあるnumpyパッケージが必要です。詳細は here を参照してくださいscipyが提供するスパース行列オプションの詳細。

24
Alex Martelli

Stefano Boriniの post は、この種のものがどれだけ先に進んでいるかを調べさせてくれました。

これがそれです。 基本的にあなたがしたいことをするようです。 HDF5を使用すると、非常に大きなデータセットを保存し、NumPyと同じ方法でそれらにアクセスして使用できます。

64ビットオペレーティングシステムと64ビットバージョンのPython/NumPyを使用していることを確認してください。 32ビットアーキテクチャでは、通常3GBのメモリをアドレス指定できることに注意してください(メモリマップI/Oなどで約1GBが失われます)。

使用可能なRAMよりも大きい64ビットおよびモノの配列では、スワップが必要な場合は遅くなりますが、メモリマップ(numpy.memmapを参照してください)メモリにロードせずにディスク上の巨大なファイルを操作する方法ですが、この場合も、64ビットのアドレス空間を使用する必要があります。 。

5
dwf

少しアルファですが、 http://blaze.pydata.org/ はこれを解決するために取り組んでいるようです。

5
wisty

テラバイトのRAMなしで2,500,000,000の要素マトリックスを処理する方法を求めていますか?

80億バイトのRAMなしで20億のアイテムを処理する方法は、行列をメモリに保持しないことです。

つまり、ファイルシステムから断片を取得するためのはるかに高度なアルゴリズムを意味します。

4
S.Lott

簡単な解決策の1つは、マトリックスアイテムにカスタムタイプを使用することです。必要な数字の範囲に基づいて、手動でdtypeを使用でき、アイテムには特に小さくできます。 Numpyはデフォルトでオブジェクトの最大の型を考慮するため、これは多くの場合に役立つアイデアです。以下に例を示します。

In [70]: a = np.arange(5)

In [71]: a[0].dtype
Out[71]: dtype('int64')

In [72]: a.nbytes
Out[72]: 40

In [73]: a = np.arange(0, 2, 0.5)

In [74]: a[0].dtype
Out[74]: dtype('float64')

In [75]: a.nbytes
Out[75]: 32

カスタムタイプの場合:

In [80]: a = np.arange(5, dtype=np.int8)

In [81]: a.nbytes
Out[81]: 5

In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16)

In [78]: a.nbytes
Out[78]: 8
3
Kasrâmvd

私がnumpyについて知っている限り、いや、しかし間違っている可能性があります。

この代替ソリューションを提案できます。ディスクにマトリックスを書き込み、チャンクでアクセスします。 HDF5ファイル形式をお勧めします。透過的に必要な場合は、ndarrayインターフェイスを再実装して、ディスクに格納されたマトリックスをメモリにページ分割することができます。データを変更してディスク上で同期する場合は注意してください。

1
Stefano Borini

通常、大きな行列を扱うときは、 スパース行列 として実装します。

Numpyがスパース行列をサポートしているかどうかはわかりませんが、代わりに this が見つかりました。

1

Google Colabでコードを実行できます。 Google Colabは無料のクラウドサービスであり、現在は無料のGPUをサポートしています。 Google Colabに(870199 * 14425)マトリックスを作成できましたが、PCで実行できませんでした。

0
hamed baziyad