머신러닝/numpy

NumPy의 기초(1)

빈코더 2021. 9. 9. 22:21
728x90

NumPy

NumPy의 정의

NumPy는 Numerical Python의 줄임말로, 파이썬에서 산술 계산을 위한 가장 중요한 필수 패키지중 하나이다.

과학 계산을 위한 대부분의 패키지는 NumPy의 배열 객체를 데이터 교환을 위한 공통 언어처럼 사용된다.

  • 효율적인 차원 배열인 ndarray는 빠른 배열 계산과 유연한 브로드캐스팅 기능을 제공한다.
  • 반목문을 작성할 필요 없이 전체 데이터 배열을 빠르게 계산할 수 있는 표준 수학 함수
  • 배열 데이터를 디스크에 쓰거나 읽을 수 있는 도구와 메모리에 적재된 파일을 다루는 도구
  • 선형대수, 난수 생성기, 푸리에 변환등 가능
  • C, C++, 포트란으로 작성한 코드를 연결할 우 있는 C API

대부분의 데이터 분석 애플리케이션에서 중요하다고 생각되는 기능이다.

  • 벡터 배열 상에서 데이터 가공, 정제, 부분집합, 필터링, 변형 그리고 다른 여러 종류의 연산을 빠르게 수행
  • 정렬, 유일 원소 찾기, 집합 연산 같은 일반적인 배열 처리 알고리즘
  • 통계의 효과적인 표현과 데이터를 수집 요약하기
  • 다양한 종류의 데이터를 병합하고 엮기 위한 데이터 정렬과 데이터 간의 관계 조작
  • 내부에서 if - elif - else를 사용하는 반복문 대신 사용할 수 있는 조건절 표현을 허용하는 배열 처리
  • 데이터 묶음 전체에 적용할 수 있는 수집, 변형, 함수 적용 같은 데이터 처리

NumPy는 일반적인 산술 데이터 처리를 위한 기반 라이브러리를 제공하기 때문에 통계나 분석,

특히 표 형식의 데이터를 처리 하기 위해 Pandas를 사용하기 원한다.

또 Pandas는 NumPy에는 없는 시계열 처리 같은 다양한 도메인 특화 기능을 제공한다.

NumPy가 파이썬 산술 계싼 영역에서 중요한 위치를 차지하는 이유 중 하나는 대용량 데이터 배열을

효율적으로 다룰 수 있도록 설계되어 있다는 점이다.

  • NumPy는 내부적으로 데이터를 다른 내장 파이썬 객체와 구분된 연속된 메미로 블록에 저장한다.
  • NumPy의 각종 알고리즘은 모두 C로 작성되어 타입 검사나 다른 오버헤드 없이 메모리를 직접 조잘할 수 있다.
  • NumPy 배열은 또한 내장 파이썬의 연속된 자료형들보다 훨씬 더 적은 메모리를 사용한다.
  • NumPy 연산은 파이썬 반복문을 사용하지 않고 전체 배열에 대한 복잡한 계산을 수행할 수 있다.

ndarray와 python list의 성능 비교를 해보자.

  import numpy as np
  np_array = np.arange(1000000)
  py_list = list(range(1000000))
  %time for _ in range(10): np_array2 = np_array * 2

    Wall time: 25.9 ms

  %time for _ in range(10): py_list2 = [x * 2 for x in py_list]

      Wall time: 963 ms

위 결과만으로도 속도차이가 엄청나게 차이나는 것을 확인이 가능하다.

NumPy ndarray: 다차원 배열 객체

NumPy ndarray는 NumPy의 핵심 기능중 하나이다.

ndarray라고 하는 N차원의 배열 객체인데 파이썬에서 사용할 수 있는 대규모 데이터 집합을 담을 수 있는

빠르고 유연한 자료구조이다.

배열은 스칼라 원소간의 연산에 사용하는 문법과 비슷한 방식을 사용해서

전체 데이터 블록에 수학적 연산을 수행할 수 있도록 해준다.

하나씩 알아보자.

ndarray 생성

ndarray를 생성해보자.

import numpy as np
data = np.ndarray(2)
data
  array([1.1578953e-311, 0.0000000e+000])

