본문 바로가기

Study doc./Python

[Python] 알고 써라!! 넘파이(Numpy)

* 해당 포스팅은 파이썬 머신러닝 완벽가이드(권철민, 2019) 교재를 참고하여 공부하며 작성한 글 입니다.

 

 

안녕하세요!! 

오늘은 파이썬 머신러닝에서 정말 많이 사용되는 패키지 중 하나인 "넘파이(Numpy) 패키지" 에 대해서 정리해보겠습니다.

 

보통 머신러닝 책의 도입부에서 많이 설명되는 개념이기 때문에 머신러닝 입문자 분들이라면 이미 많이 보셨을테지만, 정확한 개념을 몰라도 코드를 짜는데 아무 문제가 없기 때문에 대충 훑어보고 넘어가는 경우가 많은것 같습니다.

 

하지만 이쪽 분야를 공부하면 공부할수록 기본기의 중요성에 대해 깨닫게 되고, 이런 기본기가 없으면 난잡하고 불필요한 코드를 짜는데에 많은 시간을 소비하던 저의 경험을 바탕으로 기본기 공부를 시작하게 되었습니다.

 

처음부터 천천히 읽어보시면서 왜 넘파이를 쓰는지, 언제 주로 사용되는지 등을 이해해봅시다!!

 

 

 


 

 

순서

  1. Numpy 패키지를 이용해 만든 배열, 그리고 크기 조절
    1. Numpy 패키지의 역할과 개념
    2. 배열 생성, 크기 조절
  2. 배열에서의 특정값 추출
    1. 단일값
    2. 연속적인 값
    3. 조건에 맞는 값
  3. 배열에서의 순서 정렬
  4. 정렬된 인덱스를 활용한 배열

 


 

1. Numpy 패키지를 이용해 만든 배열, 그리고 크기 조절

1-1. Numpy 패키지의 역할과 개념

Numpy 패키지는 '행렬, 선형대수, 통계 등을 파이썬에서 쉽게 다룰 수 있게 도와주는 패키지'라고 이해하면 됩니다.

잘 모르시겠다구요?

그럼 Numpy 가 생기게 된 계기부터 생각해볼게요!!

 

혹시 수학적으로 머신러닝의 작동 원리에 대해서 공부해본 적이 있으신가요?

해보신 분들은 아시겠지만 사실 머신러닝은 100% 수학입니다.

단지 그 수학적 계산들을 컴퓨터가 대신 해주는 것 뿐이죠.

 

그렇다면 맨 처음 머신러닝이 등장했을때 수학적 계산식들을 어떻게 컴퓨터로 옮겼을까요?!!

행렬을 예로 들어 생각해봅시다.

지금이야 2*2 행렬식을 만들어보라면 뚝딱 만들수 있지만, 패키지를 사용하지 않고 만드는 방법을 생각해보면 쉽지 않습니다.

그 뿐만이 아니라 행렬곱까지 해야하니 머리가 터질 것 같습니다.

 

그렇게 1년이 지나고, 어떤 똑똑한 사람들이 말했습니다!

" 내가 행렬을 컴퓨터로 쉽게 표현하고, 행렬곱도 쉽게 하는 함수를 만들었어!! 내가 만든 함수 써볼래? "

" 나는 컴퓨터로 미분하는 방법을 구현해봤어!! 내 함수도 공유해줄게!! "

 

이렇게 함수들이 쌓이고 쌓이자 한 사람이 아이디어를 냅니다.

" 우리 이 함수들을 다 모아서 하나의 덩어리로 만들자!! "

" 그리고 나중에 어떤 함수를 쓰고 싶을때 그 덩어리를 불러오자!! " .... > import 덩어리

 

그렇게 패키지의 개념이 탄생하고, 지금의 우리는 행렬 하나도 한 줄의 코드로 쉽게 만들 수 있었던 것입니다.

 * 이해를 돕기 위한 예시일뿐, 사실과 무관합니다.

 

다시 돌아와서!!

이제 Numpy 패키지가 만들어진 이유에 대해 알게 되었습니다.

