numpy의 차원 다루기

김상윤·2023년 3월 8일
0

새로운 차원 만들기

(n,)을 1) 브로드캐스팅을 위해 (1,n), (n,1)로 바꿔줄 수 있다 2)(H,W)의 흑백 이미지가 있다고 할때 tensorflow는 이미지가 (H,W,C) shape으로 무조건 맞춰주기를 규칙으로 한다.

reshape API를 활용하여 새로운 차원 만들기

import numpy as np
a = np.arange(9) (9,)

b = a.reshape((1,-1)) (1,9)
c = a.reshape((-1,1)) (9,1)

Reshape은 원소의 개수가 변하지 않는 상태에서 shape을 바꿔주는 연산이다. 따라서 차원을 많이 늘려야하는 상황에서는 코드의 가독성이 떨어질 우려가 있다.

import numpy as np
a = np.arange(9) (9,)

b = a.reshape((1,1,-1)) (1,1,9)
c = a.reshape((1,-1,1)) (1,9,1)
d = a.reshape((-1,1,1)) (9,1,1)

조심할 스타일의 코드

import numpy as np
a = np.random.normal(size=(100,200))

b = a.reshape((1,100,200))
c = a.reshape((100,200,1))

위와 같은 방식으로 차원을 늘려줄 수도 있지만 입력이 100x200에서 다른 값으로 변한다면 b,c 모두 직접 수정해줘야 하는 debugging하기 까다로운 코드가 된다.
다음과 같은 방법으로 해보자 : TUPLE UNPACKING

import numpy as np
a = np.random.normal(size=(100,150))

a.shape (100,150)
*a.shape 100 150
print((1,*a.shape)) (1, 100, 150)

a의 shape을 자동으로 unpacking하여 tuple을 만들어주기 때문에 a가 변하면 나머지 코드도 맞춰서 실행된다.

  • 단점은 (100,1,150)과 같은 중간 차원을 늘려주는 것은 안되지만 대부분의 경우 양끝의 차원을 늘려주는 것이 대부분이다.

Slicing을 이용한 새로운 차원 만들기

import numpy as np
a = np.arange(9)

row_vec1 = a[np.newaxis, :] (1,9)
row_vec2 = a[None, :] (1,9)

col_vec1 = a[:, np.newaxis] (9,1)
col_vec2 = a[:,None]  (9,1)

b = a[np.newaxis, ...]
c = a[..., np.newaxis]

newaxis는 내부적으로 None이다. 그러나 가독성면에서 a[None,:]보다 이해하기 좋다.

expand_dims API

차원을 늘려주기 위한 API이다.

import numpy as np
a = np.arange(9)
b = np.expand_dims(a, axis=0)
c = np.expand_dims(a, axis=1)

a.shape (9,)
b.shape (1,9)
c.shape (9,1)

expand_dims는 원하는 차원을 선택해서 늘려줄 수 있는 장점이 있다.

import numpy as np
a = np.arange(9)
b = np.expand_dims(a, axis=(0,1)) (1,1,9)
c = np.expand_dims(a, axis=(0,2)) (1,9,1)
d = np.expand_dims(a, axis=(1,2)) (9,1,1)

더 고급진 활용은 다음과 같다

import numpy as np
a = np.arange(9).reshape((3,3))
b = np.expand_dims(a, axis=0)		(1,3,3)
c = np.expand_dims(a, axis=-1) 	   (3,3,1)
d = np.expand_dims(a, axis=(0,-1)) (1,3,3,1)

쓸데없는 차원 없애기

(H,W,1)이라는 이미지가 있을 때 1을 없애고 텐서를 정리하는 용도로 사용할 수 있다.

flatten

import numpy as np
a = np.ones(shape=(1,10))
b = a.reshape((10,)) (10,)
c = a.reshape((-1,)) (10,)
d = a.flatten()
import numpy as np
a = np.ones(shape=(1,3,4))
b = np.ones(shape=(3,4,1))

c = a.reshape(*a.shape[1:]) (3,4)
d = b.reshape(*b.shape[:-1]) (3,4)

