갈루아의 반서재

728x90

Numpy로 수치계산하기 (1)


ndarray


일반적으로 n 차원 배열을 ndarray 라고 말하며, n 차원 매트릭스다. 모든 수를 인덱스로 식별한다.
ndarray는 기본적으로 다음으로 정의된다.

  • 차원수 dimensions
  • 세이프 shape
  • 스트라이드 stride
  • 데이터 타입 data type
  • 실제 데이터

배열에서 모든 원소는 같은 데이터 타입(homogeneously typed)을 가져야한다.


순수 파이썬과 NumPy 계산비교


1,000,000개의 무작위 원소를 갖는 두 벡터를 만들어, NumPy의 계산속도가 순수 파이썬 코드에 비해 얼마나 더 빠르지 확인해보자.

먼저 순수 파이썬 코드로 278ms 가 소요되었다.

1
2
3
4
5
6
7
8
9
10
11
12
>>> from random import random
>>> list_1 = [random() for __ in range(1000000)]
>>> list_2 = [random() for __ in range(1000000)]
>>> 
>>> out = [ x + y for (x, y) in zip(list_1, list_2)]
>>> out[:3]
 
[1.30941709729564070.97552266234633361.3935934203308324]
 
>>> %timeit [ x + y for (x, y) in zip(list_1, list_2)]
 
1 loop, best of 3278 ms per loop
cs



NumPy로 동일한 연산을 해보자. np.array() 함수는 파이썬 리스트를 ndarray로 변환한다. 약 2.76ms가 소요되어 약 100배 가까이 빠름을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
>>> import numpy as np
>>> arr_1 = np.array(list_1)
>>> arr_2 = np.array(list_2)
>>> 
>>> type(list_1), type(arr_1)
 
(list, numpy.ndarray)
 
>>> arr_1.shape
 
(1000000,)
 
>>> arr_1.dtype
 
dtype('float64')
 
>>> arr_1.ndim
 
1
 
>>> arr_1.strides
 
(8,)
 
>>> arr_1.dtype
 
dtype('float64')
 
>>> sum_arr = arr_1 + arr_2
>>> sum_arr[:3]
>>> array([ 1.3094171 ,  0.97552266,  1.39359342])
>>> 
>>> %timeit arr_1 + arr_2
 
100 loops, best of 32.76 ms per loop
cs


배열 생성과 로딩


np.linspace( ) 함수는 수를 공백으로 나눠 배열을 만든다.

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import numpy as np
>>> 
>>> print("ones", np.ones(5))
>>> print("arange", np.arange(5))
>>> print("linspace", np.linspace(0.1.5))
>>> print("random", np.random.uniform(size=3))
>>> print("custom", np.array([253]))
 
('ones', array([ 1.,  1.,  1.,  1.,  1.]))
('arange', array([01234]))
('linspace', array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ]))
('random', array([ 0.59753005,  0.60388531,  0.31248934]))
('custom', array([253]))
cs



np.array( ) 는 리스트나 튜플을 NumPy 배열로 변환한다.
np.ones( ) 는 기본으로 부동소수점 수의 배열을 생성하지만,  np.arange( )는 정수 배열을 생성한다. 하지만 다음과 같이 특정 데이터 타입을 명시할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> np.array([[12], [34]])
 
array([[12],
       [34]])
 
>>> np.ones(5, dtype=np.int64)
 
array([11111])
 
>>> np.arange(5).astype(np.float64)
 
array([ 0.,  1.,  2.,  3.,  4.])
 
cs



파일에서 배열 로딩


NYC 택시 데이터를 가지고 실습해보자. NYC 택시 데이터는 아래와 같은 구조를 가졌다.


numpy.load(file, mmap_mode=None, allow_pickle=True, fix_imports=True, encoding='ASCII')

Load arrays or pickled objects from .npy, .npz or pickled files.

numpy.save(file, arr, allow_pickle=True, fix_imports=True)

Save an array to a binary file in NumPy .npy format.

numpy.fromfile(file, dtype=float, count=-1, sep='')

Construct an array from data in a text or binary file.

numpy.fromstring(string, dtype=float, count=-1, sep='')

A new 1-D array initialized from raw binary or text data in a string.

numpy.loadtxt(fname, dtype=<type 'float'>, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0)

Load data from a text file.

Each row in the text file must have the same number of values.

numpy.genfromtxt(fname, dtype=<type 'float'>, comments='#', delimiter=None, skip_header=0, skip_footer=0, converters=None, missing_values=None, filling_values=None, usecols=None, names=None, excludelist=None, deletechars=None, replace_space='_', autostrip=False, case_sensitive=True, defaultfmt='f%i', unpack=None, usemask=False, loose=True, invalid_raise=True, max_rows=None)

Load data from a text file, with missing values handled as specified.

Each line past the first skip_header lines is split at the delimiter character, and characters following the comments character are discarded.


CSV 나 다른 종류의 혼합 데이터를 로드하기 위해서는 NumPy 보다는 판다스가 더 효율적이다. 판다스는 내부적으로 NumPy를 기반으로 하고 있기 때문에, 판다스와 NumPy 구조 간에 데이터 변환은 매우 용이하다. 다음 예제를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> import pandas as pd
>>> data = pd.read_csv('data/nyc_data.csv')
>>> 
>>> data.shape
 
(84694514)
 
>>> pickup = data[['pickup_longitude''pickup_latitude']].values
>>> 
>>> pickup
 
array([[-73.955925,  40.781887],
       [-74.005501,  40.745735],
       [-73.969955,  40.79977 ],
       ..., 
       [-73.993492,  40.729347],
       [-73.978477,  40.772945],
       [-73.987206,  40.750568]])
 
>>> pickup.shape
 
(8469452)
 
cs


참고 사이트


The N-dimensional array (ndarray) https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html


728x90