본문 바로가기

머신러닝 공부

numpy(2)

SMALL

넘파이 ndarray의 axis 축

ndarray의 shape는 행, 열, 높이 단위로 부여되는 것이 아니라 axis0, axis1, axis2 와 같이 axis 단위로 붙게 됩니다.

그림에서 보듯이 axis 기준이 차원에 따라서 계속 변하는 것을 볼 수 있습니다. 이런 이유로 혼란을 많이 겪게 됩니다.

우선 2차원 배열에서 보겠습니다. 

2차원 배열에서 [1, 2, 3, 4]와 같은 개별 원소가 여러개 있는게 2차원 배열입니다.

이렇듯 단일 원소로 표현될 수 있는 가장 작은 단위는 맨 마지막 axis입니다. (따라서 axis 1이 되는 것입니다.)

결과적으로 단일 원소 즉, 가장 작은 원소로부터 axis 기준을 거꾸로 잡아서 나아가는게 이해하는데 도움이 될 것 입니다.

 

이후 shape를 나타낼 때 2차원 배열의 shape(2, 4)에서는 2가 axis0, 4는 axis1이란 것을 알 수 있습니다.

 

 

ndarray를 편리하게 생성하기 - arange, zeros, ones

특정 크기와 차원을 가진 ndarray를 연속값이나 0또는 1로 초기화 생성해야 할 경우 arange(), zeros(), ones()를 이용해 쉽게 ndarray를 생성할 수 있습니다. 주로 테스트 용으로 데이터를 만들거나 데이터를 일괄적으로 초기화해야 할 경우에 사용됩니다.

 

1. np.arange(10)

==> 0~9까지 10개의 원소를 가지는 1차원 ndarray를 만들어줍니다.

2. np.zeros((3,2), dtype='int32')

==> shape형태인 (3,2)로 하고 개별원소값은 0으로 된 ndarray를 만들어줍니다.

3. np.ones((3,2))

==> 2번과 거의 비슷하지만 개별원소값을 1로 만들어줍니다.

(데이터타입을 따로 지정을 해주지 않는다면 default 값으로 float64가 나옵니다.)

 

 

ndarray의 차원과 크기를 변경하는 reshape()

앞선 글에서도 ndarray의 shape가 중요하다고 했습니다. ndarray의 차원과 크기를 변경할 수 있는 reshape()에 대해 알아보겠습니다.

reshape를 하는데 조금 헷갈리는 요소가 있을 수 있습니다. 대표적으로 -1을 썼을 때 입니다.

array1.shape이 (10,)라고 할 때 reshape(-1, 5)라는 의미는 coloumn은 5로 하는데 행은 가변적으로 알아서 바꿔주라는 뜻입니다. 따라서 -1이 아닌 인자값에 해당하는 axis크기를 인자값으로 고정하여 ndarray의 shape을 변환합니다.

 

또한 reshape(-1,)과 reshape(-1, 1)은 다른것 입니다.

주로 머신러닝 API의 인자로 1차원 ndarray를 명확하게 2차원 ndarray로 변환하여 입력하기를 원하거나, 또는 반대의 경우가 있을 경우 reshape()를 이용하여 ndarray의 형태를 변환시켜 주는데 사용됩니다.

 

arange(), zeros(), ones()를 실습해보겠습니다.

sequence_array = np.arange(10)
print(sequence_array)
print(sequence_array.dtype, sequence_array.shape)

#(3, 2) shape을 가지는 모든 원소가 0, dtype은 int32 인 ndarray 생성.  
zero_array = np.zeros((3, 2), dtype='int32')
print(zero_array)
print(zero_array.dtype, zero_array.shape)

#(3, 2) shape을 가지는 모든 원소가 1인 ndarray 생성. ,
one_array = np.ones((3, 2))
print(one_array)
print(one_array.dtype, one_array.shape)

sequence_array에서는 arange(10)을 써서 1차원 ndarray를 만들어냈으며, zero_array는 np.zeros를 이용하여서 데이터타입까지 설정해 개별인자가 0인 ndarray 2차원을 만들어 냈습니다. 마지막으로 one_array도 개별인자가 1이고 앞서 비슷한 배열을 만들게 되었습니다.

[0 1 2 3 4 5 6 7 8 9]
int32 (10,)
[[0 0]
 [0 0]
 [0 0]]
int32 (3, 2)
[[1. 1.]
 [1. 1.]
 [1. 1.]]
float64 (3, 2)

앞선 코드들의 output입니다.

 

이제 ndarray의 차원과 크기를 변경하는 reshape를 간단하게 실습해보겠습니다.

array1 = np.arange(10)
print('array1:\n', array1)

# (2, 5) shape으로 변환
array2 = array1.reshape(2, 5)
print('array2:\n',array2)

#(5, 2) shape으로 변환. 
array3 = array1.reshape(5,2)
print('array3:\n',array3)

array1을 arange로 만들어주며 array2,array3는 reshape()로 만들며 형태를 확인합니다

array1:
 [0 1 2 3 4 5 6 7 8 9]
array2:
 [[0 1 2 3 4]
 [5 6 7 8 9]]
array3:
 [[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]

여기서 reshape를 시킬 때 array1.reshape(4,3)과 같이 1차원 배열 인자가 10개인데 배열의 size에 맞지 않게 reshape를 할 수가 없어 에러가 날 수 있으므로 유의하여야 합니다

 

array1 = np.arange(8)
array3d = array1.reshape((2,2,2))
print('array3d:\n',array3d.tolist())

# 3차원 ndarray를 2차원 ndarray로 변환하되 칼럼갯수는 1
array5 = array3d.reshape(-1, 1)
print('array5:\n',array5.tolist())
print('array5 shape:',array5.shape)

# 1차원 ndarray를 2차원 ndarray로 변환화되 칼럼 갯수는 1
array6 = array1.reshape(-1, 1)
print('array6:\n',array6.tolist())
print('array6 shape:',array6.shape)

# 3차원 array를 1차원으로 변환
array1d = array3d.reshape(-1,)
print(array1d)

다음과 같은 1차원 ndarray를 생성하고 reshape를 이용해서 다양한 차원의 ndarray를 생성해보면 결과는 다음과 같다

array3d:
 [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]
array5:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array5 shape: (8, 1)
array6:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array6 shape: (8, 1)
[0 1 2 3 4 5 6 7]

마지막 줄의 reshape(-1,) 하면 무조건 1차원 배열로 반환하는 것임을 확인할 수 있습니다.

LIST