본문 바로가기

AI Study/Machine Learning

머신러닝을 위한 Numpy 기초

1. 넘파이 기본 개념

 

>> 수치해석용 Python 라이브러리

 

  • Numerical Python의 약자
  • C로 구현 (파이썬용 C라이브러리)
  • loop 사용하지 않는 대량 데이터 배열 연산 가능(Vectorization)
  • 빠른 수치 계산을 위한 Structured Array 제공

>> 학습을 위해 참고할 링크

 


>> Numpy의 필요성

 

  • C/C++과 같은 저수준 언어 기반의 호환 API 제공
  • 수행 성능이 매우 중요한 부분은 C/C++기반의 코드로 작성 -> 이를 numpy에서 호출하면 통합가능
    • 구글의 딥러닝 프레임워크인 tensorflow가 위의 방식 사용, 배열 연산 수행 속도를 개선, 넘파이와 호환될 수 있게 작성되었음
  • 데이터 분석은 pandas가 더 용이하나, 많은 머신러닝 알고리즘이 넘파이를 기반으로 작성됨
  • 또한 ML 알고리즘의 입/출력 데이터가 넘파이 배열 타입으로 사용되므로 이해할 필요가 있음

>> Python List vs NumPy Array

 

  • Python List
    • 여러가지 타입의 원소
    • 메모리 용량이 크고 속도가 느림
    • nesting 가능
    • 전체 연산 불가

 

  • NumPy Array
    • 동일 타입의 원소
    • 메모리 최적화, 계산 속도 향상
    • 크기(dimension)이 명확하게 정의

 


 

2. 넘파이 기초 문법

 

In [3]:
# Numpy 라이브러리 불러오기
import numpy as np

In [4]:
array1 = np.array([1,2,3])
print('array1 type:',type(array1))
print('array1 array 형태:',array1.shape)

array2 = np.array([[1,2,3],
                  [2,3,4]])
print('array2 type:',type(array2))
print('array2 array 형태:',array2.shape)

array3 = np.array([[1,2,3]])
print('array3 type:',type(array3))
print('array3 array 형태:',array3.shape)
 
Out [4]:
array1 type: <class 'numpy.ndarray'>
array1 array 형태: (3,)
array2 type: <class 'numpy.ndarray'>
array2 array 형태: (2, 3)
array3 type: <class 'numpy.ndarray'>
array3 array 형태: (1, 3)

In [5]:
print('array1: {:0}차원, array2: {:1}차원, array3: {:2}차원'.format(array1.ndim,array2.ndim,array3.ndim))
 

Out [5]:

array1: 1차원, array2: 2차원, array3:  2차원

In [6]:
list1 = [1,2,3]
print(type(list1))
array1 = np.array(list1)
print(type(array1))
print(array1, array1.dtype)

Out [6]:

<class 'list'>
<class 'numpy.ndarray'>
[1 2 3] int32

In [7]:
list2 = [1, 2, 'test']
array2 = np.array(list2)
print(array2, array2.dtype)

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

Out [7]:

['1' '2' 'test'] <U11
[1. 2. 3.] float64

In [8]:
array_int = np.array([1, 2, 3])
array_float = array_int.astype('float64')
print(array_float, array_float.dtype)

array_int1= array_float.astype('int32')
print(array_int1, array_int1.dtype)

array_float1 = np.array([1.1, 2.1, 3.1])
array_int2= array_float1.astype('int32')
print(array_int2, array_int2.dtype)
 

Out [8]:

[1. 2. 3.] float64
[1 2 3] int32
[1 2 3] int32
 

2.1 ndarray를 편리하게 생성하기 - arange, zeros, ones

In [9]:
sequence_array = np.arange(10)
print(sequence_array)
print(sequence_array.dtype, sequence_array.shape)
 

Out [10]:

[0 1 2 3 4 5 6 7 8 9]
int32 (10,)

In [10]:
zero_array = np.zeros((3,2),dtype='int32')
print(zero_array)
print(zero_array.dtype, zero_array.shape)

one_array = np.ones((3,2))
print(one_array)
print(one_array.dtype, one_array.shape)
 

Out [10]:

[[0 0]
 [0 0]
 [0 0]]
int32 (3, 2)
[[1. 1.]
 [1. 1.]
 [1. 1.]]
float64 (3, 2)
 

2.2 reshape

In [11]:
array1 = np.arange(10)
print('array1:\n', array1)

array2 = array1.reshape(2,5)
print('array2:\n',array2)

array3 = array1.reshape(5,2)
print('array3:\n',array3)
 

Out [11]:

array1:
 [0 1 2 3 4 5 6 7 8 9]
array2:
 [[0 1 2 3 4]
 [5 6 7 8 9]]
