본문 바로가기
  • Survival Plan
개발 이야기/Python

[파이썬-Python] Numpy는 왜 필요할까?

by IT/머신러닝 엔지니어의 독서/경제/육아 공부 리치윈드 - windFlex 2018. 3. 3.

Numpy

 

많이 들어보셨고, 많이들 사용하고 계실 겁니다. 

 

그런데, 이런 생각 드신적 있나요?

동일한 array인데, 어떤 때는 요렇게, 어떤 때는 np.array, 심지어는 pandas는 도 좀 다르고..

 

혼동되지 않나요?

 

그래서 오늘은 Python과 Numpy에 대해서 이야기를 좀 해보려 합니다. 

 

좀 더 구체적을, 아래와 같은 결과를 예측해 보세요.

파이썬 터미널에서 아래와 같은 계산을 했을 경우를 가정해 봅시다. 

>>> [1, 2] * 2

1) 어느 누군가는 [2, 4]를  기대 했을 겁니다. 

2) 또는, Python을 많이 다루어 보신 분들은, [1, 2, 1, 2] 를 기대하기도 합니다. 

3)  [ [1, 2], [1, 2] ] 를 기대하신 분도 계시려나요?

 

Python에 위와 같은 형태가 모두 가능한데, 왜 이런 차이를 만들어 놨는지,

어느 경우에는 결과가 이렇게 나오는지 한번은 정리하고 가야하겠습니다. 


[우선 Python 이야기 먼저 해 보지요]

 

최근 Data분석을 위한 Tool으로써, Python의 인기가 급격하게 상승하고 있습니다.

Python은 방대한 범위와 대조적으로,,, 초라하지만, Data Analytics 관점에서 접근해 보고자 합니다.

 

기존에 R, SPSS, Matlab 등이 다양하게 사용되어 왔었으나, 각 도구의 유료(비용) 측면과, 라이브러리의 활용성 측면에서, R과 Python으로 귀결되고 있는것으로 보입니다.

 

더보기

최근에 데이터 분석, App개발, 웹프레임워크, 인프라 관리, 자동화 등 다양한 영역에서 범용적으로 사용하고 있는 막강한 스크립트형 언어 입니다. 

(과거에는 스크립트는 언어로 취급도 않했었는데, 정말 대중성이라는 것이 무섭습니다.)

 

주로 통계를 다루기 위해서 개발된 언어/플랫폼 이지요.

SPSS, Matlab 등의 무료 버전 이라고 생각할 수 있습니다.

상당히 강력하며, 참고 자료가 많기 때문에, 데이터 분석 분야의 대세중 한축입니다.

다만, 파이썬과 비교하여 범용성측면이 약한것이 단점 입니다. 

 

 

 

물론, SPSS, SAS E-Miner 등의 편리한 GUI성은 진입장벽을 많이 낮추어 주지만,

 

최근 주로 사용되는 D-NN, C-NN, 강화학습을 활용하기 어려워, Python으로 대체되고 있다.

 

 

 

 

기존 Matlab에서는 모든 알고리즘을 자체 개발하거나, 다른 연구자의 라이브러리를 직접 수정해서 사용해야 했으나, 요즈음 대중성이 떨어지고 있어서 좀 그렇습니다. 

그러나, 저는 개인적으로 아직도 Matlab을 좋아합니다.

 


언어의 종류를 뛰어 넘어서, 최근 데이터 분석/ 머신러닝 알고리즘 등을 구현한 라이브러리 들이 활용되고 있습니다. 

Tensorflow , PyTorch, Theano, Caffe 등 상위레벨 라이브러리 들이 대세입니다.

몇년 전만해도 Machine Learning 알고리즘 구현/활용을 위해서는, 알고리즘 하나 하나를 구현하고 매개변수를 조정하였는데, 

요즈음은 라이브러리를 그냥 가져다 사용만 하면 되는 구조로 바뀌었습니다. 

누구나 Machine Learning을 활용하여 개발 할 수 있는 시대가 되었네요.

 

 

Tensorflow
torch
Theano

 

 

 

물론, 그 원리와 결과에 대한 해석 등 부분은 다양한 로직/수학적 사고 등이 필요하므로 어느정도 진입 장벽이 있을 것이나, 최근 D-NN 등은 태생자체가 BlackBox 알고리즘으로, 알고리즘을 이해하고 있어서, 결과에 대한 원인 규명에 한계는 명확하다. 


각설하고, 

 

Python을 사용하여 머신러닝을 구현하기 위해서는, 기본적으로 벡터(Vector) / 행렬 (matrix)를 능숙하게 다룰 수 있어야 한다. 

 

요런거요...

 

 

행렬을 다루게 되면 필연적으로, 일반적인 숫자연산 (Scalar)외에

행렬곱 / 내적 등 행렬연산 (Vector/Matrix Calculation)이 필요합니다. 

 

이것을 개발자가 일일이 구현하기에는 생산성이 떨어집니다. 

(※ Matlab 등은 기본 연산 방식이 벡터/행렬)

 

행렬 연산

 

 

예를 들면, 기존의 방식의 배열(Array) / 리스트(List)로 행렬 덧셈을 하기 위해서는, 모든 계산마다 For Loop를 통해 계산 해야 합니다.

이렇게 되면, 수학적 연산에 집중하지 못하고, Loop에 집중하여, 주객전도가 발생하는 꼴이 될 수 있죠.

 

 

시간도 없는데.... 선택과 집중.....!!이 필요합니다.

 

그래서,

이런 Vector/Matrix 연산 지원하는 라이브러리 Numpy를 사용합니다. 

