간단히 말해, numpy.newaxis는 numpy array의 차원을 늘려준다고 보면 된다.
- 1D 배열은 2D 배열이 됩니다
- 2D 배열은 3D 배열이 됩니다
- 3D 배열은 4D 배열이 됩니다
- 4D 배열은 5D 배열이 됩니다
다음은 1D array에서 2D array로 차원을 늘려주는 그림이다.
np.newaxis를 사용함에 있어 3가지 정도의 시나리오가 적합해 보인다.
시나리오-1
1D array를 row vector나 column vector로 사용하고 싶을 경우
numpy에서 array를 만들면 shape은 아래와 같이 나타낸다.
1
2
3
4
|
# 1D array
In [7]: arr = np.arange(4)
In [8]: arr.shape
Out[8]: (4,)
|
cs |
x자리만 4고 y자리는 공란이다.
vector로 보고 indexing을 한다던지 연산을 한다던지 해도 껄끄러운 상태가 되겠다.
그래서 np.newaxis를 사용해 다음과 같이 해결할 수 있다.
1
2
3
4
5
6
7
8
9
|
# make it as row vector by inserting an axis along first dimension
In [9]: row_vec = arr[np.newaxis, :]
In [10]: row_vec.shape
Out[10]: (1, 4)
# make it as column vector by inserting an axis along second dimension
In [11]: col_vec = arr[:, np.newaxis]
In [12]: col_vec.shape
Out[12]: (4, 1)
|
cs |
시나리오-2
shape이 다른 array간 연산(numpy broadcasting)을 할때 유용하다.
아래와 같이 모양이 다른 array끼리 덧셈 한번 해보자.
1
2
|
x1 = np.array([1, 2, 3, 4, 5])
x2 = np.array([5, 4, 3])
|
cs |
shape이 다른 array를 연산하면 NumPy는 ValueError을 발생시킨다.
1
|
ValueError: operands could not be broadcast together with shapes (5,) (3,)
|
cs |
이 상황에서 np.newaxis는 NumPy가 브로드 캐스트 할 수 있도록 배열 중 하나의 차원을 늘리는 데 사용할 수 있다.
1
2
3
4
5
6
7
|
In [2]: x1_new = x1[:, np.newaxis] # x1[:, None]
# now, the shape of x1_new is (5, 1)
# array([[1],
# [2],
# [3],
# [4],
# [5]])
|
cs |
이제 다음과 같은 계산이 가능하다.
1
2
3
4
5
6
7
|
In [3]: x1_new + x2
Out[3]:
array([[ 6, 5, 4],
[ 7, 6, 5],
[ 8, 7, 6],
[ 9, 8, 7],
[10, 9, 8]])
|
cs |
시나리오-3
시나리오 1과 유사하다. 그러나 배열을 더 높은 차원 np.newaxis으로 승격시키기 위해 두 번 이상 사용할 수 있다. 이러한 연산은 때때로 고차원 배열 ( 즉, Tensor )에 필요하다.
1
2
3
4
5
6
7
8
9
10
|
In [124]: arr = np.arange(5*5).reshape(5,5)
In [125]: arr.shape
Out[125]: (5, 5)
# promoting 2D array to a 5D array
In [126]: arr_5D = arr[np.newaxis, ..., np.newaxis, np.newaxis]
In [127]: arr_5D.shape
Out[127]: (1, 5, 5, 1, 1)
|
cs |
np.reshape vs np.newaxis 추가 설명
np.newaxis는 결국 차원을 임시적으로 추가함으로써 차원의 변화를 주는 것이다.
그리고 우리느 np.reshape라는 기능을 쓰면 되지 않느냐라고 질문할 수도 있다.
하지만 np.reshape는 변환 전 차원의 합과 변환 후 차원의 합이 같아야 한다.
(4,1)을 변환한다는 기준으로 (2,2)는 reshape 가능한데 (4,1)을 (3,3)으로 부꿀수는 없다는 게 제약이 있는 것이다.
* 4개의 원소를 2by2로 재배열한다는 느낌이 reshape인것이다. 없는 걸 만들어내는 것은 아니다...
newaxis = None
그리고 newaxis는 None과 같은 객체이다.
즉, np.newaxis를 대신해서 None를 사용해도 무방하다는 것이다.
참고