2017-11-18 1 views
1

크기가 (3, n) 인 np.array에 저장된 많은 데이터를 처리하고 있습니다.numpy에서 효율적인 벡터화 수행 방법 (메모리 제약 조건)

각 데이터 x : xx.T (3x3 매트릭스 구성)을 수행해야합니다. 그래서 이것은 3x3 행렬을 많이 만들 것입니다. 그런 다음이 행렬 각각의 결과를 추가하여 전체 3x3 행렬을 형성해야합니다.

나는 이것을 다음과 같이했다 : np.einsum('ij,ki->jk', x, x.T) 그것은 작동하는 것처럼 보인다. 그러나 문제는 내 n이 엄청나게 크다는 것입니다. (저는 많은 메가 픽셀의 매우 큰 이미지를 다루고 있습니다)이 방법은 MemoryError이됩니다.

벡터화 된 방법을 유지하면서 다른 작업을 수행 할 수 있습니까?

감사합니다.

+0

여기에 'n'이 포함 된 데이터 세트 크기를 측정 해주세요. – Divakar

+0

다음과 같이하면됩니다 :'x.T.dot (x)'. – Divakar

+0

@Divakar : 배열에 shape (3, n)이 있으면 x.dot (x.T)를 원하지 않습니까? – DSM

답변

1

귀하의 코멘트에서 근무 :

In [465]: x=np.array([[1,2,3],[4,5,6]]) 
In [466]: np.einsum('ij,ik', x,x) 
Out[466]: 
array([[17, 22, 27], 
     [22, 29, 36], 
     [27, 36, 45]]) 
In [467]: x=np.ones((10,3)) 
In [468]: np.einsum('ij,ik', x,x) 
Out[468]: 
array([[ 10., 10., 10.], 
     [ 10., 10., 10.], 
     [ 10., 10., 10.]]) 
In [471]: x=np.ones((10000000,3)) 
In [472]: np.einsum('ij,ik', x,x) 
Out[472]: 
array([[ 10000000., 10000000., 10000000.], 
     [ 10000000., 10000000., 10000000.], 
     [ 10000000., 10000000., 10000000.]]) 

배열이 메모리에 너무 큰 될 경우, 당신이 그것을 청크 시도 할 수 :

In [479]: res = np.zeros((3,3)) 
In [480]: for i in range(10): 
    ...:  res += np.einsum('ij,ik',x,x) 
    ...:  
In [481]: res 
Out[481]: 
array([[ 170., 220., 270.], 
     [ 220., 290., 360.], 
     [ 270., 360., 450.]]) 

일반적으로 몇 번 반복 복잡한 작업을 통해 것은 밀어보다 빠르다 어떤 반복도없이 메모리 제한. 어떤 시점에서 메모리 관리 비용이 반복 비용을 초과합니다.

이 간단한 einsum은 그냥 간단하게 dot으로 해결하고, 잠재적으로 빠른

:

In [484]: x.T.dot(x) 
Out[484]: 
array([[17, 22, 27], 
     [22, 29, 36], 
     [27, 36, 45]]) 
나는 아직 메모리 제한을 타격하고 있지 않다하더라도 그래서
In [486]: x=np.ones((10000000,3)) 
In [487]: timeit np.einsum('ij,ik',x,x) 
426 ms ± 151 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) 

In [488]: x1=np.ones((50000000,3)) 
In [490]: timeit np.einsum('ij,ik',x1,x1) 
2.14 s ± 15.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

In [493]: %%timeit 
    ...: res = np.zeros((3,3)) 
    ...: x2 = x1.reshape(5,-1,3) 
    ...: for i in range(5): 
    ...: x3 = x2[i] 
    ...: res += np.einsum('ij,ik',x3,x3) 
2.1 s ± 5.74 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

는 청크 준다 나 약간의 속도 향상. (비록 메모리 한계에서 멀지는 않지만, ipython 히스토리 스택에있는 항목들 중 몇 개가 나를 밀어 붙일 수있다). 단지 비교

AN, dot를 사용할 때 도움이되지 않습니다이 크기의 청크에서 (2D에 대한 dot와 동일)에서 @

In [494]: %%timeit 
    ...: res = np.zeros((3,3)) 
    ...: x2 = x1.reshape(5,-1,3) 
    ...: for i in range(5): 
    ...: x3 = x2[i] 
    ...: res += [email protected] 
537 ms ± 9.62 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

In [495]: timeit [email protected] 
530 ms ± 1.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
In [496]: timeit [email protected] 
106 ms ± 1.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

.

관련 문제