2

M x N 配列Iがあり、その各行は N 次元配列のインデックスAです。ベクトル化された式で、A から M インデックス付きの値の 1 次元配列を取得したいと考えています。これA[tuple(I.T)]は正しいことですが、プロファイリングでは、ベクトル化されているにもかかわらず非常にコストがかかることがわかりました。また、特にエレガントでも「自然」でもなく、まったく異なることを行いA[I]ますA[I.T]

これを行う正しい方法は何ですか?次のような割り当てにも機能するはずです

A[tuple(I.T)] = 1
4

2 に答える 2

4

あなたは次のようなことを話していると思います:

In [398]: A=np.arange(24).reshape(4,6)
In [401]: I=np.array([[0,1],[1,2],[3,4],[0,0],[2,5]])

In [402]: tuple(I.T)
Out[402]: (array([0, 1, 3, 0, 2]), array([1, 2, 4, 0, 5]))

In [403]: A[tuple(I.T)]
Out[403]: array([ 1,  8, 22,  0, 17])

これはhttp://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#purely-integer-array-indexing - 純粋な整数配列の高度なインデックス付けです。

これは、ビューを返す基本的なインデックス作成よりも常に遅くなります。基本的なインデックス作成では、連続したデータ ブロック、またはストライドで選択できる値が選択されます。これは、インデックス作成では不可能です。

いくつかのタイミングを見てください:

In [404]: timeit tuple(I.T)
100000 loops, best of 3: 3.4 µs per loop

In [405]: timeit A[tuple(I.T)]
100000 loops, best of 3: 10 µs per loop

In [406]: %%timeit i,j=tuple(I.T)
   .....: A[i,j]
   .....: 
100000 loops, best of 3: 4.86 µs per loop

タプルの構築には約 1/3 の時間がかかります。 i,j=I.Tは少しだけ速いです。しかし、そのインデックス作成は最大のピースです。

A[i,j]A[(i,j)]は(そのまま)と同じA.__getitem__((i,j))です。したがって、ラップI.Tするtupleと、各次元に 1 つずつ、2 つのインデックス配列が生成されます。

フラット化されたバージョンの配列にインデックスを付ける方が高速です。

In [420]: J= np.ravel_multi_index(tuple(I.T),A.shape)
In [421]: J
Out[421]: array([ 1,  8, 22,  0, 17], dtype=int32)

In [422]: A.flat[J]
Out[422]: array([ 1,  8, 22,  0, 17])

In [425]: timeit A.flat[J]
1000000 loops, best of 3: 1.56 µs per loop

In [426]: %%timeit
    .....: J= np.ravel_multi_index(tuple(I.T),A.shape)
    .....: A.flat[J]
    .....: 
100000 loops, best of 3: 11.2 µs per loop

したがって、インデックスを事前計算して再利用できると時間を節約できますが、個々の値の束を選択するのにA余分な時間がかかるという事実を理解する方法はありません。

楽しみのために、インデックス作成にかかる時間をAの各行と比較してみましょうI:

In [442]: timeit np.array([A[tuple(i)] for i in I])
100000 loops, best of 3: 17.3 µs per loop
In [443]: timeit np.array([A[i,j] for i,j in I])
100000 loops, best of 3: 15.7 µs per loop
于 2015-08-15T20:28:45.667 に答える