안녕하세요 콥스랩(COBS LAB)입니다. 오늘 소개해드릴 주제는 Numpy입니다. 이번에는 배열 데이터를 다룰 수 있는 파이썬 라이브러리인 넘파이(Numpy)의 개념과 기본 배열 생성에 대해 알아보도록 하겠습니다.
목차
- 배열 정의 및 생성
- 배열 shape
- 배열 연산
Numpy란?
파이썬 기반 데이터 분석 환경에서 NumPy는 행렬 연산을 위한 핵심 라이브러리입니다. NumPy는 “Numerical Python “의 약자로 대규모 다차원 배열과 행렬 연산에 필요한 다양한 함수를 제공합니다. 파이썬 list 객체를 개선한 NumPy의 ndarray 객체를 사용하면 더 많은 데이터를 더 빠르게 처리할 수 있습니다.
Numpy를 사용하는 이유 :
- 메모리 사이즈 : 메모리 버퍼에 배열 데이터를 저장하고 처리하는 효율적인 인터페이스를 제공합니다.
- 성능 : 파이썬 list 객체를 개선한 NumPy의 ndarray 객체를 통해 더 많은 데이터를 더 빠르게 처리할 수 있습니다.
- 빌트인 함수 : 선형대수, 통계 관련 여러 함수가 내장되어 있습니다.
Python에서 Arrays를 사용하는 이유
Python의 Arrays은 동일한 유형의 여러 값을 저장할 수 있는 데이터 구조입니다. Arrays와 Python을 조합하면 많은 시간을 절약할 수 있습니다. 앞에서 설명한 바와 같이 Arrays은 코드 전체의 크기를 줄이는 데 도움이 되며, 파이썬은 다른 언어와는 달리 문제가 있는 구문을 제거하는 데 도움이 됩니다. 예를 들어 1 ~ 100의 정수를 저장해야 하는 경우 100개의 변수 이름을 명시적으로 기억할 수 없기 때문에 배열을 사용하여 쉽게 저장할 수 있습니다**.**
Python에서의 Arrays란?
Array는 정적 할당에 해당하며, List의 경우는 동적 할당에 해당합니다. 동적으로 계속 크기가 변할 수 있는 Python List와 달리 NumPy Array는 고정된 크기를 갖습니다. Size를 변화하면 기존의 array를 삭제하고 새로운 array를 생성해야 합니다.
Numpy를 사용하면 Array를 Python에서 사용할 수 있습니다. Numpy는 다차원적인 배열 객체, 다양한 파생 객체(마스크 된 배열 및 행렬 등) 및 에 대한 다양한 작업을 지원하고 있습니다.
array는 기본적으로 np.array( ) 함수를 사용하여 정의합니다. 이때 Python 리스트 혹은 기존에 정의된 다른 array가 함수의 인자로 입력됩니다. array를 생성할 때 인자로 입력되는 Python 리스트는 1차원 혹은 그 이상의 차원을 가지는 것이 될 수 있습니다.
numpy에서 array를 생성하고 사용할 때는, 해당 array의 크기(혹은 모양)에 대한 정보를 항상 트래킹 하고 있는 것이 중요합니다.
Python에서 Arrays 생성
Python의 Arrays는 Arrays 모듈을 Import 한 후 다음과 같이 생성할 수 있습니다.
numpy는 범용적으로 활용되는 파이썬 패키지이지만, 기본적으로 파이썬에 포함되어있는 패키지는 아닙니다.
활용하기 위해서는 다음 명령어를 통해 설치 및 임포트를 해야 합니다.
!pip install numpy
import numpy as np
print("numpy version: ", np.__version__)
NumPy 배열은 다차원 배열을 지원합니다. NumPy 배열의 구조는 “Shape “으로 표현됩니다. Shape은 배열의 구조를 파이썬 튜플 자료형을 이용하여 정의합니다.
다차원 배열은 입체적인 데이터 구조를 가지며, 데이터의 차원은 여러 갈래의 데이터 방향을 갖습니다. 다차원 배열의 데이터 방향을 axis로 표현할 수 있습니다. 행방향(높이), 열 방향(폭), 채널 방향은 각각 axis=0, axis=1 그리고 axis=2로 지정됩니다.
배열 생성
배열을 생성하는 기본적인 방법인 array입니다. array에는 리스트나 튜플 객체를 인자로 받습니다. 아래 코드처럼 원소가 3개인 1차원 배열을 생성했습니다.
a = np.array([ 1, 2, 3])
print(a)
>>>[1 2 3]
print(a.shape)
>>>(3,)
2차원 배열 즉, 행렬도 생성할 수 있습니다. 2중 리스트를 array인자에 넘겨주면 됩니다.
a = np.array([[ 1, 0, 0],
[ 0, 1, 2]])
print(a.shape)
>>>(2,3)
배열 생성 및 초기화
Numpy는 원하는 shape으로 배열을 설정하고, 각 요소를 특정 값으로 초기화하는 zeros, ones, full, eye 함수를 제공합니다. 또한, 파라미터로 입력한 배열과 같은 shape의 배열을 만드는 zeros_like, ones_like, full_like 함수도 제공합니다. 이 함수를 이용하여 배열 생성하고 초기화할 수 있습니다.
np.zeros(shape, dtype=np.float64)
지정된 shape의 배열을 생성하고, 모든 요소를 0으로 초기화시켜 줍니다. zeros함수는 1차원 0 벡터를 생성할 경우 양의 정수를, 2차원 0 행렬을 생성할 경우 행, 열 개수를 지정해줘야 합니다.
a = np.zeros((3, 4))
print(a)
>>>
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]]
[ 3, 4 ] 크기의 배열을 생성하고 0으로 채워줍니다.
np.ones(shape, dtype=np.float64)
지정된 shape의 배열을 생성하고, 모든 요소를 1로 초기화시켜 줍니다. ones함수는 zeros함수와 마찬가지로 1로만 이루어진 array를 생성합니다.
a = np.ones((3,4), dtype=np.float64)
print(a)
>>>
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[ 3, 4 ] 크기의 배열을 생성하고 1로 채워줍니다.
np.full(shape, fill_value, dtype=None)
지정된 shape의 배열을 생성하고, 모든 요소를 지정한 "fill_value"로 초기화시켜 줍니다.
full 함수는 지정된 모양 및 데이터 유형으로 배열을 특정 값으로 채웁니다. 배열의 모양, 채울 값 및 배열의 데이터 유형을 입력 매개 변수로 취하고 지정된 값으로 채워진 지정된 모양 및 데이터 유형의 배열을 리턴합니다.
a = np.full(5,7)
print(a)
>>>
[7 7 7 7 7]
위의 코드에서 full 함수로 길이 5 배열 안에 7 값을 채웁니다. 배열의 모양과 full 함수 내에서 원하는 값을 지정하여 동일한 값으로 NumPy 배열을 초기화합니다.
np.eye(N, M=None, k=0, dtype=np.float32)
(N, N) shape의 단위행렬(Unit Matrix)을 생성합니다.
#단위행렬: 대각행렬이 1이고 나머지는 모두 0인 행렬
np.eye(4)
print(a)
>>>
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
np.empty(shape, dtype=float64)
empty 함수는 초기화되지 않은 값으로 zeros나 ones와 마찬가지로 배열을 생성합니다.
주의해야 할 것은 메모리도 초기화되지 않기 때문에 예상하지 못한 불필요한 값이 들어가 있습니다.
a = np.empty((3,4))
print(a)
>>>
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
아래 코드는 초기화되지 않은 [ 3, 4 ] 크기의 배열을 생성합니다.
데이터 생성 함수
NumPy는 주어진 조건으로 데이터를 생성한 후, 배열을 만드는 데이터 생성 함수를 제공합니다.
numpy.arange([start,] stop [, step,], dtype=None)
start부터 stop 미만까지 step 간격으로 데이터 생성한 후 배열을 만들어줍니다.
범위 내에서 간격을 기준 균등 간격의 배열을 생성합니다.
요소의 개수가 아닌 데이터의 간격을 기준으로 배열을 생성합니다.
a = np.arange(0, 10, 2, np.float)
print(a)
>>>
[ 0. 2. 4. 6. 8.]
0부터 10 미만까지 2 간격으로 데이터를 생성하였습니다.
numpy.linspace(start, stop, num=50, endpoint=True, restep=False, dtype = None)
start부터 stop의 범위에서 num개를 균일한 간격으로 데이터를 생성하고 배열을 만드는 함수입니다.
요소 개수를 기준으로 균등 간격의 배열을 생성합니다.
a = np.linspace(0, 100, 5)
print(a)
>>>
[0. , 25. , 50. , 75. , 100.]
0부터 100 범위에서 5개의 균일한 간격으로 데이터를 생성하였습니다.
numpy.longspace(start, stop, num=50, endpoint=True, base=10.0, dtype = None)
로그 스케일의 linspace 함수입니다. 로그 스케일로 지정된 범위에서 num 개수만큼 균등 간격으로 데이터 생성한 후 배열을 생성합니다.
a = np.logspace(0.1, 1, 20, endpoint=True)
print(a)
>>>
[ 1.25892541 1.40400425 1.565802 1.74624535 1.94748304 2.1719114
2.42220294 2.70133812 3.0126409 3.35981829 3.74700446 4.17881006
4.66037703 5.19743987 5.79639395 6.46437163 7.2093272 8.04013161
8.9666781 10. ]
Shape이란?
머신 러닝에서 행렬의 차원을 shape라는 개념으로 표현합니다.
#형상(shape) 확인하기
arr = np.array([1, 2, 3]) #1차원 배열
print(arr.shape)
>> (3,)
arr2 = np.array([[1, 2, 3],[4, 5, 6]]) #2차원 배열
print(arr2.shape)
>> (2, 3)
확인하고 싶은 배열에. shape을 더하면 해당 배열의 형상을 확인할 수 있습니다. 1차원 배열에서 (m, )은 m칸으로 구성된 1차원 배열이라는 의미입니다. 2차원 배열에서의 (m, n)는 m행 n열로 구성된 2차원 배열을 의미합니다. 3차원 배열에서 shape을 구하면 (층, 행, 열) 총 3가지 정보를 얻을 수 있습니다.
reshape
reshape 기능은 배열의 차원의 크기를 변경하는 방법입니다. 배열의 요소의 개수는 동일하며 차원만 조정합니다.
예를 들면 (2,4) 차원의 배열을 reshape 기능을 통해 (8,) 차원으로 변경이 가능합니다. 배열의 사이즈만 같다면 다차원으로 자유롭게 변형이 가능합니다.
import numpy as np
test_array = [[1,2,3,4],[1,2,3,4]]
가장 먼저 numpy를 import 하고 테스트 배열을 만들어 줍니다.
test_matrix = np.array(test_array)
test_matrix.shape
>>>
(2,4)
np.array를 생성 한 뒤 shape 하면 해당 차원이 몇 차원인지 표시해 줍니다.
test_matrix = np.array(test_array).reshape(8,)
test_matrix
>>>
array([1, 2, 3, 4, 1, 2, 3, 4])
만들어진 행렬을 reshape을 하면 차원을 변경할 수 있습니다.
test_matrix = np.array(test_array).reshape(2,2,2)
test_matrix
(adsbygoogle = window.adsbygoogle || []).push({})
>>>
array([[[1, 2], [3, 4]], [[1, 2], [3, 4]]])
위와 같이 3차원으로도 변경이 가능합니다.
test_matrix = np.array(test_array).reshape(-1,2)
test_matrix
>>>
array([[1, 2],
[3, 4],
[1, 2],
[3, 4]])
1은 size를 기반으로 row 개수를 선정하는 옵션입니다.
flatten
flatten은 배열을 1차원 형태의 배열로 변환해주는 명령어입니다. 1차원 형태의 배열이 필요하다면 reshape 보다 간편하게 flatten만 사용하여 배열을 만들어 줄 수 있습니다.
test_matrix = np.array(test_array).flatten()
test_matrix
>>>
array([1, 2, 3, 4, 1, 2, 3, 4])
배열 연산
numpy는 기본적으로 array 간의 사칙 연산을 지원합니다.
행과 열이 같은 배열을 계산하면 값은 위치에 있는 값들이 계산됩니다.
이런 현상을 Element-wise operations이라 하며 Shape이 같을 때 발생합니다.
import numpy as np
a = np.array([[1,2,3],[4,5,6]], np.float)
(2, 3) 모양의 배열을 만들어 줍니다.
덧셈
a + a
>>>
array([[ 2., 4., 6.],
[ 8., 10., 12.]])
행과 열이 같은 배열이기 때문에 위치에 있는 값들끼리 더해줍니다.
뺄셈
a - a
>>>
array([[0., 0., 0.],
[0., 0., 0.]])
행과 열이 같은 배열이기 때문에 위치에 있는 값들끼리 빼줍니다.
곱셈
a * a
>>>
array([[ 1., 4., 9.],
[16., 25., 36.]])
행과 열이 같은 배열이기 때문에 위치에 있는 값들끼리 곱해줍니다.
나눗셈
a / a
>>>
array([[1., 1., 1.],
[1., 1., 1.]])
행과 열이 같은 배열이기 때문에 위치에 있는 값들끼리 나눠줍니다.
Broadcating
array 연산중 중요한 개념입니다. Shape이 다른 배열간 연산을 자동으로 지원하는 기능을 Broadcating이라 합니다.
열 또는 행이 어느 정도 shape이 맞아야 자동으로 계산해 줍니다. 일반적으로 NumPy에서 모양이 다른 배열끼리는 연산이 불가능합니다.
# 데모 배열 생성
a = np.arange(1, 25).reshape(4, 6)
b = np.arange(25, 49).reshape(4, 6)
print(a)
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]
[13 14 15 16 17 18]
[19 20 21 22 23 24]]
print(b)
[[25 26 27 28 29 30]
[31 32 33 34 35 36]
[37 38 39 40 41 42]
[43 44 45 46 47 48]]
두 넘파이 배열이 있습니다.
print(a+b)
[[26 28 30 32 34 36]
[38 40 42 44 46 48]
[50 52 54 56 58 60]
[62 64 66 68 70 72]]
Shape이 같은 배열의 이항 연산입니다. 위치가 같은 요소 단위로 수행되어 다음과 같은 결과가 나옵니다.(Broadcasting 이 일어나지 않았습니다.)
# 데모 배열 생성
a = np.arange(5).reshape((1, 5))
b = np.arange(5).reshape((5, 1))
print(a)
[[0 1 2 3 4]]
print(b)
[[0]
[1]
[2]
[3]
[4]]
print(a+b)
[[0 1 2 3 4]
[1 2 3 4 5]
[2 3 4 5 6]
[3 4 5 6 7]
[4 5 6 7 8]]
Shape이 다른 두 배열 사이의 이항 연산 사이에서는 두 배열을 같은 Shape로 만들어주는 Broadcasting 과정을 거친 후 연산을 수행합니다.
a=[[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4],
[0 1 2 3 4]]
b =[[0 0 0 0 0],
[1 1 1 1 1],
[2 2 2 2 2],
[3 3 3 3 3],
[4 4 4 4 4]]
이는 a와 b의 배열의 Broadcasting을 통해 아래와 같이 서로 같은 Shape로 바뀐 후 연산을 수행하게 되기 때문입니다. 즉, Broadcasting은 "두 배열 간의 연산 과정을 수행할 때 배열 간 Shape가 다를 경우 두 배열 간의 형상을 맞추는 작업을 말합니다."
'Numpy' 카테고리의 다른 글
Numpy 기초 (3) - 배열 차원, 배열 shape, dtype (0) | 2023.01.13 |
---|---|
Numpy 기초 (2) - 배열 인덱싱 및 슬라이싱, 다양한 함수들 (0) | 2023.01.04 |
댓글