NumPy의 transpose () 메서드는 배열의 축을 어떻게 변경합니까?


81
In [28]: arr = np.arange(16).reshape((2, 2, 4))

In [29]: arr
Out[29]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])


In [32]: arr.transpose((1, 0, 2))
Out[32]: 
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

정수 튜플을 transpose()함수에 전달하면 어떻게됩니까?

구체적으로 말하자면, 이것은 3D 배열입니다. 축의 튜플을 전달할 때 NumPy는 배열을 어떻게 변환 (1, 0 ,2)합니까? 이 정수가 참조하는 행 또는 열을 설명 할 수 있습니까? 그리고 NumPy의 맥락에서 축 번호는 무엇입니까?



2
0첫 번째 축, 1두 번째, 2세 번째 등 ... 정렬하려는 새 순서 axestranspose제공하는 매개 변수 입니다. 예를 들어 첫 번째, 두 번째, 첫 번째, 세 번째.
Jaime

3D 디스플레이에는 블록, 행 및 열이 있습니다. 조옮김이 블록과 행의 순서를 변경하여 열을 변경하지 않았습니다. 1 번째 블록의 2 번째 행이었던 것이 2 번째 블록의 1 번째 행이됩니다.
hpaulj

답변:


190

배열을 전치하기 위해 NumPy는 각 축의 모양과 보폭 정보를 바꿉니다. 다음은 걸음 걸이입니다.

>>> arr.strides
(64, 32, 8)

>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)

조바꿈 작업은 축 0과 축 1의 보폭을 바꿨습니다.이 축의 길이도 바뀝니다 (두 길이 모두이 2예에 있음).

이를 위해 데이터를 복사 할 필요가 없습니다. NumPy는 단순히 새 배열을 구성하기 위해 기본 메모리를 보는 방식을 변경할 수 있습니다.


보폭 시각화

stride 값은 배열 축의 다음 값에 도달하기 위해 메모리에서 이동해야하는 바이트 수를 나타냅니다.

이제 3D 배열 arr은 다음과 같습니다 (레이블이 지정된 축 포함).

여기에 이미지 설명 입력

이 배열은 연속 된 메모리 블록에 저장됩니다 . 본질적으로 1 차원입니다. 3D 객체로 해석하려면 NumPy가 세 축 중 하나를 따라 이동하기 위해 일정한 수의 바이트 위로 점프해야합니다.

여기에 이미지 설명 입력

각 정수는 8 바이트의 메모리를 차지하므로 (int64 dtype 사용) 각 차원의 stride 값은 점프해야하는 값 수의 8 배입니다. 예를 들어, 축 1을 따라 이동하려면 4 개의 값 (32 바이트)이 점프되고 축 0을 따라 이동하려면 8 개의 값 (64 바이트)이 점프되어야합니다.

쓸 때 arr.transpose(1, 0, 2)축 0과 1을 교환합니다. 전치 된 배열은 다음과 같습니다.

여기에 이미지 설명 입력

NumPy가해야 할 일은 축 0과 축 1의 보폭 정보를 바꾸는 것입니다 (축 2는 변경되지 않음). 이제 우리는 축 0보다 축 1을 따라 더 이동해야합니다.

여기에 이미지 설명 입력

이 기본 개념은 배열 축의 모든 순열에 적용됩니다. 전치를 처리하는 실제 코드는 C로 작성되었으며 여기 에서 찾을 수 있습니다 .


7

문서에 설명 대로 :

기본적으로 치수를 반대로하고 그렇지 않으면 주어진 값에 따라 축을 순회합니다.

따라서 axes새로운 차원 순서를 정의 하는 선택적 매개 변수를 전달할 수 있습니다 .

예를 들어 RGB VGA 픽셀 배열의 처음 두 차원을 전치합니다.

 >>> x = np.ones((480, 640, 3))
 >>> np.transpose(x, (1, 0, 2)).shape
 (640, 480, 3)