array3:
 [[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]

In [12]:
array1.reshape(4,3)
 

Out [12]:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-12-a40469ec5825> in <module>
----> 1 array1.reshape(4,3)

ValueError: cannot reshape array of size 10 into shape (4,3)
 

 
In [13]:
array1 = np.arange(10)
array4 = array1.reshape(-1,4)
 

Out [13]:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-07da9760475e> in <module>
      1 array1 = np.arange(10)
----> 2 array4 = array1.reshape(-1,4)

ValueError: cannot reshape array of size 10 into shape (4)

In [14]:
array1 = np.arange(8)
array3d = array1.reshape((2,2,2))
print('array3d:\n',array3d.tolist())

# 3차원 ndarray를 2차원 ndarray로 변환
array5 = array3d.reshape(-1,1)
print('array5:\n',array5.tolist())
print('array5 shape:',array5.shape)

# 1차원 ndarray를 2차원 ndarray로 변환
array6 = array1.reshape(-1,1)
print('array6:\n',array6.tolist())
print('array6 shape:',array6.shape)
 

Out [14]:

array3d:
 [[[0, 1], [2, 3]], [[4, 5], [6, 7]]]
array5:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array5 shape: (8, 1)
array6:
 [[0], [1], [2], [3], [4], [5], [6], [7]]
array6 shape: (8, 1)
 

2.3 indexing

2.3.1 단일값 추출

In [15]:
# 1에서 부터 9 까지의 1차원 ndarray 생성 
array1 = np.arange(start=1, stop=10)
print('array1:',array1)
# index는 0 부터 시작하므로 array1[2]는 3번째 index 위치의 데이터 값을 의미
value = array1[2]
print('value:',value)
print(type(value))
 

Out [16]:

array1: [1 2 3 4 5 6 7 8 9]
value: 3
<class 'numpy.int32'>

In [16]:
print('맨 뒤의 값:',array1[-1], ', 맨 뒤에서 두번째 값:',array1[-2])
 

Out [16]:

맨 뒤의 값: 9 , 맨 뒤에서 두번째 값: 8

In [17]:
array1[0] = 9
array1[8] = 0
print('array1:',array1)
 

Out [17]:

array1: [9 2 3 4 5 6 7 8 0]

In [18]:
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)
print(array2d)

print('(row=0,col=0) index 가리키는 값:', array2d[0,0] )
print('(row=0,col=1) index 가리키는 값:', array2d[0,1] )
print('(row=1,col=0) index 가리키는 값:', array2d[1,0] )
print('(row=2,col=2) index 가리키는 값:', array2d[2,2] )
 

Out [18]:

[[1 2 3]
 [4 5 6]
 [7 8 9]]
(row=0,col=0) index 가리키는 값: 1
(row=0,col=1) index 가리키는 값: 2
(row=1,col=0) index 가리키는 값: 4
(row=2,col=2) index 가리키는 값: 9
 

2.3.2 Slicing

In [19]:
array1 = np.arange(start=1, stop=10)
array3 = array1[0:3]
print(array3)
print(type(array3))
 

Out [19]:

[1 2 3]
<class 'numpy.ndarray'>

In [20]:
array1 = np.arange(start=1, stop=10)
array4 = array1[:3]
print(array4)

array5 = array1[3:]
print(array5)

array6 = array1[:]
print(array6)
 

Out [20]:

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

In [21]:
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)
print('array2d:\n',array2d)

print('array2d[0:2, 0:2] \n', array2d[0:2, 0:2])
print('array2d[1:3, 0:3] \n', array2d[1:3, 0:3])
print('array2d[1:3, :] \n', array2d[1:3, :])
print('array2d[:, :] \n', array2d[:, :])
print('array2d[:2, 1:] \n', array2d[:2, 1:])
print('array2d[:2, 0] \n', array2d[:2, 0])
 

Out [21]:

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

In [22]:
print(array2d[0])
print(array2d[1])
print('array2d[0] shape:', array2d[0].shape, 'array2d[1] shape:', array2d[1].shape )
 

Out [22]:

[1 2 3]
[4 5 6]
array2d[0] shape: (3,) array2d[1] shape: (3,)
 

2.3.3 fancy indexing

In [23]:
array1d = np.arange(start=1, stop=10)
array2d = array1d.reshape(3,3)

array3 = array2d[[0,1], 2]
print('array2d[[0,1], 2] => ',array3.tolist())

array4 = array2d[[0,1], 0:2]
print('array2d[[0,1], 0:2] => ',array4.tolist())

array5 = array2d[[0,1]]
print('array2d[[0,1]] => ',array5.tolist())
 

Out [24]:

array2d[[0,1], 2] =>  [3, 6]
array2d[[0,1], 0:2] =>  [[1, 2], [4, 5]]
array2d[[0,1]] =>  [[1, 2, 3], [4, 5, 6]]
 

2.3.4 Boolean indexing

In [24]:
array1d = np.arange(start=1, stop=10)
# [ ] 안에 array1d > 5 Boolean indexing을 적용 
array3 = array1d[array1d > 5]
print('array1d > 5 불린 인덱싱 결과 값 :', array3)
 

