Python/NumPy | Pandas

[Python] NumPy - 배열의 연산 1

비번변경 2022. 11. 19. 17:01

벡터화 연산

NumPy가 지원하는 벡터화 연산을 사용하면 반복문을 명시적으로 사용하지 않아도 배열의 모든 원소에 대한 반복 연산을 할 수 있다. 이로 인해 선형 대수 공식과 동일한 형태로 Python 코드를 작성할 수 있게 된다.

 

선형 대수에서 두 벡터의 합은 다음과 같이 구한다.

$$ 
x = \begin{bmatrix}1 \\ 2 \\ 3 \\ \vdots \\ 10000 \end{bmatrix}, \;\;\;\;
y = \begin{bmatrix}10001 \\ 10002 \\ 10003 \\ \vdots \\ 20000 \end{bmatrix},
$$

일 때, 두 벡터의 합

$$ z = x + y $$

은 다음과 같이 구한다.

$$
\begin{bmatrix}1 \\ 2 \\ 3 \\ \vdots \\ 10000 \end{bmatrix} + 
\begin{bmatrix}10001 \\ 10002 \\ 10003 \\ \vdots \\ 20000 \end{bmatrix} 
= \begin{bmatrix}1+10001 \\ 2+10002 \\ 3+10003 \\ \vdots \\ 10000+20000 \end{bmatrix}
= \begin{bmatrix}10002 \\ 10004 \\ 10006 \\ \vdots \\ 30000 \end{bmatrix}
$$

만약 벡터화 연산을 사용하지 않으면 반복문 또는 리스트 컴프리헨션을 사용해 연산해야한다.

%%time # 셀 코드의 실행 시간을 측정하는 IPython Magic 명령
z = np.array([x[i] + y[i] for i in range(10000)])
z

실행 결과

CPU times: total: 0 ns
Wall time: 2 ms
array([10002, 10004, 10006, ..., 29996, 29998, 30000])

 

벡터화 연산을 사용하면 단순 덧셈 연산으로 해결할 수 있다.

%%time
z = x + y
z

실행 결과

CPU times: total: 0 ns
Wall time: 0 ns
array([10002, 10004, 10006, ..., 29996, 29998, 30000])

벡터화 연산을 사용하지 않았을 때와 사용했을 때의 결과는 동일하지만, 실행 속도는 벡터화 연산을 사용한 것이 더 빠르다. 벡터화 연산은 사칙 연산 뿐만 아니라 논리 연산, 지수 함수, 로그 함수도 지원한다.

a == b
a >= b
np.exp(a)
10 ** a
np.log(a + 1)

 

배열의 각 원소를 일일히 비교하는 게 아니라 배열의 모든 원소가 다 같은지 알고 싶다면 numpy.all 함수를 사용하면 된다.

a = np.array([1, 2, 3, 4])
b = np.array([4, 2, 2, 4])
c = np.array([1, 2, 3, 4])

np.all(a == b), np.all(a == c)

실행 결과

(False, True)

 

 

스칼라와 벡터/행렬의 곱셈

스칼라와 벡터/행렬의 곱셈도 선형 대수에서 사용하는 식과 동일하게 코딩한다.

x = np.arange(10)
100 * x

실행 결과

array([  0, 100, 200, 300, 400, 500, 600, 700, 800, 900])

 

 

브로드캐스팅

벡터, 행렬끼리 덧셈, 뺄셈 연산을 하기 위해서는 두 벡터, 행렬의 크기가 같아야 하지만 NumPy에서는 브로드캐스팅(broadcasting)이라는 기능을 이용해 서로 다른 크기를 가진 두 배열을 사칙연산할 수 있다. 브로트캐스팅은 크기가 작은 배열을 자동으로 반복 확장하여 크기가 큰 배열에 맞추는 방법이다.

 

예로 들어 다음과 같은 벡터와 스칼라의 덧셈 연산을 하는 경우가 있다고 하자.

$$ 
x = \begin{bmatrix}0 \\ 1 \\ 2 \\ 3 \\ 4 \end{bmatrix}, \;\;\;\; 
x + 1 = \begin{bmatrix}0 \\ 1 \\ 2 \\ 3 \\ 4 \end{bmatrix} + 1 = ?
$$

브로드캐스틴은 스칼라를 벡터와 같은 크기로 확장시켜 연산하는 것이다.

$$ 
\begin{bmatrix}0 \\ 1 \\ 2 \\ 3 \\ 4 \end{bmatrix} + 1 = 
\begin{bmatrix}0 \\ 1 \\ 2 \\ 3 \\ 4 \end{bmatrix} +  \begin{bmatrix}1 \\ 1 \\ 1 \\ 1 \\ 1 \end{bmatrix} = 
\begin{bmatrix}1 \\ 2 \\ 3 \\ 4 \\ 5 \end{bmatrix}
$$

x = np.arange(5)
x
x + 1

실행 결과

array([0, 1, 2, 3, 4])
array([1, 2, 3, 4, 5])

브로드캐스팅은 차원이 더 높은 경우에도 적용할 수 있다.

 

 

참고 문서

데이터 사이언스 스쿨 - 3.3 배열의 연산