web-dev-qa-db-ja.com

numpyライブラリの大きなO複雑度のリストはありますか?

私はアルゴリズムの時間複雑度分析を行っており、特定の複雑な操作がどのような複雑さを持っているかを知る必要があります。

一部の人にとっては、それらが基礎となる数学的演算と一致すると仮定します。 np.dot(array1, array2)はO(n)になります。他の人にとっては、私にはよくわかりません。たとえば、np.array(my_array) O(1)ですか?それともO(n)ですか?それは単にポインタを再割り当てするのですか、それともリストを反復して各値をコピーするのですか?

各操作の複雑さを確認したいと思います。この情報を見つけられる場所はありますか?それとも、それらが数学演算と一致すると仮定する必要がありますか?

9
James

BigOの複雑さは、Pythonとnumpyで使用されることはあまりありません。これは、コードが問題のサイズに応じてどのようにスケーリングするかを示す尺度です。これは、Cなどのコンパイル済み言語で役立ちます。 Pythonとコンパイルされたコード。両方とも同じbigOを持つことができますが、解釈されたバージョンは桁違いに遅くなります。そのため、SOスピードの速い、「ループの削除」と「ベクトル化」について話します。

また、純粋なO(n)である操作はほとんどありません。ほとんどはミックスです。セットアップコストに加えて、要素ごとのコストがあります。要素ごとのコストが小さい場合は、セットアップコストが優先します。

リストから始める場合、リストを配列に変換するとかなりのオーバーヘッド(O(n))が発生するため、リストを反復する方が高速であることがよくあります。

すでに配列がある場合は、可能な限り(Pythonレベルの)反復を避けてください。反復はほとんどの計算の一部ですが、numpyを使用すると、より高速にコンパイルされたコード(より高速なO(n))でその多くを実行できます。

ある時点で、numpyが配列を格納する方法を理解する必要があります。 viewcopyの違いは重要です。ビューは事実上O(1)、コピーO(n)です。

多くの場合、SO答えはtimeit速度比較を行います。結果は問題のサイズによって異なる可能性があるという警告を追加します。より良い答えは、さまざまなサイズの問題の時間を計り、ナイスプロットの結果。結果は多くの場合、直線(O(n))と曲線(O(1)とO(n)コンポーネント)。


np.array。次に、タイミングの例を示します。

In [134]: %%timeit alist = list(range(1000))
     ...: np.array(alist)
67.9 µs ± 839 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [135]: %%timeit alist = list(range(10))
     ...: np.array(alist)

2.19 µs ± 9.88 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [136]: %%timeit alist = list(range(2000))
     ...: np.array(alist)
134 µs ± 1.98 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

配列をコピーします。

In [137]: %%timeit alist = list(range(2000)); arr=np.array(alist)
     ...: np.array(arr)
1.77 µs ± 24.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

コピーなし:

In [138]: %%timeit alist = list(range(2000)); arr=np.array(alist)
     ...: np.array(arr, copy=False) 
237 ns ± 1.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

文字列のリストから:

In [139]: %%timeit alist = [str(i) for i in range(2000)]
     ...: np.array(alist, dtype=int)
286 µs ± 4.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

numpyのほとんどすべての計算はO(n)です。配列の各要素が関係する場合、速度は配列のサイズに依存します。一部の配列操作は、実際にはデータに対して何も実行しないため、再形成な​​どのO(1)です。形状や歩幅などのプロパティを変更します。

多くの場合、検索問題はO(n)よりも速く成長します。通常、numpyはその種の問題に最適な選択ではありません。使いやすいPythonリストと辞書はより高速にできます。

5
hpaulj

特定の例np.array(my_array)では、my_arrayのすべての要素を実行し、メモリを割り当てて値を初期化する必要があるため、線形時間で行われます。

python modulebig_Oを使用して、実行時間から関数の複雑さを分析できます。

詳細については、これを参照してください link

3