*a.reshape[1:]은 unpacking된 (1,3,4) tuple을 1번 index부터 끝까지 가져온다는 의미이다. 따라서 1은 안가져오고 (3,4)만 tuple로 가져온다.
*b.reshape[:-1]도 마찬가지로 마지막 차원 전까지만 tuple로 가져오는 명령이다.

index와 slice를 통한 차원 정리

import numpy as np
a = np.arange(9).reshape((3,3))

row, col = a[1,:], a[:,1] -> shape (3,)

a[1,:], a[:,1]은 차원 하나를 indexing하고 나머지는 slicing했다. 이를 통해 차원 하나가 떨어져 나갔다. 왜냐하면 a란? (3,)가 3개 모여있는 ndarray이기 때문이다.

또 다른 indexing을 통한 차원 없애기 예시

import numpy as np
a = np.ones(shape=(1,3,4))
b = np.ones(shape=(3,4,1))

c = a[0,...]  (3,4)
d = b[...,0]  (3,4)

Squeeze API

1을 차원값으로 가지는 차원을 전부다 없애주는 API

import numpy as np
a = np.ones(shape=(1,3,4))

c = np.squeeze(a)	(3,4)
d = a.squeeze() 	(3,4)

여러 개의 1인 차원들이 존재할 때

import numpy as np
a = np.ones(shape=(1,1,3,1,4,1))

c = np.squeeeze(a)	(3,4)
d = a.squeeze()		(3,4)

index/ slicing등을 이용하여 깔끔하게 만들어주기 쉽지 않고 불편한 케이스이다.

조심할 것

  • 차원을 없애고 난 다음에 남아있는 각각의 차원이 무엇을 의미하는지 차원 의미를 적어놓도록 하자

ndarray의 차원 바꾸기

np.swapaxes API

API를 이용하여 차원을 바꿀 위치를 지정해주고 서로 위치를 교체한다.

import numpy as np
a = np.random.normal(size = (3,4,5,6))

b = np.swapaxes(a,0,1)  (4,3,5,6)
c = np.swapaxes(a,0,2)  (5,4,3,6)
d = np.swapaxes(a,0,3)  (6,4,5,3)

swapaxes는 2개의 차원을 서로 바꿔줄 때 유용하게 사용할 수 있는 API이다.
주로 활용하는 방법

import numpy as np
a = np.random.normal(size = (3,200,100))
b = np.swapaxes(a,0,-1)

처음 차원과 마지막 차원을 서롤 바꿔준다.

np.moveaxis API

import numpy as np
a = np.random.normal(size=(3,4,5,6))
b = np.moveaxis(a, source = 0, destination = 1)  (4,3,5,6)
c = np.moveaxis(a, source = 0, destination = 2)  (4,5,3,6)
d = np.moveaxis(a, source = 0, destination = 3)  (4,5,6,3)

source 차원의 값을 destination 차원으로 옮기고 나머지를 옆으로 밀어서 빈자리를 채운다.

np.transpose API

import numpy as np
a = np.random.normal(size=(3,4))

b = np.transpose(a)  shape (4,3)
c = a.T				 shape (4,3)

transpose를 알아야할 이유
1. 사람들이 많이 사용하는 API이다.
2. 고차원 텐서를 한번에 순서를 바꿔줄 수 있다.

import numpy as np
a = np.random.normal(size=(3,4,5,6,7))

b = np.transpose(a)  shape (7,6,5,4,3)
c = a.T				 shape (7,6,5,4,3)

np.transpose의 axes 활용

import numpy as np
a = np.random.normal(size = (3,4,5))

b = np.transpose(a, axes = (0,1,2))    (3,4,5)
c = np.transpose(a, axes = (1,2,0))	   (4,5,3)
d = np.transpose(a, axes = (2,0,1))    (5,3,4)
e = np.transpose(a, axes = (2,1,0))    (5,4,3)

source array의 index를 이용하여 값들을 원하는 위치에 정렬시킨다.

연습문제

import numpy as np
a = np.random.normal(size=(3,4))

b = np.transpose(a, axes = tuple(range(a.dim))[::-1])

a.dim은 4이고 tuple.range(a.dim)은 (0 1 2 3)을 반환한다. 마지막으로 [::-1]은 (3 2 1 0)으로 바꿔준다.

profile
AI 대학원 지망생

0개의 댓글