Out [24]:

array1d > 5 불린 인덱싱 결과 값 : [6 7 8 9]

In [25]:
array1d > 5
 
 
Out[25]:
array([False, False, False, False, False,  True,  True,  True,  True])

In [26]:
boolean_indexes = np.array([False, False, False, False, False,  True,  True,  True,  True])
array3 = array1d[boolean_indexes]
print('불린 인덱스로 필터링 결과 :', array3)
 

Out [26]:

불린 인덱스로 필터링 결과 : [6 7 8 9]

In [27]:
indexes = np.array([5,6,7,8])
array4 = array1d[ indexes ]
print('일반 인덱스로 필터링 결과 :',array4)
 

Out [27]:

일반 인덱스로 필터링 결과 : [6 7 8 9]
 

2.4 행렬의 정렬 – sort( )와 argsort( )

2.4.1 행렬 정렬

 
In [28]:
org_array = np.array([ 3, 1, 9, 5]) 
print('원본 행렬:', org_array)
# np.sort( )로 정렬 
sort_array1 = np.sort(org_array)         
print ('np.sort( ) 호출 후 반환된 정렬 행렬:', sort_array1) 
print('np.sort( ) 호출 후 원본 행렬:', org_array)
# ndarray.sort( )로 정렬
sort_array2 = org_array.sort()
print('org_array.sort( ) 호출 후 반환된 행렬:', sort_array2)
print('org_array.sort( ) 호출 후 원본 행렬:', org_array)
 

Out [28]:

원본 행렬: [3 1 9 5]
np.sort( ) 호출 후 반환된 정렬 행렬: [1 3 5 9]
np.sort( ) 호출 후 원본 행렬: [3 1 9 5]
org_array.sort( ) 호출 후 반환된 행렬: None
org_array.sort( ) 호출 후 원본 행렬: [1 3 5 9]

In [29]:
sort_array1_desc = np.sort(org_array)[::-1]
print ('내림차순으로 정렬:', sort_array1_desc) 
 

Out [29]:

내림차순으로 정렬: [9 5 3 1]

 
In [30]:
array2d = np.array([[8, 12], 
                   [7, 1 ]])

sort_array2d_axis0 = np.sort(array2d, axis=0)
print('로우 방향으로 정렬:\n', sort_array2d_axis0)

sort_array2d_axis1 = np.sort(array2d, axis=1)
print('컬럼 방향으로 정렬:\n', sort_array2d_axis1)
 

Out [30]:

로우 방향으로 정렬:
 [[ 7  1]
 [ 8 12]]
컬럼 방향으로 정렬:
 [[ 8 12]
 [ 1  7]]
 

2.4.2 정렬 행렬의 인덱스 반환

In [31]:
org_array = np.array([ 3, 1, 9, 5]) 
sort_indices = np.argsort(org_array)
print(type(sort_indices))
print('행렬 정렬 시 원본 행렬의 인덱스:', sort_indices)
 

Out [31]:

<class 'numpy.ndarray'>
행렬 정렬 시 원본 행렬의 인덱스: [1 0 3 2]

In [32]:
org_array = np.array([ 3, 1, 9, 5]) 
sort_indices_desc = np.argsort(org_array)[::-1]
print('행렬 내림차순 정렬 시 원본 행렬의 인덱스:', sort_indices_desc)
 

Out [32]:

행렬 내림차순 정렬 시 원본 행렬의 인덱스: [2 3 0 1]

In [33]:
import numpy as np

name_array = np.array(['John', 'Mike', 'Sarah', 'Kate', 'Samuel'])
score_array= np.array([78, 95, 84, 98, 88])

sort_indices_asc = np.argsort(score_array)
print('성적 오름차순 정렬 시 score_array의 인덱스:', sort_indices_asc)
print('성적 오름차순으로 name_array의 이름 출력:', name_array[sort_indices_asc])
 

Out [33]:

성적 오름차순 정렬 시 score_array의 인덱스: [0 2 4 1 3]
성적 오름차순으로 name_array의 이름 출력: ['John' 'Sarah' 'Samuel' 'Mike' 'Kate']
 

2.5 선형대수 연산 – 행렬 내적과 전치 행렬 구하기

2.5.1 행렬 내적

 
In [34]:
A = np.array([[1, 2, 3],
              [4, 5, 6]])
B = np.array([[7, 8],
              [9, 10],
              [11, 12]])

dot_product = np.dot(A, B)
print('행렬 내적 결과:\n', dot_product)
 

Out [34]:

행렬 내적 결과:
 [[ 58  64]
 [139 154]]
 

2.5.2 전치 행렬

In [35]:
A = np.array([[1, 2],
              [3, 4]])
transpose_mat = np.transpose(A)
print('A의 전치 행렬:\n', transpose_mat)
 

Out [36]:

A의 전치 행렬:
 [[1 3]
 [2 4]]

 

* 출처 *

파이썬 머신러닝 완벽가이드