머신러닝 알고리즘에 수없이 사용되는 통계적 기법들을 손쉽게 사용할 수 있기 위해서겠죠~

 

그럼 왜 패키지 이름을 Numpy로 지었을까요?

사실 Numpy는 Numerical python 의 줄임말 입니다. 

숫자(수치)의 파이썬?!? 직관적으로 느낌이 오죠?? ㅎㅎ 

 

 

1-2. 배열 생성, 크기 조절

Numpy 패키지에는 배열을 생성하는 여러가지 함수가 있지만, 저는 arange(), zeros(), ones() 함수를 다뤄보겠습니다.

arange() 함수는 array 와 range를 합친 말로, 배열의 범위를 설정하여 출력할 수 있습니다.

보통 연속적인 숫자를 이용할 때, 그래프의 x축/ y축의 눈금을 표현할때 많이 사용합니다.

 

zeros()는 사용자가 설정한 숫자만큼 0을 생성하고, ones()는 1을 생성합니다.

이 두 함수는 분류 문제의 y값을 생성할때 많이 사용합니다.(ex. 이탈했다=1, 이탈하지 않았다=0)

 

배열의 크기는 reshape() 함수로 조절 가능하고, 

기존의 데이터프레임에 배열을 합치는 등의 작업을 할때 reshape() 함수를 통해 크기를 조절해주어야 합니다.

 

# numpy 패키지 불러오기, 사용할 때에는 np로 부를거야
import numpy as np

# 배열 생성
display(np.arange(10))
display(np.zeros((3,2))) # 3행 2열
display(np.ones((3,2), dtype='int32')) # dtype 디폴트값은 float

# 크기 조절
display(np.arange(10).reshape(2,5)) # reshape(-1,5) 와 동일

 

 

 

 

2. 배열에서의 특정값 추출

2-1. 단일값

# 1차원
arr = np.arange(1,10)
display(arr)
display(arr[3]) # 인덱스 값(0부터 시작)
display(arr[-1]) # 음수 : 제일 뒤에서부터 (=arr[8])

# 2차원 이상
arr = np.arange(1,10).reshape(3,3)
display(arr)
display(arr[0,2]) # 0행 2열 값

 

2-2. 연속적인 값

# 결과값도 배열 형태

# 1차원
arr = np.arange(1,10)
display(arr)
display(arr[0:3]) # 인덱스 0부터 3 전까지

# 2차원 이상
arr = np.arange(1,10).reshape(3,3)
display(arr)
display(arr[1:3,:]) # 1행부터 3행전까지, 모든열
display(arr[0]) # 첫번째 행 출력
display(arr[[0,1],2]) # 0,1행, 2열

 

2-3. 조건에 맞는 값

arr = np.arange(1,10)
display(arr)
display(arr[arr>5])

 

 

3. 배열에서의 순서 정렬

np.sort() vs .sort()

# np.sort()
arr = np.array([3,1,9,5])
arr2 = np.sort(arr)
display(arr) # 원본 : 그대로
display(arr2) # 적용됨 : 바뀜

# .sort()
arr = np.array([3,1,9,5])
arr3 = arr.sort()
display(arr) # 원본 : 바뀜
display(arr3) # 적용됨 : None, 사용X

display(arr[::-1]) # 내림차순 [::-1]

* 결론 : .sort() 는 원본을 바꿔버리고, np.sort()는 원본은 유지함

 

 

 

 

4. 정렬된 인덱스를 활용한 배열

넘파이(Numpy)는 1차원 배열의 형태만 가질 수 있고, 2차원의 데이터 프레임 형태를 가질수 없습니다. 따라서 2차원 데이터 형태를 사용하기 위해서는 1차원 배열 두 개를 만들어야하고, 이 두 개를 맵핑하는 상황에 유용하게 사용됩니다.

np.argsort()

# 가격이 비싼 순서대로 날짜를 나열하면?
date_arr = np.array([20120205, 20170318, 20000101])
price_arr = np.array([100, 500, 300])

display(date_arr[np.argsort(price_arr)[::-1]])