1
안녕하세요, 답변 해 주셔서 감사합니다. 그러나 나는 여전히이 문제를 이해할 수 없습니다. 보시다시피 arr의 모양은 (2,2,4)이고 arr.transpose (1,0,2)도 (2,2,4)입니다. 이것은 3 차원 배열입니다. (1,0,2)를 전달할 때 배열을 변환하는 방법, 1,0,2가 참조하는 행 또는 열을 설명 할 수 있습니까? 그리고 numpy 측면에서 축 번호는 무엇입니까?
Frank Hu

1
@FrankHu는 3D 공간에서 시각화하므로 여기서 x, y 축 회전이 발생합니다. (1,0,2)는 (0,1,2)에서 전치되었으므로 처음 2 축이 전환됩니다. 0은 축의 인덱스 번호입니다. 말은, X는 Y는 Z는 0, 1, 2에 매핑
CodeFarmer

5

C 표기법에서 배열은 다음과 같습니다.

int arr[2][2][4]

이것은 2 개의 2D 배열이있는 3D 배열입니다. 각각의 2D 배열에는 2 개의 1D 배열이 있으며 각 1D 배열에는 4 개의 요소가 있습니다.

따라서 3 차원이 있습니다. 축은 0, 1, 2이고 크기는 2, 2, 4입니다. 이것은 정확히 numpy가 N 차원 배열의 축을 처리하는 방법입니다.

따라서 arr.transpose((1, 0, 2))축 1을 가져 와서 위치 0, 축 0에 놓고 위치 1, 축 2에 놓고 위치 2에 둡니다. 축을 효과적으로 순열하고 있습니다.

0 -\/-> 0
1 -/\-> 1
2 ----> 2

즉, 1 -> 0, 0 -> 1, 2 -> 2. 대상 축은 항상 순서대로되어 있으므로 소스 축을 지정하기 만하면됩니다. 순서대로 튜플을 읽습니다 (1, 0, 2)..

이 경우 [2][2][4]축 0과 1이 같은 크기 (2)를 가졌기 때문에 새 배열 차원이 다시 입니다.

더 흥미로운 것은 (2, 1, 0)배열을 제공 하는 전치 입니다 [4][2][2].

0 -\ /--> 0
1 --X---> 1
2 -/ \--> 2

즉, 2 -> 0, 1 -> 1, 0 -> 2. 순서대로 튜플을 읽습니다 (2, 1, 0)..

>>> arr.transpose((2,1,0))
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])

당신은 int[4][2][2].

모든 차원의 크기가 다른지 더 잘 이해할 수 있으므로 각 축의 위치를 ​​확인할 수 있습니다.

왜 첫 번째 내부 요소 [0, 8]입니까? 당신은 용지 두 장이로 3D 배열을 시각화하는 경우 때문에 0그리고 8왼쪽 상단에 하나의 종이에 하나 다른 용지에 하나, 둘, 줄 지어있다. 조옮김 (2, 1, 0)으로써 당신은 종이에서 종이로의 방향이 이제 종이를 따라 왼쪽에서 오른쪽으로 행진하고 왼쪽에서 오른쪽으로 이제 종이에서 종이로 이동하기를 원한다고 말하는 것입니다. 왼쪽에서 오른쪽으로 4 개의 요소가 있었으므로 이제 대신 4 개의 종이가 있습니다. 그리고 2 개의 논문이 있었으므로 이제 왼쪽에서 오른쪽으로 2 개의 요소가 있습니다.

끔찍한 ASCII 아트에 대해 죄송합니다. ¯\_(ツ)_/¯


당신이 제공하는 튜플이 transpose()수학적 순열이 아니라고 생각하는 것이 맞 습니까? 문자 그대로 "이제 축을이 위치에 놓으십시오"라는 명령 일 뿐입니 까? 예를 들어 .transpose(p, q, r, s)"축을 p0 번, q1 번, r2 번, s3 번" 이라고 말하는 건가요? 아니면 다른 방법으로 본다는 b = a.transpose(axes)의미 b.shape == tuple(a.shape[i] for i in axes)입니까?
Tim

