[파이썬-Python] Numpy는 왜 필요할까?
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을 활용하여 개발 할 수 있는 시대가 되었네요.



물론, 그 원리와 결과에 대한 해석 등 부분은 다양한 로직/수학적 사고 등이 필요하므로 어느정도 진입 장벽이 있을 것이나, 최근 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
|