본문 바로가기

C

[Numpy] 넘파이 브로드캐스팅 및 슬라이싱 이해하기

넘파이로 가즈아ㅏ

 

Numpy는 Numerical Python의 약자로, 고성능 과학계산 컴퓨팅과 데이터 분석에 사용하는 패키지이다.

특히 머신러닝/딥러닝 알고리즘에 사용될 텐서 계산하는데 많이 쓰인다.

 

빠르고 메모리를 효율적으로 사용하여 벡터 산술연산

세련된 브로드캐스팅 기능을 제공하는 다차원 배열인 ndarray

반복문을 작성할 필요 없이 전체 데이터 배열에 대해 빠른 연산을 제공하는 표준 수학 함수

배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 올려진 파일을 사용하는 도구

 

 

 

1. 브로드캐스팅

 

넘파이의 가장 강력한 장점 중 하나를 꼽자면 브로드캐스팅이 아닐까 싶다.

모양이 다른 배열들 간의 연산을 위해, 몇가지 룰을 적용해 배열을 자동적으로 변환하는 자체 기능이다.


[규칙 1] Dimension 크기를 같게 해줌 (차원 추가)
두 배열의 차원 수가 다르면 , 더 작은 수의 차원을 가진 배열 형상의 가장 앞쪽 왼쪽 을 1 로 채움

[규칙 2] Dimension 내 형상을 같게 해줌 (형상 확장)
두 배열의 형상이 어떤 차원에서도 일치하지 않는다면 , 해당 차원의 형상이 1 인 배열이 다른 형상
과 일치하도록 늘어남

[규칙 3] 위의 두 규칙을 적용했는데
임의의 차원에서 크기가 일치하지 않고 1 도 아니라면 오류

 

예제)

import numpy as np

a = np.one((2,3))

>>> print(a)
array([[1,1,1],
	[1,1,1]))
        
b = np.arange(3)

>>> print(b)
array([0,1,2])

a.shape # (2,3)
b.shape # (3,)

>>> print(a+b)
array([[1,2,3],
	[1,2,3]))

 

위의 예제에서는 아래와 같은 방식으로 브로드캐스팅이 진행된다.

 

by [규칙1]

b의 첫번째 차원에 1을 생성 > b.shape = (1,3)

by [규칙2]

b의 첫번째 차원의 형상을 2로 확장 > b.shape = (2,3)

 

a.shape과 b.shape이 동일하므로 연산이 가능하다.

 

import numpy as np

a = np.arange(3).reshape((3,1))

>>> print(a)
array([[0], [1], [2]])

b = np.arange(3)

>>> print(b)
array([0,1,2])

 

by [규칙1]

b의 첫번째 차원에 1이 생성됨 > b.shape = (1,3)

by [규칙2]

a의 두번째 차원에 형상을 3으로 확장 > a.shape = (3,3)

b의 첫번째 차원에 형상을 3으로 확장 > b.shape = (3,3)

 

a.shape과 b.shape이 동일하므로 연산이 가능하다.

 

여기에 차원이 더 늘어나도, 해당 규칙을 적용하면 다차원 배열의 산술연산이 가능하고,

이를 알아서 해주니까 이제 우린 룰에 어긋나지만 않게 쉐입을 잡고 쓰기만 하면 된다.

 

2. 색인과 슬라이싱

 

import numpy as np

arr = np.arange(10)

arr[5:8] = 228

>>> print(arr)
[0,1,2,3,4,228,228,228,8,9]

 

기본적인 슬라이싱은 똑같지만, 슬라이싱 조각을 어떻게 띄우냐에 차이점이 있다.

배열 슬라이싱은 원본 배열의 뷰라는 점이다.

위와 같이 브로드캐스팅을 적용하면 슬라이싱 조각이 변하는 것이 아니라 원본 array의 value도 변한다.

따라서 데이터는 복사되지 않고 뷰에 대한 변경이 원본 데이터에 그대로 반영 된다.

이러한 점으로 numpy가 데이터 복사를 남발하지 않는 것이 메모리 측면에서 이득을 볼 수 있고,

굳이 복사를 하자면 arr[5:8].copy() 와 같이 접근할 수 있겠다.

 

[참고자료]

https://numpy.org/doc/1.21/