Home python NumPy를 이용한 수치 계산
Post
Cancel

python NumPy를 이용한 수치 계산

numpy logo

지난 포스팅에선 NumPy를 통한 배열(array) 핸들링을 어떻게 효과적으로 할 수 있을까에 대해서 알아보았다.

이번 포스팅 또한 data handling에 근간이 되는 배열 연산에 대해서 알아보고자 한다.

Numpy에 관련해서 3편의 포스팅을 올리는 동안에 혹자는 “어차피 데이터 핸들링 다 pandas로 처리하는데 왜 NumPy를 배워? pandas만 하면 되지” 이런 생각을 할 수 있으리라 생각한다. 하지만 pandas의 기본적인 자료구조가 numpy에서 파생되었고, 결국 데이터를 저장하는 방식이 numpy 방식이다. 그렇기때문에 pandas 활용성을 높여주는 아주 근간이 되는 라이브러리라고 생각한다.

서두가 길었다!

바로 코드를 통해 예제를 살펴보자.

Numpy 연산

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

# 연산을 위해 두개의 ndarray를 만들어주자.

arr1 = np.array([[1, 2, 3],
                 [4, 5, 6]])  # 2x3

arr2 = np.arange(10, 16, 1).reshape(2, 3).copy()  # view 말고 원본을 원하니깐 copy() 메서드를 뒤에 호출함

# 두개를 더하면 어떨까?
# 1 2 3        10 11 12     =>     11 13 15
# 4 5 6        13 14 15     =>     17 19 21   

# 이런 모습을 우리는 기대한다. 
# 자 단순하게 더하기를 해주면된다. 
# shape이 일치한다면***  요소끼리 (element wise) 더해진다. 
# shape이 일치하지 않는다면 에러를 리턴한다.

print(arr1 + arr2)
# 출력물:
# [[11 13 15]
#  [17 19 21]]

그렇다면 위의 ndarray 더하기와 파이썬 list의 더하기는 어떻게 다를까?

1
2
3
4
5
6
a = [1, 2, 3]   # 파이썬의 리스트
b = [4, 5, 6]   

print(a + b)
# 출력물:
# [1, 2, 3, 4, 5, 6]   이렇게 리스트가 이어지게 된다. (concatenate)

파이썬 리스트의 연산은 연결성(concatenateness)가 가장 큰 특징이다. 반면, ndarray는 우리가 수학시간에 배웠던 vector calcuation을 따르는 경향이 있다.

음 여기까진 단순히 저거 구분만 하면 되겠네?

shape 만 맞춰주면 ndarray끼리의 연산은 문제 없겠네? 라고 생각할 수 있다.

문제는 행렬 곱 (matrix multiplication)에서 나온다.

한번 살펴보자.

행렬 곱 (Matrix Multiplication)

선형대수학을 배웠거나 아직 고교과정에서 배웠던 matrix에 대한 지식이 남아있다면 별로 문제될 거 없이 쉽게 해결할 수 있지만, 그렇지 않다면 어느정도 행렬 곱에 대한 공부를 하고 오길 바란다.

특히나 머신러닝같은 경우에는 2차원이상의 차원을 가장 많이 접할텐데 2차원에서 행렬에 관련된 연산은 필수적이기 때문이다.

거두절미하고 예제를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
a = np.array([[1, 2],
              [3, 4],
              [5, 6]])    # 3x2

b = np.array([[1, 2, 3],
              [4, 5, 6]])   # 2x3 

# 이렇게 3x2 매트릭스 a가 있고, 2x3 매트릭스 b가 있다.
# 행렬곱의 가장 기본 원칙은 (m x n) x (n x k) = (m x k) 인데, 무슨말이냐하면 
# 앞선 행렬의 열의 개수가 곱하고자 하는 행렬의 행의 개수와 같아야한다.
# 따라서 우리의 경우에는
# (3x2) x (2x3) => (3x3)  의 행렬로 결과가 나오게 된다.

# 행렬곱 연산은 또 일반 곱하기 기호를 사용하여 하는것이 아니고
# numpy만의 함수가 있다.
# numpy의 matmul이라는 함수가 있다. (matrix multiplication의 약자임)
# 결괏값을 살펴보자.

