머신러닝

넘파이 (NumPy) : 행렬과 선형대수를 다루는 패키지

jeongpil 2021. 3. 8. 22:48

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

 

 

머신러닝 개발을 위해서는 넘파이와 판다스에 대해 이해하는 것이 매우 중요합니다.

 

사이킷런의 머신러닝 알고리즘에 입력하기 위한 데이터 처리 대부분이 넘파이와 판다스의 몫일 뿐더러,

 

넘파이와 판다스에 대한 이해가 충분해야 다른 데이터 분석가의 소스 코드를 이해하고 자신의 것으로 흡수하며 성장해나갈 수 있습니다.

 

행렬과 선형대수를 다루는 패키지인 넘파이에 대해 먼저 알아보겠습니다. 

 

 

1. 넘파이란?

2. 넘파이를 활용한 배열 생성 및 크기 조절

  2-1. 배열 생성

  2-2. 배열의 크기 조절

3. 넘파이를 활용한 인덱싱

  3-1. 단일값 추출

  3-2. 연속된 값 추출

  3-3. 조건에 맞는 값 추출 

4. 넘파이의 행렬 정렬

  4-1. np.sort() vs sort()

  4-2. 정렬된 행렬의 인덱스 반환 np.argsort()

 

 

1. 넘파이란?

 

Numerical Python의 약자인 NumPy는 파이썬에서 선형대수 기반의 프로그램을 쉽게 만들 수 있도록 지원하는 대표적인 패키지입니다.

 

머신러닝의 주요 알고리즘은 모두 수학(선형대수, 통계 등)에 기반하기 때문에 많은 수학적 계산이 요구됩니다.

 

이러한 수학적인 계산들을 넘파이 패키지의 함수들이 해결해주는 것입니다.

 

넘파이의 기반 데이터 타입은 ndarray입니다.

 

서로 다른 데이터 타입을 가질 수 있는 리스트와는 달리, ndarray내의 데이터 타입은 모두 같아야 하고

 

만약 타입이 다른 데이터가 섞여있을 때에는 데이터 크기가 더 큰 데이터 타입으로 형 변환을 적용합니다.

 

list1=[1,2,'ML']
array1=np.array(list1)
print(array1,array1.dtype)

['1' '2' 'ML'] <U11

 

list2=[1,2.0,'3']
array2=np.array(list2)
print(array2,array2.dtype)

['1' '2.0' '3'] <U32

 

list3=[1,2,3.0]
array3=np.array(list3)
print(array3,array3.dtype)

[1. 2. 3.] float64

 

 

 

2. 넘파이를 활용한 배열 생성 및 크기 조절

2-1. 배열의 생성

 

넘파이에는 여러 배열 생성 방식이 있지만 본 포스팅에서는 arange(), zeros(), ones(), empty(), full()을 알아보겠습니다.

 

 

① np.arange()

 

넘파이의 arange()는 0부터 (함수 인자 값-1)까지의 값을 순차적으로 ndarray의 데이터값으로 변환해 줍니다.

 

arange_array=np.arange(10) #0부터 (10-1) 까지
print(arange_array)

arange_array2=np.arange(start=1,stop=11) #start부터 stop-1 까지
print(arange_array2)

[0 1 2 3 4 5 6 7 8 9]

[ 1 2 3 4 5 6 7 8 9 10]

 

 

② np.zeros(), np.ones(), np.empty(), np.full()

 

넘파이의 zeros()와 ones()는 설정한 배열의 크기에 0과 1을 채워 넣는 함수이고 empty()는 메모리를 할당 받기만 하고 초기화 하지않고 반환합니다.

 

초기화를 생략하기 때문에 성능이 조금 개선되지만 실무에서는 거의 사용되지 않습니다.

 

full()은 크기 설정 뒤의 value값으로 채워진 상태로 반환합니다.

 

 

zeros_array=np.zeros((2,2))
ones_array=np.ones((2,3))
empty_array=np.empty((1,2))
full_array=np.full((2,4),10)


print('zeors\n',zeros_array)
print('ones\n',ones_array)
print('empty\n',empty_array)
print('full\n',full_array)

 

 

2-2. 배열의 크기 조절

 

배열의 차원과 크기는 reshape()를 이용하여 변경할 수 있습니다.

 

기존의 데이터프레임에 새로운 배열을 합치는 경우 reshape를 통해 차원과 크기를 조절해줘야 합니다.

 

arange_array.reshape(2,5)

 

1행 10열의 arange_array 배열을 2행 5열의 배열로 변경하였습니다.

 