축을 ASCII 아트로 바꾸는 아이디어는 내 이해를 명확히합니다. 고마워요
K_inverse

0

질문과 예제는 Wes McKinney의 Python for Data Analysis 책에서 비롯된 것 같습니다 . 이 기능은 4.1 장에transpose 언급되어 있습니다. 배열 전치 및 축 교환 .

더 높은 차원의 배열의 transpose경우 축을 순회하기 위해 축 번호의 튜플을 허용합니다 (추가적인 마음 굽힘을 위해).

여기서 "permute"는 "재정렬"을 의미하므로 축 순서를 다시 정렬합니다.

의 숫자 .transpose(1, 0, 2)는 원본과 비교하여 축의 순서가 변경되는 방식 을 결정합니다. 를 사용하는 .transpose(1, 0, 2)것은 "첫 번째 도끼를 두 번째 도끼로 바꾸십시오."라는 의미입니다. 를 사용 .transpose(0, 1, 2)하면 변경할 것이 없기 때문에 배열이 동일하게 유지됩니다. 기본 순서입니다.

(2, 2, 4)크기 배열이 있는 책의 예는 첫 번째와 두 번째 축의 크기가 동일하기 때문에 명확하지 않습니다. 따라서 최종 결과는 행 arr[0, 1]arr[1, 0].

각 차원이 다른 크기를 갖는 3 차원 배열로 다른 예제를 시도하면 재배치 부분이 더 명확 해집니다.

In [2]: x = np.arange(24).reshape(2, 3, 4)

In [3]: x
Out[3]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

In [4]: x.transpose(1, 0, 2)
Out[4]: 
array([[[ 0,  1,  2,  3],
        [12, 13, 14, 15]],

       [[ 4,  5,  6,  7],
        [16, 17, 18, 19]],

       [[ 8,  9, 10, 11],
        [20, 21, 22, 23]]])

여기에서 원래 배열 크기는 (2, 3, 4). 우리는 1 일과 2 일을 변경 했으므로 (3, 2, 4)크기가됩니다. 재배치가 정확히 어떻게 일어 났는지 자세히 살펴보면; 숫자 배열이 특정 패턴으로 변경된 것 같습니다. @ RobertB 의 종이 비유를 사용하여 두 개의 숫자 청크를 시트에 쓰고 각 시트에서 하나의 행을 가져와 배열의 한 차원을 구성하면 이제 3x2x4 크기의 배열이됩니다. , 가장 바깥 쪽에서 가장 안쪽 레이어까지 계산합니다.

[ 0,  1,  2,  3] \ [12, 13, 14, 15]

[ 4,  5,  6,  7] \ [16, 17, 18, 19]

[ 8,  9, 10, 11] \ [20, 21, 22, 23]

다른 크기의 배열로 플레이하고 작동 방식에 대한 더 나은 직관을 얻기 위해 다른 축을 변경하는 것이 좋습니다.


-3

요약하면 a.transpose () [i, j, k] = a [k, j, i]

a = np.array( range(24), int).reshape((2,3,4))
a.shape gives (2,3,4)
a.transpose().shape gives (4,3,2)  shape tuple is reversed.

튜플 매개 변수가 전달되면 축은 튜플에 따라 순열됩니다. 예를 들면

a = np.array (range (24), int) .reshape ((2,3,4))

a [i, j, k]는 a.transpose ((2,0,1)) [k, i, j]와 같습니다.

축 0이 2 위를 차지함

축 1이 3 위를 차지함

축 2 이야기 1 위

물론 전치하기 위해 전달 된 튜플 매개 변수의 값이 고유하고 범위 (축 수)에 있는지주의해야합니다.


지정된 축으로 전치 할 때 발생하는 OP의 질문을 해결하지 않았습니다 .
Robert B

축이 지정 될 때 질문에 추가 된 응답.
Raghu Ram
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.