print(np.matmul(a, b))  # 3x3 
# 출력물은 
# [[ 9 12 15]
#  [19 26 33]
#  [29 40 51]] 이다.

# 와우.. 저 요소들은 어디서 나왔나요?
# 음 이건 수학적 수식을 통해 쉽게 설명할 수 있는데 
# 지금 당장은 설명을 스킵하겠다.

자 그럼 이번에는 행렬 곱을 boolean indexing과 같이 사용해보자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
arr1 = np.array([[1, 2, 3], [20, 21, 22]])  # 2x3
# arr1:
# [[1 2 3]
#  [20 21 22]]

arr2 = np.arange(10, 16, 1).reshape(2,3).copy()  # 2x3 
# view가 아닌 원본을 만들고자 뒤에 .copy()를 추가적으로 호출했다.
# arr2:
# [[10 11 12]
#  [13 14 15]]

print(arr1 > arr2)   # mask로 나옴
# 출력물:
# [[False False False]
#  [True True True]]

# 이제 boolean indexing 을 사용해보자

print(arr1[ arr1 > arr2 ])  
# 도움이 될진 모르겠지만, 필자는 해당 명령어를 사용할 때
# "파이썬아, arr1을 출력하는데 arr1 요소중 에서 arr2보다 큰 것만 출력해!"
# 이렇게 생각하면 쉽게 이해가 되었다.
# 출력물:
# [20 21 22]      

“근데 왜 이렇게까지 해요?” 라고 생각할 수 있다.

거듭 말하지만, data handling의 가장 기초이며 머신러닝 모델을 많이 알고 뭐 완벽한 모델이 있다한들 데이터 정제를 제대로 하지 못하면 결국엔 빛좋은 개살구에 지나지 않는다. 왜냐고? 결괏값이 어차피 틀렸을테니깐.

Broadcasting

이번 포스팅에서 다뤄볼 마지막 주제는 broadcasting이다.

이친구가 하는 역할은 shape 을 “억지로” 일치시켜 행렬 연산을 하게끔 도와준다. 음.. 선형대수학을 제대로 배운 독자라면 “이게 뭔 🐶 소리야? 그렇게 얻은 값이 무슨 의미가 있는데? 수학적 논리를 거슬러서 얻은 값 아닌가?” 라고 생각할 수도 있다. 하지만 당장은 순수 수학의 입장에서 받아들이지말고 “아 신기한 기능도 있구만?ㅎㅎ” 이렇게 생각하며 넘어가도록 하자.

바로 예제 코드를 보도록하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 두개의 array가 주어졌다.
arr1 = np.array([[1, 2, 3],
                 [4, 5, 6]])  # 2x3

arr2 = np.array([1, 2, 3]) # 1차원    1x3

# 1 2 3      1 2 3
# 4 5 6
# 이렇게 shape이 각기 다른 친구들을 더한다면 어떻게 될까?
# 에러가 날까? 한번 확인해보자.

print(arr1 + arr2)
# 출력물:  
# [[2 4 6]
#  [5 7 9]]     

# 아마 짐작했겠지만,  [1 2 3] 이 2행으로 추가되어  
# [[1 2 3]
#  [1 2 3]]   이렇게 2x3 형태로 만들어져서 연산이 되었음을 알 수 있다.
# 이걸 broadcasting이라고 일컫는다.

그렇지만 broadcasting을 모든 배열에 적용시킬 수 있는 것은 아니다. 가능한 케이스가 있고 또 불가능한 케이스가 있다.

(2x3) 행렬과 (1x2) 행렬을 연산할 수 있는가? 되게 애매하다. 행과 열 모두 다르기 때문이다. 실제로 이건 불가능하기도 하다.

Broadcasting은 한쪽의 행 또는 열이 연산하고자 하는 행렬의 행이나 열의 수와 일치해야함을 기억하자.

오늘 numpy 연산에 관한 포스팅은 여기서 마치도록 하겠다. 👋

This post is licensed under CC BY 4.0 by the author.

python NumPy 인덱싱과 슬라이싱

파이썬과 객체지향, 그리고 절차지향의 이해 (3)

Comments powered by Disqus.