3

2 つのインデックスを持つ配列を暗黙的に反復することは可能ですか? これは私がやりたいことの非常に簡単な例です:

import numpy as np

x = np.arange(3)
y = np.zeros(3)

for i in range(3):
    y[i] = np.sum(x - x[i])

暗黙的なループ (合計) と明示的なループ ( for i in range(3)) があります...完全に暗黙的なバージョンを持つことは可能ですか?

4

2 に答える 2

4

可能であれば、コンピュータ サイエンスの前に常に数学を使用するようにしてください。あなたの式はy[i] = np.sum(x - x[i])、小さな代数で次のように書き直すことができますy[i] = np.sum(x) - x.size * x[i]。これにより、次のようにループなしでコードを書き直すことができることが非常に明確になります。

y = np.sum(x) - x.size * x

明らかなように、大きな配列の場合、@ JoshAdel のソリューションよりもはるかに高速に実行され、サイズ 1000 の入力では x400 高速になります。

>>> x = np.random.normal(size=(1000,))
>>> np.allclose(np.sum(x - x[:,None], 1), np.sum(x) - x.size * x)
True

%timeit np.sum(x - x[:,None], 1)
100 loops, best of 3: 6.33 ms per loop

%timeit np.sum(x) - x.size * x
100000 loops, best of 3: 16.5 us per loop
于 2013-10-01T16:23:21.853 に答える
3

以下が機能するはずです。

y = np.sum(x - x[:,None], axis=1)

このソリューションは、numpy のブロードキャスト機能を使用しています。まず、 to usingxの形をしているリキャストです。これは と書かれている場合もあります。(N,)(N,1)x[:,None]x[:,np.newaxis]

x - x[:,None](N,N)要素が である配列を作成しますtmp_{i,j} = x_i - x_jaxis=1次に、引数inを使用して行全体を合計しますnp.sum

見る:

In [13]: y = np.zeros(10)

In [14]: x = np.random.normal(size=(10,))

In [15]: for i in range(10):
        y[i] = np.sum(x - x[i])
   ....:

In [16]: y
Out[16]:
array([  7.99781458,   4.15114434, -17.24655912, -20.35606168,
        -5.0211756 ,   7.52062868,   8.2501526 ,   3.90397351,
        10.18746451,   0.61261819])

In [17]: np.sum(x - x[:,None], 1)
Out[17]:
array([  7.99781458,   4.15114434, -17.24655912, -20.35606168,
        -5.0211756 ,   7.52062868,   8.2501526 ,   3.90397351,
        10.18746451,   0.61261819])

In [18]: np.allclose(y, np.sum(x - x[:,None], 1))
Out[18]: True

タイミング:配列を操作するために numpy が提供する機能を使用すると、多くの場合、標準の Python 構造を使用するよりも大幅に高速になることを指摘しておきます。

In [48]: x = np.random.normal(size=(100,))

In [49]: %timeit y = np.array([sum(x - k) for k in x])
100 loops, best of 3: 6.86 ms per loop

In [67]: %timeit y = np.array([np.sum(x - k) for k in x])
1000 loops, best of 3: 1.54 ms per loop

In [50]: %timeit np.sum(x - x[:,None], 1)
10000 loops, best of 3: 59 µs per loop

In [51]:

In [51]: x = np.random.normal(size=(1000,))

In [52]: %timeit y = np.array([sum(x - k) for k in x])
1 loops, best of 3: 592 ms per loop

In [72]: %timeit y = np.array([np.sum(x - k) for k in x])
100 loops, best of 3: 17.2 ms per loop

In [53]: %timeit np.sum(x - x[:,None], 1)
100 loops, best of 3: 8.67 ms per loop
于 2013-10-01T13:39:02.580 に答える