2016-06-14 15 views
1

NumPy配列で作業しています。numpy配列の効率的な再構成

私は2Nの長さのベクトルDを持っており、その一部をN x Nの配列Cに再構成したいと考えています。

右は今、このコードは、私が欲しいものを行いますが、より大きなNのボトルネックである:Cが行われ

`` `

import numpy as np 
M = 1000 
t = np.arange(M) 
D = np.sin(t) # initial vector is a sin() function 
N = M/2 
C = np.zeros((N,N)) 
for a in xrange(N): 
    for b in xrange(N): 
     C[a,b] = D[N + a - b] 

` ``

たら、私が先に行くと、

このネストループはかなり遅いですが、この操作は本質的にインデックスの変更であるため私はNumPyの組み込みの形(numpy.reshape)を使ってこの部分を高速化できると考えました。

残念ながら、私はこれらの指標を変換する良い方法を理解できないようです。

このパートのスピードアップに役立つヘルプがありますか?

答えて

3

あなたはそれらのネストされたループを削除するためにNumPy broadcastingを使用することができます -

C = D[N + np.arange(N)[:,None] - np.arange(N)] 

そうのようなものでも、インデックスを置き換えるためにnp.takeを使用することができます -

C = np.take(D,N + np.arange(N)[:,None] - np.arange(N)) 

よく見るが近いようにパターンを明らかにする​​およびhankelマトリクス。だから、それらを使って、私たちはそれを解決するための2つのアプローチを持っていますが、放送と同等のスピードアップがあります。実装は、これらのようになります -

from scipy.linalg import toeplitz 
from scipy.linalg import hankel 

C = toeplitz(D[N:],np.hstack((D[0],D[N-1:0:-1]))) 
C = hankel(D[1:N+1],D[N:])[:,::-1] 

ランタイムテスト

In [230]: M = 1000 
    ...: t = np.arange(M) 
    ...: D = np.sin(t) # initial vector is a sin() function 
    ...: N = M/2 
    ...: 

In [231]: def org_app(D,N): 
    ...:  C = np.zeros((N,N)) 
    ...:  for a in xrange(N): 
    ...:   for b in xrange(N): 
    ...:    C[a,b] = D[N + a - b] 
    ...:  return C 
    ...: 

In [232]: %timeit org_app(D,N) 
    ...: %timeit D[N + np.arange(N)[:,None] - np.arange(N)] 
    ...: %timeit np.take(D,N + np.arange(N)[:,None] - np.arange(N)) 
    ...: %timeit toeplitz(D[N:],np.hstack((D[0],D[N-1:0:-1]))) 
    ...: %timeit hankel(D[1:N+1],D[N:])[:,::-1] 
    ...: 
10 loops, best of 3: 83 ms per loop 
100 loops, best of 3: 2.82 ms per loop 
100 loops, best of 3: 2.84 ms per loop 
100 loops, best of 3: 2.95 ms per loop 
100 loops, best of 3: 2.93 ms per loop 
+0

すごいです!これは、ループを大幅に高速化しました。 – jjgoings

+0

@jjgoingsうん、それを確認した! – Divakar

関連する問題