10=2x5인 것을 알기 때문에 2행 5열로 변경할 수 있었지만 만약 나누기가 직관적으로 되지 않는다면 어떻게 해야할까요?

 

이는 인자로 -1을 적용하면 쉽게 해결할 수 있습니다.

 

array1=np.arange(1096)
array2=array1.reshape(4,-1) #4행 (1096/4)열로 변환

print('array2의 배열의 크기는 :',array2.shape)

 

물론 -1을 활용하더라도 나누기가 나누어지지 않는다면 형태를 변환할 수 없습니다.

 

 

3. 넘파이를 활용한 인덱싱

3-1. 단일값 추출

 

# 1차원
array = np.arange(1,10)
print(array)
print('array의 index=5인 값',array[5]) # 인덱스 값(0부터 시작)
print('array의 제일 마지막 값 :',array[-1]) # 음수 : 제일 뒤에서부터 (=arr[8])

# 2차원 이상
array2 = np.arange(1,10).reshape(3,3)
print(array2)
print('array2의 1행 2열 값: ',array2[1,2])

 

3-2. 연속된 값 추출

 

# 1차원
array = np.arange(1,10)
print('1차원 배열')
print(array,'\n')
print('인덱스 0부터 (3-1) 까지')
print(arr[0:3],'\n')

# 2차원 이상
array2 = np.arange(1,10).reshape(3,3)
print('2차원 배열')
print(array2,'\n')
print('1행부터 2행까지, 모든열 ')
print(array2[1:3,:],'\n')
print('0행과 1행, 2열')
print(array2[[0,1],2],'\n')
print('0행과 2행, 모든열')
print(array2[[0,2], :],'\n')

 

3-3. 조건에 맞는 값 추출

 

[ ] 내에 조건을 넣어 조건에 맞는 데이터만 추출할 수 있습니다.

 

array = np.arange(1,10)
print(array)
print('5보다 큰 수 추출',array[array>5])

 

 

4. 넘파이의 행렬 정렬

4-1. np.sort() vs sort()

 

넘파이에서 행렬을 정렬하는 대표적인 방법으로 np.sort() 와 sort() 가 있습니다.

 

둘의 차이점은 np.sort()의 경우 원본 행렬은 그대로 유지되고 정렬된 행렬을 반환하고

 

sort()는 원본 행렬 자체를 정렬한 형태로 변환하고 반환 값은 None이라는 점입니다.

 

즉, np,sort()는 원본 행렬이 유지, sort()는 원본 행렬이 변환됩니다.

 

# np.sort()
array = np.array([2,1,5,7])
array_sorted = np.sort(array)
array_sorted_desc=np.sort(array)[::-1]

print('원본 행렬\n',array) 
print('반환 행렬\n',array_sorted) 
print('반환 행렬 내림차순\n',array_sorted_desc)

#sort()
array2 = np.array([2,1,5,7])
array2_sorted = array2.sort()

print('원본 행렬\n',array2)
print('반환 행렬\n',array2_sorted) 

#2차원 이상
array2d=np.array([[10,2],[5,4]])
array2d_sorted_axis0=np.sort(array2d,axis=0)
array2d_sorted_axis1=np.sort(array2d,axis=1)
print('2차원 행렬\n',array2d)
print('행 방향으로 정렬\n',array2d_sorted_axis0)
print('열 방향으로 정렬\n',array2d_sorted_axis1)

 

※ 2차원에서 axis0은 행, axis1은 열을 뜻합니다. 3차원에서는 axis0, axis1, axis2로 3개의 축을 가집니다.

 

 

4-2. 정렬된 행렬의 인덱스 반환 np.argsort()

 

원본 행렬이 정렬되었을 때 기존 원본 행렬의 원소에 대한 인덱스를 필요로 할 때 np.argsort()를 이용합니다.

 

np.argsort()를 사용하면 두 개의배열에 대해 하나의 배열을 기준으로 다른 배열을 정렬할 수 있습니다.

 

#기온이 낮은 순으로 날짜를 나열하라

date_array=np.array(['5월14일','3월23일','12월25일','7월20일'])
temp_array=np.array([15,7,-2,30])
temp_sorted_asc=np.argsort(temp_array)
date_sorted_by_temp=date_array[temp_sorted_asc]
print('기온이 낮은 순으로 날짜 배열',date_sorted_by_temp)

 

 

 

이렇게 행렬과 선형대수를 다루는 중요한 패키지인 넘파이(NumPy)에 대해 알아봤습니다.