일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- db
- LSTM
- instaloader
- Seq2Seq
- 머신 러닝
- Regression
- gan
- machine learning
- 국민대학교
- 회귀
- 국민대
- GIT
- Stack
- python3
- kmu
- Python
- 재귀
- Heap
- SQL
- googleapiclient
- 파이썬
- PANDAS
- C++
- 정렬
- 스택
- programmers
- 운영체제
- 프로그래머스
- 데이터베이스
- OS
- Today
- Total
정리 노트
2일차(2022/07/05) 본문
오늘은 Numpy 모듈이 무엇인지 보고 이를 사용하는 방법에 대해 배웠습니다.
Numpy를 쓰는 이유?
사실 numpy를 쓴다고 하면 '아 쓰나 보다' 하고 아무렇지 않게 생각했지 이걸 써야 하는 이유에 대해 물으면 잘 몰랐습니다. numpy를 사용하면 필요한 연산들은 C로 만들어져 있기 때문에 python의 list를 사용하는 것보다 numpy의 array를 사용하는 것이 더 빠르다고 합니다. 아래의 방법을 통해 연산 시간을 간단하게 확인할 수 있었습니다.
import numpy as np
my_list = range(1000)
%timeit [i**2 for i in my_list] # %timeit은 timeit 모듈을 사용하겠다는 jupyter notebook 만의 문법입니다.
arr = np.arange(1000)
%timeit n**2
my_list를 사용했을 때는 한 번의 loop 마다 최대 224.1㎲ 걸렸고, arr를 사용했을 때는 한 번의 loop 마다 최대 1.38㎲ 걸렸습니다. 220배 넘게 차이가 났습니다. 이래서 numpy를 쓰나 봅니다.
numpy.array에서의 인덱싱
numpy.array에서도 파이썬의 리스트와 같이 인덱싱 기능을 제공합니다. 인덱싱 방식도 유사합니다.
둘의 차이는 numpy.array가 행렬의 범위로 커질 때 발생합니다. 파이썬의 이차원 배열에서는 []을 두 번 사용했다면, numpy.array에서의 행렬은 하나의 []안에서 쉼표로 행과 열을 구분합니다.
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a[0, 0], a[2, 2], a[1, 2])
a[0, 0]은 0행 0열의 값, a[1, 2]는 1행 2열의 값, a[2, 2]는 2행 2열의 값을 나타내므로 print 결과는 각각 1, 9, 6입니다.
인덱싱을 활용해 특정 열 또는 특정 행의 정보만 추출해올 수 있습니다.
print(a[:, 1], a[:2])
a[:, 1]은 모든 행의 범위에서 1열만 추출하므로 [[2], [5], [8]]이 출력되고, a[:2]는 1행까지의 정보만 추출하므로 [[1, 2, 3], [4, 5, 6]]이 출력됩니다.
numpy.array의 Broadcasting
피연산자가 연산을 할 수 없는 size를 가지고 있다면 다른 피연산자에 맞춰 자신을 resizing 하는 것을 Broadcasting이라고 합니다. 아래의 예제들을 보면 이해하기 더 쉽습니다.
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
x = np.array([1, 0, 1]) # 현재 x는 행 벡터
x = x[:, None] # x를 열 벡터러 변환
print(a + x)
y = np.array([1, 0, -1])
print(a * y)
t = np.array([1, 2, 3])
t = t[:, None]
u = np.array([1, -1, 0])
print(t + u)
a는 3 * 3 행렬이고, x는 3 * 1 행렬(벡터)입니다. 이 둘은 element-wise 덧셈이 불가능합니다. 하지만 numpy.array에서의 broadcasting을 하면 x는 자신이 갖고 있는 값을 복사해 a와 같은 size로 resizing 합니다. 즉 x는 [[1, 1, 1], [0, 0, 0], [1, 1, 1]]의 형태가 됩니다. 따라서 a + x를 실행하면 [[2, 3, 4], [4, 5, 6], [8, 9, 10]]이 출력됩니다.
y는 1 * 3 행렬(벡터)입니다. y는 a와 element-wise 곱셈을 할 수 없는 size이지만 broadcasting을 통해 [[1, 0, -1], [1, 0, -1], [1, 0, -1]]의 형태가 됩니다. 따라서 a * y를 실행하면 [[1, 0, -3], [4, 0, -6], [7, 0, -9]]가 출력됩니다.
t와 u는 각각 3 * 1 행렬, 1 * 3 행렬입니다. 이 경우 두 행렬이 서로에 맞춰 resizing을 진행합니다. 만약 t가 먼저 broadcasting을 한다면, t는 [[1, 1, 1], [2, 2, 2], [3, 3, 3]]이 되고 u가 t에 맞춰 [[1, -1, 0], [1, -1, 0], [1, -1, 0]]로 됩니다. 결국 두 3 * 3 행렬의 element-wise 덧셈이 이루어져 [[2, 0, 1], [3, 1, 2], [4, 2, 3]]이 출력됩니다.
Numpy로 선형대수 하기
numpy에서는 선형 대수를 할 수 있도록 많은 지원을 해줍니다.
numpy.zeros(dim) | 영행렬을 제공, dim은 숫자 또는 튜플(, ) |
numpy.ones(dim) | 일행렬을 제공, dim은 숫자 또는 튜플(, ) |
numpy.diag((main_diagonals)) | (main_diagonals)를 가지는 대각 행렬을 제공 |
numpy.eye(n) | 사이즈가 n * n인 항등행렬을 제공 |
numpy.array.dot(numpy.array) or '@' | 행렬 간의 곱 연산을 제공 |
numpy.array.trace() | 행렬의 Main Diagonal의 합을 제공 |
numpy.linalg.det(numpy.array) | 행렬의 행렬식을 제공 |
numpy.linalg.inv(numpy.array) | 행렬 A에 대해 AB = BA = I를 만족하는 행렬 B 제공 |
numpy.linalg.eig(numpy.array) | 정방행렬 A에 대해 Ax = (lambda)x를 만족하는 (lambda)와 x를 제공 |
아래에 사용 예시들을 적었습니다.
user@<your_name>:~$ python3
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.zeros(3)
array([0., 0., 0.])
>>> np.zeros((2, 1))
array([[0.],
[0.]])
>>> np.ones(4)
array([1., 1., 1., 1.])
>>> np.ones((4, 4))
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> np.diag((1, 2, 3, 4))
array([[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 3, 0],
[0, 0, 0, 4]])
>>> np.diag((1))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in diag
File "/usr/lib/python3/dist-packages/numpy/lib/twodim_base.py", line 285, in diag
raise ValueError("Input must be 1- or 2-d.")
ValueError: Input must be 1- or 2-d.
>>> numpy.eye(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'numpy' is not defined
>>> np.eye(2)
array([[1., 0.],
[0., 1.]])
>>> matrix1 = np.array([[0, 1, 2], [1, 2, 3]])
>>> matrix2 = np.array([[0, 1, 2], [1, 2, 3], [2, 3, 4]])
>>> matrix1 @ matrix2
array([[ 5, 8, 11],
[ 8, 14, 20]])
>>> matrix1.trace()
2
>>> matrix2.trace()
6
>>> np.linalg.det(matrix1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in det
File "/usr/lib/python3/dist-packages/numpy/linalg/linalg.py", line 2122, in det
_assertNdSquareness(a)
File "/usr/lib/python3/dist-packages/numpy/linalg/linalg.py", line 213, in _assertNdSquareness
raise LinAlgError('Last 2 dimensions of the array must be square')
numpy.linalg.LinAlgError: Last 2 dimensions of the array must be square
>>> np.linalg.det(matrix2)
0.0
>>> np.linalg.inv(matrix1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in inv
File "/usr/lib/python3/dist-packages/numpy/linalg/linalg.py", line 546, in inv
_assertNdSquareness(a)
File "/usr/lib/python3/dist-packages/numpy/linalg/linalg.py", line 213, in _assertNdSquareness
raise LinAlgError('Last 2 dimensions of the array must be square')
numpy.linalg.LinAlgError: Last 2 dimensions of the array must be square
>>> matrix3 = [[3, 8], [7, 1]]
>>> np.linalg.inv(matrix3)
array([[-0.01886792, 0.1509434 ],
[ 0.13207547, -0.05660377]])
>>> matrix3 @ np.linalg.inv(matrix3)
array([[1., 0.],
[0., 1.]])
>>> np.linalg.eig(matrix2)
(array([ 6.87298335e+00, -8.72983346e-01, -7.69038628e-16]), array([[-0.30646053, -0.8598926 , 0.40824829],
[-0.54384383, -0.19382266, -0.81649658],
[-0.78122713, 0.47224729, 0.40824829]]))
'[TIL]국민대X프로그래머스 여름방학 인공지능 과정' 카테고리의 다른 글
6일 차(2022/07/11) (0) | 2022.07.12 |
---|---|
5일 차(2022/07/08) (0) | 2022.07.08 |
4일 차(2022/07/07) (0) | 2022.07.07 |
3일차(2022/07/06) (0) | 2022.07.06 |
1일차(2022/07/04) (0) | 2022.07.05 |