Numpy 라이브러리
Numpy 는 파이썬이 계산과학분야에 이용될 때 핵심 역할을 하는 라이브러리로, 고성능의 다차원 배열 객체와 이를 다룰 도구를 제공합니다. scikit-learn 에서 Numpy 배열은 기본 데이터 구조입니다.
용어 정리
본격적으로 사용법을 알기 전에 용어를 알도록 합시다.
- axis : 각 차원의 축
- rank : 축의 개수
- shape : 배열의 축 길이
- size : 배열의 사이즈
코드를 통해 이제 각 의미를 더 알아봅시다.
소스코드로 알아보기
import
우선 넘파이를 사용하기 위해서는 numpy를 불러와야합니다.
import numpy as np
numpy를 보통 np로 alias합니다.
배열
Numpy의 가장 핵심은 배열 객체입니다. 배열 객체의 생성과 각 객체가 어떻게 생겼는지 알아봅시다.
array
기본적인 배열을 의미합니다. 다음과 같이 생성 맟 초기화 할 수 있습니다.
import numpy as np
a = np.array([1, 2, 3]) # rank가 1인 배열 생성
type
그리고 shap
을 확인해보면 다음과 같습니다.
print(type(a)) # 출력 "<type 'numpy.ndarray'>"
print(a.shape) # 출력 "(3,)"
print(a[0], a[1], a[2]) # 출력 "1 2 3"
a[0] = 5 # 요소를 변경
print(a) # 출력 "[5, 2, 3]"
b = np.array([[1,2,3],[4,5,6]]) # rank가 2인 배열 생성
print(b.shape) # 출력 "(2, 3)"
print(b[0, 0], b[0, 1], b[1, 0]) # 출력 "1 2 4"
zeros / ones / full
원하는 값으로 채워진 배열을 만들기 위해 사용됩니다.
- zeros : 0
- ones : 1
- full : 파라미터 지정값
# zeros
a = np.zeros(5)
b = np.zeros((3,4))
print(a)
# [0. 0. 0. 0. 0.]
print(b)
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
# ones
c = np.ones(5)
d = np.ones((3,4))
print(c)
# [1. 1. 1. 1. 1.]
print(d)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# full
e = np.full((3,2),7)
print(e)
#[[7 7]
# [7 7]
# [7 7]]
eye
단위 행렬로 만드는 함수입니다. 정사각행렬에 주대선의 원소들이 1인 행렬입니다.
a = np.eye(2)
print(a)
#[[1. 0.]
# [0. 1.]]
배열 인덱싱
넘파이 배열을 인덱싱하는 방법에 대해서 알아봅시다.
슬라이싱
파이썬 배열과 마찬가지로 슬라이싱을 할 수 있습니다.
import numpy as np
# 아래와 같은 요소를 가지는 rank가 2이고 shape가 (3, 4)인 배열 생성
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 배열의 중간 행에 접근하는 두 가지 방법이 있습니다.
# 정수 인덱싱과 슬라이싱을 혼합해서 사용하면 낮은 rank의 배열이 생성되지만,
# 슬라이싱만 사용하면 원본 배열과 동일한 rank의 배열이 생성됩니다.
row_r1 = a[1, :] # 배열a의 두 번째 행을 rank가 1인 배열로
row_r2 = a[1:2, :] # 배열a의 두 번째 행을 rank가 2인 배열로
print(row_r1, row_r1.shape) # 출력 "[5 6 7 8] (4,)"
print(row_r2, row_r2.shape) # 출력 "[[5 6 7 8]] (1, 4)"
# 행이 아닌 열의 경우에도 마찬가지입니다:
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print(col_r1, col_r1.shape) # 출력 "[ 2 6 10] (3,)"
print(col_r2, col_r2.shape) # 출력 "[[ 2]
# [ 6]
# [10]] (3, 1)"
정수 배열 인덱싱
슬라이싱은 배열에서 부분배열로 만드는 방법이라면, 인덱싱을 이용하면 새로운 배열을 만들 수 있습니다.
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
# 정수 배열 인덱싱의 예.
# 반환되는 배열의 shape는 (3,)
print (a[[0, 1, 2], [0, 1, 0]]) # 출력 "[1 4 5]"
# 정수 배열 인덱싱을 사용할 때,
# 원본 배열의 같은 요소를 재사용할 수 있습니다:
print (a[[0, 0], [1, 1]]) # 출력 "[2 2]"
다음과 같은 방법으로 활용할 수 있습니다.
import numpy as np
# 요소를 선택할 새로운 배열 생성
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print (a) # 출력 "array([[ 1, 2, 3],
# [ 4, 5, 6],
# [ 7, 8, 9],
# [10, 11, 12]])"
# 인덱스를 저장할 배열 생성
b = np.array([0, 2, 0, 1])
# b에 저장된 인덱스를 이용해 각 행에서 하나의 요소를 선택합니다
print (a[np.arange(4), b]) # 출력 "[ 1 6 7 11]"
# b에 저장된 인덱스를 이용해 각 행에서 하나의 요소를 변경합니다
a[np.arange(4), b] += 10
print (a) # 출력 "array([[11, 2, 3],
# [ 4, 5, 16],
# [17, 8, 9],
# [10, 21, 12]])
불리안 배열 인덱싱
불리안 즉 조건을 통해 원하는 정보만 가져올 수도 있습니다.
import numpy as np
a = np.array([[1,2], [3, 4], [5, 6]])
bool_idx = (a > 2) # 2보다 큰 a의 요소를 찾습니다;
# 이 코드는 a와 shape가 같고 불리언 자료형을 요소로 하는 numpy 배열을 반환합니다,
# bool_idx의 각 요소는 동일한 위치에 있는 a의
# 요소가 2보다 큰지를 말해줍니다.
print(bool_idx) # 출력 "[[False False]
# [ True True]
# [ True True]]"
# 불리언 배열 인덱싱을 통해 bool_idx에서
# 참 값을 가지는 요소로 구성되는
# rank 1인 배열을 구성할 수 있습니다.
print (a[bool_idx]) # 출력 "[3 4 5 6]"
# 위에서 한 모든것을 한 문장으로 할 수 있습니다:
print (a[a > 2]) # 출력 "[3 4 5 6]"
자료형
생략
연산
넘파이는 행렬간 연산을 효율적으로 해주기에 유용하며, 앞으로 사용해야하는 다양한 연산이 있지만 그 중에서도 기본은 다음과 같습니다.
기본 연산
넘파이에서 기본적인 연산의 경우에는 각 대응되는 원소간의 연산으로 이루어집니다. 배열에서의 각 원소가 독립적으로 계산되는 것 입니다.
import numpy as np
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)
# 요소별 합; 둘 다 다음의 배열을 만듭니다
# [[ 6.0 8.0]
# [10.0 12.0]]
print (x + y)
print (np.add(x, y))
# 요소별 차; 둘 다 다음의 배열을 만듭니다
# [[-4.0 -4.0]
# [-4.0 -4.0]]
print (x - y)
print (np.subtract(x, y))
# 요소별 곱; 둘 다 다음의 배열을 만듭니다
# [[ 5.0 12.0]
# [21.0 32.0]]
print (x * y)
print (np.multiply(x, y))
# 요소별 나눗셈; 둘 다 다음의 배열을 만듭니다
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print (x / y)
print (np.divide(x, y))
# 요소별 제곱근; 다음의 배열을 만듭니다
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
print (np.sqrt(x))
dot 연산
import numpy as np
x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])
v = np.array([9,10])
w = np.array([11, 12])
# 벡터의 내적; 둘 다 결과는 219
print (v.dot(w))
print (np.dot(v, w))
# 행렬과 벡터의 곱; 둘 다 결과는 rank 1인 배열 [29 67]
print (x.dot(v))
print (np.dot(x, v))
# 행렬곱; 둘 다 결과는 rank 2인 배열
# [[19 22]
# [43 50]]
print (x.dot(y))
print (np.dot(x, y))
sum 연산
다양한 연산이 존재하지만 sum
은 그 중에서도 유용한 기능을 가지고 있습니다.
import numpy as np
x = np.array([[1,2],[3,4]])
print (np.sum(x)) # 모든 요소를 합한 값을 연산; 출력 "10"
print (np.sum(x, axis=0)) # 각 열에 대한 합을 연산; 출력 "[4 6]"
print (np.sum(x, axis=1)) # 각 행에 대한 합을 연산; 출력 "[3 7]"
변환
전치
연산이 아니라도 전처리를 하기 위해 변환이 필요합니다. 그 중에서 가장 많이 사용되는 것은 전치입니다. 주대각선을 기준으로 뒤집는 연산입니다. 2차원 행열에서는 행과 열이 바뀌는 것을 의미합니다.
import numpy as np
x = np.array([[1,2], [3,4]])
print (x) # 출력 "[[1 2]
# [3 4]]"
print (x.T) # 출력 "[[1 3]
# [2 4]]"
# rank 1인 배열을 전치할 경우 아무 일도 일어나지 않습니다:
v = np.array([1,2,3])
print (v) # 출력 "[1 2 3]"
print (v.T) # 출력 "[1 2 3]"
브로드캐스팅
numpy의 가장 큰 장점은 크기가 다른 배열에서도 연산을 가능하게 해줍니다. 이를 브로드캐스팅이라고 합니다.
하지만 귀찮으니까 나중에 정리하겠습니다.
Leave a Comment