( ※ 추후, 데이터 분석을 위해서, Numpy에 기반을 두고, Series / DataFrame 등으로 파생하는 것이 Pandas라 하겠다. )

 


 

[ Numpy - Numerical Python(???) ]

 

 

python 의 기본 배열형은 vector / Matrix 연산을 지원하지 않는다.

예를 한번 들어 보자.

 

>>> a = [0, 1, 2, 3, 4 ] >>> a * 3 [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4]

>>> type(a) <class 'list'>

아래와 같이 List a = [0, 1, 2, 3, 4]가 있다고 가정하면, python의 기본형에서, a *3 은 "a를 3번 반복한 결과"를 반환한다.

 

그러나, 선형대수학 (Linear Algebra)에서는, a*3은 "각 원소에 3배수"를 의미한다.

순수한 C/Java에서, 이 들을 구하기 위해서는 For Loop 등을 사용하여, 각 원소에 3을 곱하는 방법이 있겠다.

 

데이터과학 및 데이터분석, Machine Learning 등을 사용할 때는,

단순곱 외에도, 내적(inner Product), 외적(Outer Product), 전치(Transpose), 행렬곱(Matrix Product), 역함수(Inverse), 대각행렬(Diagonal Matrix) ...등

다수의 연산 등을 처리하는 것은 여간 번거롭지 않을 수 없다.

 

따라서, 이러한 Needs에 따라서, 벡터/행렬연산 (ex. "a*3" 등)을 간소화하고, 문자열 위주 대신 벡터/행렬의 단위 연산을 해주는 제공하기 위해 Numpy를 사용한다.

 

>>> import numpy as np

>>> np_a = np.array( [0, 1, 2, 3, 4] )

>>> np_a

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

>>> np_a * 3

array([ 0,  3,  6,  9, 12])

>>> type(np_a)

 

<class 'numpy.ndarray'>

 

Python의 기본형(list)과는 달리, numpy의 array는 "numpy.ndarray"형으로 표기된다.  ( ※ type : ndarry ⇒ N Dimensional Array : N차원 배열 )

 

아래, 일반 python list와 numpy list를 비교하여 보도록 하자.

 

[ 벡터곱/행렬곱 ]

 

Python Native

 

 NumPy

 >>> a = [1, 2, 3, 4]

>>> b = [10, 20, 30, 40]

>>> a*b

Traceback (most recent call last):

 File "<stdin>", line 1, in <module>

 

 

 >>> import numpy as np

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

>>> b = np.array([10,20,30,40])

>>> c = a*b

>>> c

array([ 10,  40,  90, 160])

 

 

 

Python Native

 

 NumPy

>>>python_list = [1, 2, 3] 

>>> python_list

[1, 2, 3]

>>> python_list *2

[1, 2, 3, 1, 2, 3]

>>> python_list * 3

[1, 2, 3, 1, 2, 3, 1, 2, 3]

 

 

>>>python_list = [1, 2, 3] 

>>> np.array(python_list) * 3

 

array([3, 6, 9])

 

[ 벡터/행렬 Add ]

 

Python Native

 

 NumPy

 >>> python_list = [1,2,3]

>>> python_list + python_list

[1, 2, 3, 1, 2, 3]

 

 >>> np_list = np.array([1,2,3])

>>> np_list + np_list

array([2, 4, 6])

 

 

[ 벡터/행렬 비교 - Comparison ]

 

Python Native

 

 NumPy

 >>> python_list

[1, 2, 3]

>>> python_list > 1

True

>>> python_list > 2

True

 

 >>> np_list

array([1, 2, 3])

>>> np_list>1

array([ False,  True,  True], dtype=bool)

>>> np_list > 2

array([False, False,  True], dtype=bool)

 

 

[ 2차원 벡터 - 행렬 Matrix ]

○ Python의 기본 List형에서는 2차원 배열이라기 보다는 중첩된 배열이라고 봐야 한다. 즉, 배열의 한 원소가 또 다른 배열로 처리된 것 뿐이므로, 아래 표현되는 2차원 형태의 Shape, size 등의 개념 자체가 없다. 의미 자체가 없다.

 

Python의 list에는 Length 개념 밖에 없으며, 추가/삭제/삽입, push/pop/sort 등의 개념만이 존재 한다.

따라서, 행렬(Matrix) 개념에서 기본List형의 예는 생략한다.

 

 

Code

 

설명 

>>> np_2d = np.array( [ [1,2,3], [4,5,6] ] )

>>> np_2d

array([[1, 2, 3],

 

      [4, 5, 6]])

 

 2차원 배열 (행렬) 생성

 

Code

 

설명 

>>> np_2d.shape

(2L, 3L)     # 2 Rows, 3 Columns

 

 2차원 행렬 

 

 

 

 [2차원 배열의 인덱싱/슬라이싱]

Code

 

설명 

>>> np_2d [0]    

array([1, 2, 3])

 

>>> np_2d [1,:]    # Row 한줄

array([4, 5, 6])

 

>>> np_2d [0][1]

2

>>> np_2d  [0,1]

2

>>> np_2d [:,1]   # Column 한줄

array([2, 5])

>>> np_2d [:2,1:]  # Slicing

array([[2, 3],

 

      [5, 6]])

 

# 첫번째 Row 한줄

 

 

# 두번째 Row 한줄 (모든 컬럼)

 

 

 

# 첫번째 Row에서, 두번째 Col 

 

# 첫번째 Row, 두번째 Col

 

# 두번째 Col 전체

 

# ~두번째 Row, 두번째 Col ~ 마지막Col

 

 

 

 

댓글0