通常のPythonリストと比較したNumPyの利点は何ですか?


466

通常のPythonリストと比較したNumPyの利点は何ですか?

約100の金融市場シリーズがあり、100x100x100 = 100万セルのキューブ配列を作成します。標準誤差で配列を満たすために、各xを各yとzで回帰(3変数)します。

「大きな行列」の場合、パフォーマンスとスケーラビリティの理由から、PythonリストではなくNumPyを使用する必要があると聞きました。事は、私はPythonのリストを知っており、それらが私のために働くようです。

NumPyに移行すると、どのようなメリットがありますか?

1000シリーズ(つまり、キューブ内の10億浮動小数点セル)がある場合はどうなりますか?

回答:


727

NumPyの配列はPythonリストよりもコンパクトです-記述したリストのリストは、Pythonでは少なくとも20 MB必要ですが、セルに単精度浮動小数点数を含むNumPy 3D配列は4 MBに収まります。NumPyを使用すると、アイテムの読み取りと書き込みのアクセスも高速になります。

100万個のセルではそれほど気にしないかもしれませんが、10億個のセルでは間違いなくそうします。どちらのアプローチも32ビットアーキテクチャには適合しませんが、64ビットビルドでは、NumPyは4 GB程度で済むでしょう。 、Pythonだけでも少なくとも約12 GB(サイズが2倍になるたくさんのポインタ)が必要になります。これは非常にコストのかかるハードウェアです。

違いは主に「間接性」によるものです。Pythonリストは、Pythonオブジェクトへのポインタの配列であり、ポインタあたり4バイト以上、最小のPythonオブジェクトでも16バイトです(型ポインタは4、参照カウントは4、4値の場合-およびメモリアロケータは16に切り上げます)。NumPy配列は均一な値の配列です。単精度の数値はそれぞれ4バイト、倍精度の数値は8バイトです。柔軟性は低くなりますが、標準のPythonリストの柔軟性にかなりの費用がかかります。


「sys.getsizeof()」を使用して、PythonリストとNumPy配列のサイズを同じ要素数で比較しようとしましたが、NumPy配列がそれほど小さいことを示していないようです。これはそうですか、またはsys.getsizeof()がNumPy配列の大きさを理解するのに問題を抱えていますか?
ジャックシンプソン

3
@JackSimpson getsizeofは信頼できません。ドキュメントには、次のように明記されています。オブジェクトに直接起因するメモリ消費のみが考慮され、オブジェクトが参照するオブジェクトのメモリ消費は考慮されません。 つまり、入れ子のpythonリストがある場合、要素のサイズは考慮されません。
Bakuriu

4
getsizeofリストでは、リストオブジェクト自体が消費するRAMの量と、データ配列内のポインターが消費するRAMのみが示され、それらのポインターが参照するオブジェクトが消費するRAMの量は示されません。
PM 2Ring

@AlexMartelli、これらの番号をどこで取得しているのか教えてください。
lmiguelvargasf

リストのリストに相当するPythonリストの同等のPythonリストのサイズに関する推定はオフです。4 GBのC floatのnumpy配列(4バイト)は、12 GBではなく、32 GB相当のlistsおよびPython floats(実際にはC double)に近いものに変換されます。float64ビットPythonのそれぞれが約24バイト(アロケータでアライメントの損失がない場合)に加えてlist、参照を保持するためにさらに8バイトを占有します(lists自体の割り当て超過およびオブジェクトヘッダーを無視します。正確にどのくらいの割り当て超過が発生します)。
ShadowRanger 2018年

232

NumPyはより効率的ではありません。また、より便利です。多くのベクトルおよび行列演算を無料で取得できます。これにより、不要な作業を回避できる場合があります。また、効率的に実装されています。

たとえば、ファイルから配列に直接キューブを読み取ることができます。

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

2番目の次元に沿って合計します。

s = x.sum(axis=1)

しきい値を超えているセルを見つけます。

(x > 0.5).nonzero()

3番目の次元に沿ってすべてのインデックスが付けられたスライスを削除します。

x[:, :, ::2]

また、多くの便利なライブラリがNumPy配列で機能します。たとえば、統計分析および視覚化ライブラリ。

パフォーマンスの問題がなくても、NumPyを学ぶことは努力する価値があります。


ありがとうございます。3つ目の例でもう1つの正当な理由を説明してください。実際、しきい値を超えるセルのマトリックスを検索します。また、sqlLiteからロードしていました。ファイルアプローチの方がはるかに効率的です。
トーマスブラウン

112

アレックスはメモリ効率に言及し、ロベルトは利便性に言及し、これらは両方とも良い点です。さらにいくつかのアイデアについては、速度機能について説明します

機能:NumPy、FFT、たたみ込み、高速検索、基本統計、線形代数、ヒストグラムなどで多くの機能が組み込まれています。実際、FFTなしで生きられるのは誰ですか?

速度:リストとNumPy配列の合計を計算するテストを次に示します。NumPy配列の合計が10倍速いことを示しています(このテストでは、走行距離は異なる場合があります)。

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))

私のシステムでは(バックアップを実行している間)、次のようになります:

numpy: 3.004e-05
list:  5.363e-04

44

scipy.org Webサイトの FAQからの良い答えは次のとおりです。

NumPy配列は、(ネストされた)Pythonリストよりも優れていますか?

Pythonのリストは効率的な汎用コンテナです。それらは(かなり)効率的な挿入、削除、追加、および連結をサポートし、Pythonのリスト内包によりそれらの構築と操作が容易になります。ただし、これらには特定の制限があります。要素ごとの加算や乗算などの「ベクトル化された」演算はサポートされていません。異なる型のオブジェクトを含めることができるという事実は、Pythonがすべての要素の型情報を格納し、型ディスパッチコードを実行する必要があることを意味します各要素を操作するとき。これはまた、効率的なCループで実行できるリスト操作はほとんどないことを意味します。各反復には、型チェックと他のPython APIブックキーピングが必要です。


9

numpy配列とpythonリストの間のほとんどすべての主要な違いを強調しています。ここで簡単に説明します。

  1. Numpy配列は、Pythonリスト(動的に拡張できる)とは異なり、作成時に固定サイズになります。ndarrayのサイズを変更すると、新しい配列が作成され、元の配列が削除されます。

  2. Numpy配列の要素はすべて同じデータ型である必要があります(異種の型を使用することもできますが、数学的な演算は許可されません)。したがって、メモリ内で同じサイズになります。

  3. Numpy配列は、大量のデータに対する数学およびその他のタイプの操作を促進します。通常、このような操作は、pythonのシーケンスを使用して実行するよりも効率的かつ少ないコードで実行されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.