2017-11-28 1 views
0

이 다음 프로그램 배열 중첩리스트로부터 큰 배열을 작성numpy는 중첩 배열에 대해 메모리를 어떻게 할당합니까?

import numpy as np 
a = np.arange(6).reshape(2, 3) 
nested_list = [[a, a + 1], [a + 2, a + 3]] 
b = np.array(nested_list) 

는 np.array이 경우에 상기 메모리에 데이터를 복사하기 전에 결과 번만 메모리를 사전 할당 하는가? 3 번 메모리를 미리 할당 할

c = np.vstack([np.hstack([a, a + 1]), np.hstack([a + 2, a + 3])]) 

:

또는이 유사하다?

>>> b 
array([[[[0, 1, 2], 
     [3, 4, 5]], 

     [[1, 2, 3], 
     [4, 5, 6]]], 


     [[[2, 3, 4], 
     [5, 6, 7]], 

     [[3, 4, 5], 
     [6, 7, 8]]]]) 
>>> c 
array([[0, 1, 2, 1, 2, 3], 
     [3, 4, 5, 4, 5, 6], 
     [2, 3, 4, 3, 4, 5], 
     [5, 6, 7, 6, 7, 8]]) 
>>> b.shape 
(2, 2, 2, 3) 
>>> b.reshape(2*2, 2*3) 
array([[0, 1, 2, 3, 4, 5], 
     [1, 2, 3, 4, 5, 6], 
     [2, 3, 4, 5, 6, 7], 
     [3, 4, 5, 6, 7, 8]]) 
+0

음 ...이 두 가지가 다릅니다. 하지만 numpy가 b에 대해 메모리를 할당하는 방법을 알고 싶습니다. –

+0

numpy 1.13의 경우.x를 사용하면 numpy.block을 사용할 수 있는데, 이는 여러 번 메모리를 미리 할당하는 것처럼 보입니다. –

+0

'np.block (nested_list)'는 다른 배열 인 2 차원 배열을 만들고 약간 더 느립니다. – hpaulj

답변

1

nested_list = [[a, a + 1], [a + 2, a + 3]] 3 개 새로운 배열 (합)을 더한 그 배열에 대한 포인터의 목록을 생성합니다. 파이썬 인터프리터의 기본적인 동작 일뿐입니다.

b = np.array(nested_list) : np.array은 복잡한 컴파일 된 함수이므로 심각한 파기가 없으면 정확히 무엇을하는지 알기 어렵습니다. 이전의 사용으로 인한 인상, 특히 구성 요소의 크기가 정확하게 일치하지 않는 경우의 오류는 입력을 스캔하여 생성 할 수있는 가장 높은 차원의 배열을 결정한 다음 필요할 경우 형식 변환을 사용하여 조각을 플러그 인합니다.

시간 비교가 쉽습니다. 메모리 사용을 추적하기가 더 어렵습니다. 그러나 데이터 복사가 가장 많은 시간을 소비한다고 가정 할 때 시간 테스트는 아마도 메모리 사용을위한 좋은 프록시 일 것입니다. 그리고 우리가 메모리 오류를 치지 않는 한, 우리는 일반적으로 메모리 사용보다 시간에 더 관심이 있습니다.

In [565]: alist = [[a,a+1],[a+2,a+3]] 
In [566]: allist = [[a.tolist(), (a+1).tolist()],[(a+2).tolist(), (a+3).tolist()]] 

In [567]: timeit np.array(alist) 
6.74 µs ± 63.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 
In [568]: timeit np.array(allist) 
9.92 µs ± 286 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 

중첩 된 배열 목록에서 작업하는 것은 순수한 목록에서 작업하는 것보다 약간 빠릅니다. 이러한 배열을 대상으로 블록으로 복사하는 중일 수 있습니다.

개별 스택은 또한뿐만 아니라 a+n 배열을 생성하지만, 속도가 현저하게 느려질 :

In [569]: timeit c = np.vstack([np.hstack([a, a + 1]), np.hstack([a + 2, a + 3])]) 
37.8 µs ± 39 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

np.stack가 (기본 축) np.array과 같은 역할을합니다. 너무 concatenate 사용 타이밍에 a+n 계산에 포함

In [570]: timeit np.stack(alist) 
28.7 µs ± 262 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

는 공정한 될 수있다 :

In [571]: %%timeit 
    ...: alist = [[a,a+1],[a+2,a+3]] 
    ...: np.stack(alist) 
    ...: 
38.6 µs ± 509 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) 
In [572]: %%timeit 
    ...: alist = [[a,a+1],[a+2,a+3]] 
    ...: np.array(alist) 
    ...: 
15.7 µs ± 177 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 

새로운 np.block 언급했다 - 뭔가 다른 생산하고

을 꽤 느린
In [573]: np.block(alist) 
Out[573]: 
array([[0, 1, 2, 1, 2, 3], 
     [3, 4, 5, 4, 5, 6], 
     [2, 3, 4, 3, 4, 5], 
     [5, 6, 7, 6, 7, 8]]) 
In [574]: timeit np.block(alist) 
126 µs ± 2.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 

block pr

np.vstack([np.hstack([a, a + 1]), np.hstack([a + 2, a + 3])]) 

np.arraynp.stack는 4D 어레이를 제조 : 중첩 스택과 같은 2 차원 배열 oduces. 2 차원으로 재구성 할 수 있지만 요소의 순서는 다릅니다. 일치 시키려면 모양을 바꾸기 전에 일부 조 변경을해야합니다. 예 :

In [590]: np.array(alist).transpose(0,2,1,3).reshape(4,6) 
Out[590]: 
array([[0, 1, 2, 1, 2, 3], 
     [3, 4, 5, 4, 5, 6], 
     [2, 3, 4, 3, 4, 5], 
     [5, 6, 7, 6, 7, 8]]) 
+0

np.block은 hstack + vstack 조합보다 약 3 배 느리다는 것은 놀랍습니다. 나는 그것이 그렇게 될 줄은 몰랐다. –

+0

1.14 [더 빠름] (https://github.com/numpy/numpy/pull/9667)'np.block' 구현으로 인해 비용이 약 1.7 배 느려집니다 (np.vstack ([ np.hstack (alist [0]), np.hstack (alist [1])])). 연결을 직접 사용하면'hstack'과'vstack'에 비해 2.5 배의 속도 향상을 얻을 수 있습니다 - 작은 배열의 경우 파이썬 함수를 실행하는 비용이 압도적입니다 – Eric

관련 문제