2016-06-14 4 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)) 

자세히 살펴보면 패턴 가까이하기를 보여 toeplitzhankel 행렬에 이른다. 따라서이를 사용하여 방송과 비교해 볼 때 속도가 훨씬 빨라졌지만 해결 방법은 두 가지가 더 있습니다. 구현은 다음처럼 보일 것이다 -

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

관련 문제