연속 배열과 비 연속 배열의 차이점은 무엇입니까?
에서 NumPy와 수동 모양 변경 () 함수에 대한, 그것은 말한다
>>> a = np.zeros((10, 2))
# A transpose make the array non-contiguous
>>> b = a.T
# Taking a view makes it possible to modify the shape without modifying the
# initial object.
>>> c = b.view()
>>> c.shape = (20)
AttributeError: incompatible shape for a non-contiguous array
내 질문은 다음과 같습니다.
- 연속 및 비 연속 배열이란 무엇입니까? 연속 메모리 블록 이란 무엇입니까? 와 같이 C의 연속 메모리 블록과 유사 합니까?
- 이 둘 사이에 성능 차이가 있습니까? 둘 중 하나를 언제 사용해야합니까?
- 전치가 배열을 비 연속적으로 만드는 이유는 무엇입니까?
- 왜
c.shape = (20)오류가 발생incompatible shape for a non-contiguous array합니까?
답변 해 주셔서 감사합니다!
연속 배열은 깨지지 않은 메모리 블록에 저장된 배열 일뿐입니다. 배열의 다음 값에 액세스하려면 다음 메모리 주소로 이동합니다.
2D 배열을 고려하십시오 arr = np.arange(12).reshape(3,4). 다음과 같이 보입니다.
컴퓨터 메모리에의 값은 arr다음과 같이 저장됩니다.
이 수단은, arrA는 C 연속 때문에 어레이 행이 메모리의 연속 블록으로 저장된다. 다음 메모리 주소는 해당 행의 다음 행 값을 보유합니다. 한 열 아래로 이동하려면 세 블록을 건너 뛰면됩니다 (예 : 0에서 4로 건너 뛰는 것은 1,2, 3을 건너 뛰는 것을 의미합니다).
배열을로 arr.T바꾼다는 것은 인접한 행 항목이 더 이상 인접한 메모리 주소에 없기 때문에 C 연속성이 손실됨을 의미합니다. 그러나, arr.T이다 포트란 연속 때문에 열이 메모리의 연속 블록에는 :
성능 측면에서, 서로 옆에있는 메모리 주소에 액세스하는 것은 더 "확산"되는 주소에 액세스하는 것보다 훨씬 빠릅니다 (RAM에서 값을 가져 오면 여러 인접 주소를 가져 와서 CPU에 캐시 할 수 있음). 연속 배열에 대한 작업이 종종 더 빠르다는 것을 의미합니다.
C 연속 메모리 레이아웃의 결과로 행 단위 연산은 일반적으로 열 단위 연산보다 빠릅니다. 예를 들어, 일반적으로
np.sum(arr, axis=1) # sum the rows
다음보다 약간 빠릅니다.
np.sum(arr, axis=0) # sum the columns
마찬가지로 포트란 연속 배열의 경우 열에 대한 작업이 약간 더 빠릅니다.
마지막으로 새 모양을 할당하여 Fortran 연속 배열을 평면화 할 수없는 이유는 무엇입니까?
>>> arr2 = arr.T
>>> arr2.shape = 12
AttributeError: incompatible shape for a non-contiguous array
이것이 가능해 지려면 NumPy는 다음 arr.T과 같이 행을 합쳐야합니다.
( shape속성을 직접 설정하는 것은 C 순서를 가정합니다. 즉 NumPy는 작업을 행 단위로 수행하려고합니다.)
이것은 불가능합니다. 모든 축에 대해 NumPy 는 배열의 다음 요소에 도달하기 위해 일정한 스트라이드 길이 (이동할 바이트 수) 를 가져야합니다 . arr.T이러한 방식으로 평면화 하려면 배열의 연속 값을 검색하기 위해 메모리에서 앞뒤로 건너 뛰어야합니다.
arr2.reshape(12)대신 작성 하면 NumPy는 arr2의 값을 새 메모리 블록에 복사합니다 (이 모양에 대한 원래 데이터에 대한 뷰를 반환 할 수 없기 때문에).
12 개의 다른 배열 값이있는이 예제가 도움이 될 것입니다.
In [207]: x=np.arange(12).reshape(3,4).copy()
In [208]: x.flags
Out[208]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
...
In [209]: x.T.flags
Out[209]:
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
...
C order값은 생성 된 순서에 있습니다. 전치 사람이 아니다
In [212]: x.reshape(12,) # same as x.ravel()
Out[212]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
In [213]: x.T.reshape(12,)
Out[213]: array([ 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11])
둘 다 1d 뷰를 얻을 수 있습니다.
In [214]: x1=x.T
In [217]: x.shape=(12,)
the shape of x can also be changed.
In [220]: x1.shape=(12,)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-220-cf2b1a308253> in <module>()
----> 1 x1.shape=(12,)
AttributeError: incompatible shape for a non-contiguous array
But the shape of the transpose cannot be changed. The data is still in the 0,1,2,3,4... order, which can't be accessed accessed as 0,4,8... in a 1d array.
But a copy of x1 can be changed:
In [227]: x2=x1.copy()
In [228]: x2.flags
Out[228]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
...
In [229]: x2.shape=(12,)
Looking at strides might also help. A strides is how far (in bytes) it has to step to get to the next value. For a 2d array, there will be be 2 stride values:
In [233]: x=np.arange(12).reshape(3,4).copy()
In [234]: x.strides
Out[234]: (16, 4)
To get to the next row, step 16 bytes, next column only 4.
In [235]: x1.strides
Out[235]: (4, 16)
Transpose just switches the order of the strides. The next row is only 4 bytes- i.e. the next number.
In [236]: x.shape=(12,)
In [237]: x.strides
Out[237]: (4,)
Changing the shape also changes the strides - just step through the buffer 4 bytes at a time.
In [238]: x2=x1.copy()
In [239]: x2.strides
Out[239]: (12, 4)
Even though x2 looks just like x1, it has its own data buffer, with the values in a different order. The next column is now 4 bytes over, while the next row is 12 (3*4).
In [240]: x2.shape=(12,)
In [241]: x2.strides
Out[241]: (4,)
And as with x, changing the shape to 1d reduces the strides to (4,).
For x1, with data in the 0,1,2,... order, there isn't a 1d stride that would give 0,4,8....
__array_interface__ is another useful way of displaying array information:
In [242]: x1.__array_interface__
Out[242]:
{'strides': (4, 16),
'typestr': '<i4',
'shape': (4, 3),
'version': 3,
'data': (163336056, False),
'descr': [('', '<i4')]}
The x1 data buffer address will be same as for x, with which it shares the data. x2 has a different buffer address.
You could also experiment with adding a order='F' parameter to the copy and reshape commands.
'IT TIP' 카테고리의 다른 글
| npm의 일반 종속성에 대한 bundledDependencies의 장점 (0) | 2020.10.31 |
|---|---|
| 패딩에만 배경색을 추가 할 수 있습니까? (0) | 2020.10.31 |
| React Native에서 텍스트를 세로 (90도 회전)로 만들려면 어떻게해야합니까? (0) | 2020.10.31 |
| 프로그래밍 방식으로 색상 밝게 (0) | 2020.10.31 |
| 자바 스크립트에서 객체가 해시인지 배열인지 어떻게 식별 할 수 있습니까? (0) | 2020.10.31 |