위 와 같이 만들면 바로 생성이 된다.

이번엔 임의의 값을 넣어 생성을 해보자.

data2 = np.random.randn(2,3)
data2
  array([[ 1.58930177, -0.6037844 ,  0.9520013 ],
         [ 0.6570654 , -0.83009583,  0.19897079]])

위 처럼 random을 사용하면 난수를 포함한 array를 생성할 수 있는데 random에는 3가지 함수가 존재한다.

  • np.random.randint: 균일 분포의 정수 난수 1개 생성
  • np.random.rand: 0부터 1사이의 균일 분포에서 난수 matrix array생성
  • np.random.randn: 가우시안 표준 정규 분포에서 난수 matrix array생성
  • np.random.shuffle: 기존 데이터의 순서 바꾸기
  • np.random.choice: 기존 데이터에서 sampling
  • np.unique: 데이터에서 중복된 값을 제거하고 중복되지 않는 값의 리스트 출력
  • np.bincount: 발생하지 않은 사건에 대해서도 카운트
np.random.randint(6) # 0 ~ (n - 1)까지의 숫자에서 랜덤하게 1개
  2

np.random.randint(1, 20) # 지정한 범위내 숫자에서 랜덤하게 1개
  15

np.random.rand(6)
  array([0.11315208, 0.59243376, 0.28910335, 0.18578366, 0.40790048,
         0.98574094])

np.random.rand(3, 5) # matrix 설정
  array([[0.236882 , 0.15116258, 0.65353164, 0.52230733, 0.99831621],
        [0.75593244, 0.28804813, 0.35449516, 0.27738076, 0.50321845],
        [0.96315492, 0.78771536, 0.72716866, 0.67511291, 0.31734207]])

np.random.randn(5)
  array([ 1.54047096, 0.68563392, 2.48774941, 0.33427331, -0.56978784])

np.random.randn(3,5) # matrix 설정
  array([[ 0.95809303, -0.32382129, 0.77470499, 0.52591374, 1.4449184 ],
         [ 0.34988025, -0.05407742, -0.49471994, -0.17711538, 0.10095574],
         [-0.32601614, -0.71229428, 0.03242378, -2.00522372, -2.05218022]])

NumPy 배열의 산술 연산

배열의 중요한 특징은 for문을 작성하지 않고 데이터를 일괄 처리할 수 있다.

이를 벡터화라고 하는데, 같은 크기의 배열 간의 산술 연산은 배열의 각 원소 단위로 적용된다.

data = np.random.rand(2,5)
data
  array([[0.30245852, 0.24642019, 0.12861867, 0.10622089, 0.40544193],
         [0.62868546, 0.54278462, 0.7187829 , 0.19883709, 0.75629027]])

data * 10
  array([[3.02458523, 2.46420189, 1.28618674, 1.06220891, 4.05441929],
         [6.28685459, 5.42784621, 7.18782901, 1.98837093, 7.56290268]])

위 처럼 ndarray자체에 10을 곱해주면 전체에 10이 곱해지는 것을 확인이 가능하다.

다른 사칙연산도 가능하다.

data + data
  array([[0.60491705, 0.49284038, 0.25723735, 0.21244178, 0.81088386],
       [1.25737092, 1.08556924, 1.4375658 , 0.39767419, 1.51258054]])

data - data
  array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])

data / data
  array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

ndarray는 같은 종류의 데이터를 담을 수 있는 포괄적인 다차원 배열이다.

ndaaray의 모든 원소는 같은 자료형이어야 한다.

모든 배열은 각 차원의 크기를 알려주는 shape라는 튜플과 배열의 차원 수,

배열의 축 수를 알려주는 ndim, 배열에 저장된 자료형을 알려주는 dtype이라는 객체를 가지고 있다.

data
  array([[0.30245852, 0.24642019, 0.12861867, 0.10622089, 0.40544193],
       [0.62868546, 0.54278462, 0.7187829 , 0.19883709, 0.75629027]])

data.shape
  (2, 5)

data.ndim
  2

data.dtype
  dtype('float64')

