PythonとNumPyを使用した非常に大きな行列


86

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

なんらかの方法で(数テラバイトのRAMを使用せずに)NumPyでネイティブに巨大なマトリックス(たとえば100万×100万)を作成する方法はありますか?

回答:


91

PyTablesとNumPyがその方法です。

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

NumPyリアレイとしてデータに再度アクセスするのは、次のように簡単です。

data = table[row_from:row_to]

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


4
それで、処理のためにデータを自分でチャンクに分割する必要がありますか?これは、ディスクファイルとの間の変換を簡素化する方法にすぎませんか?
endolith 2013年

もう少し明確に、いくつかの例を挙げて答えを拡張できる可能性はありますか?
アダム

56

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

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

4
3-ビッグデータパラダイムにステップインし、MapReduceのようなソリューションを研究する
Medeiros 2013

2番目の場合、チャンクを作成する大きさをどのように決定しますか?空きメモリの量を測定し、それに基づいてチャンクのサイズを設定する方法はありますか?
endolith 2015年

30

numpy.memmapを使用して、ディスク上のファイルをメモリマップできるはずです。新しいPythonと64ビットマシンでは、すべてをメモリにロードせずに、必要なアドレス空間が必要です。OSは、ファイルの一部のみをメモリに保持するように処理する必要があります。


19
それを使って記憶に収まらないことをする方法の例を教えてください。
endolith 2013年

24

スパース行列を処理するには、必要scipyの上に座って、パッケージをnumpy-を参照して、ここでスパース行列のオプションの詳細についてはscipyあなたを与えます。


11

ステファノボリーニの投稿私はこの種のことがすでにどこまで進んでいるかを調べることができました。

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


9
より良い選択はPyTablesかもしれません。これは、コアHDF5機能よりも高レベルです(H5Pyは、Pythonからアクセスできる低レベルAPIにすぎません)。また、先週の2.2ベータ版には、この問題のツールがあります。pytables.org / moin / ReleaseNotes / Release_2.2b1 Exprを追加しました。これは、任意の大きな値で動作する式( '3 * a + 4 * b'など)を評価できるクラスです。リソースを最適化しながら配列[...]。これはNumexprパッケージに似ていますが、NumPyオブジェクトに加えて、Array、CArray、EArray、ColumnPyTablesオブジェクトなどのディスクベースの同種配列も受け入れます。
AFoglia 2009年

5

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

使用可能なRAMよりも大きい64ビットおよびthings配列を使用すると、仮想メモリを使用できますが、スワップする必要がある場合は処理が遅くなります。また、メモリマップ(numpy.memmapを参照)は、ディスク上の巨大なファイルをメモリにロードせずに操作する方法ですが、これを有効にするには、64ビットのアドレス空間が必要です。PyTablesはあなたのためにもこれのほとんどを行います。



4

単純な解決策の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

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

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

これは、ファイルシステムから断片的にフェッチするためのはるかに高度なアルゴリズムを意味します。


7
違います。要素の99.99%(現実的な例)がゼロの場合、行列のすべてのデータをメモリに保持できます。存在(row, column, value)するエントリのリストを保存できる場合は、ゼロごとに4バイトを使用する必要はありません。
エリックウィルソン

6
@EricWilson:質問のどこで、マトリックスがスパースであることが示唆されましたか?私はそれを完全に逃しました。見積もりを提供できますか?
S.Lott 2011年


1

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

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


57600 x 57600のマトリックス全体にアクセスしたい場合はどうすればよいですか?
Gunjan naik 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.