기존 리스트를 ndarray로 변환 가능하다.

data = [[1,2,3,4]]
data_np = np.array(data)
data_np
  array([[1, 2, 3, 4]])

data2 = [[1,2,3,4],[5,6,7,8]]
data_np2 = np.array(data2)
data_np2
  array([[1, 2, 3, 4],
       [5, 6, 7, 8]])

np.array는 새로운 배열을 생성하기 위한 여러 함수를 가지고 있다.

  • zeros: 0을 원소로 가진 배열을 만든다.
  • ones: 1을 원소로 가진 배열을 만든다.
  • empty: 초기화 되지 않은 배열을 만든다. 잘안쓴다.
np.zeros(10)
  array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

np.zeros((2,5))
  array([[0., 0., 0., 0., 0.],
         [0., 0., 0., 0., 0.]])

np.ones(10)
  array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

np.ones((2,5))
  array([[1., 1., 1., 1., 1.],
         [1., 1., 1., 1., 1.]])

a = [1,2,3,4,5]
asarray(a)
  array([1, 2, 3, 4, 5])

dtype이 있기 때문에 NumPy가 강력하면서도 유연한 도구가 될 수 있는 것이다.

ndarray의 astpye메서드를 사용해서 배열의 dtype을 다른형으로 명시적으로 변환(또는 캐스팅)이 가능하다.

 

배열 생성 함수

  • array: 입력 데이터(리스트, 튜플, 배열 또는 다른 순차형 데이터)를 ndarray로 변환하며 dtype을 명시하지 않은경우
      자료형을 추론하여 저장한다. 기본적으로 입력 데이터는 복사된다.
  • asarray: 입력 데이터를 ndarray로 변환하지만 입력 데이터가 이미 ndarray일 경우 복사가 일어나지 않는다.
  • arange: 내장 range함수와 유사하지만 리스트대신 ndarray를 반환한다.
  • asfarray: 따로 dtype을 설정하지 않아도 자동으로 float형태로 배열을 생성한다.
  • ones: 주어진 dtype과 모양을 가지는 배열을 생성하고 내용을 모두 1로 초기화한다.
  • ones_like: 주어진 배열과 동일한 모양과 dtype을 가지는 배열을 새로 생성하여 내용을 모두 1로 초기화 한다.
  • zeros: 주어진 dtype과 모양을 가지는 배열을 생성하고 내용을 모두 0으로 초기화 한다.
  • zeros_like: 주어진 배열과 동일한 모양과 dtype을 가지는 배열을 새로 생성하여 내용을 모두 0으로 초기화 한다.
  • full, full_like: 인자로 받은 dtype과 배열의 모양을 가지는 배열을 생성하고 인자로 받은 값으로 배열을 채운다.
  • eye, identity: N x N 크기의 단위행령을 생성한다.(좌상단에서 우하단을 잇는 대각선은 1로 채워지고 나머지는 0으로 채워진다.) 

ndarray의 dtype

dtype은 ndarray가 메모리에 있는 특정 데이터를 해석하기 위해 필요한 정보(또는 메타데이터)를 담고 있는 특수한 객체이다.

 

arr1 = np.array([1,2,3], dtype=np.float64)
arr2 = np.array([1,2,3], dtype=np.int32)

arr1.dtype
  dtype('float64')

arr2.dtype
  dtype('int32')
  
arr = np.array([1,2,3,4,5])
arr.dtype
  dtype('int32')

float_arr = arr.astype(np.float64)
float_arr.dtype
  dtype('float64')

arr = np.array([3.7,2.5,-2.6,0.5,12.9])
arr.astype(np.int32)
  array([ 3,  2, -2,  0, 12])

arr_str = np.array(['2.5','-9.6','42'], dtype=np.string_)
arr_str.astype(float)
  array([ 2.5, -9.6, 42. ])
728x90

'머신러닝 > numpy' 카테고리의 다른 글

NumPy의 기초(5)  (0) 2021.10.06
NumPy의 기초(4)  (0) 2021.10.06
NumPy의 기초(3)  (0) 2021.09.09
NumPy의 기초(2)  (0) 2021.09.09