1. 행렬 곱 (Matrix Multiplication) - dot()
n1 = np.arange(10).reshape(2, 5)
n2 = np.arange(15).reshape(5, 3)
result = n1.dot(n2)
print(result)
# n1 (2, 5)
# [[0, 1, 2, 3, 4],
# [5, 6, 7, 8, 9]]
# n2 (5, 3)
# [[ 0, 1, 2],
# [ 3, 4, 5],
# [ 6, 7, 8],
# [ 9, 10, 11],
# [12, 13, 14]]
# result
# [[ 90 100 110]
# [240 275 310]]
- 행렬 곱을 위해선 곱해지는 n1의 열과 n2의 행의 수가 같아야함. (위의 예시에서는 5로 동일)
- n1 * n2 는 행렬 곱이 아님에 유의
2. 역행렬 & 의사역행렬 (Inverse & Pseudoinverse) - inv(), pinv()
import numpy.linalg as linalg
m3 = np.array([[1,2,3],[5,7,11],[21,29,31]])
# m3
# [[ 1, 2, 3],
# [ 5, 7, 11],
# [21, 29, 31]]
inv = linalg.inv(m3) # m3의 역행렬 반환(n * n과 같은 정방행렬에 대해서만 가능)
pinv = linalg.pinv(m3) # m3의 의사역행력 반환(모든 행렬에 대해서 가능)
# Inverse & Pseudoinverse: # m3이 정방행렬인 경우 inv와 pinv의 값은 동일
# [[-2.31818182, 0.56818182, 0.02272727],
# [ 1.72727273, -0.72727273, 0.09090909],
# [-0.04545455, 0.29545455, -0.06818182]]
3. 단위 행렬과 확인- eye()
m3.dot(linalg.inv(m3)) # 원래 m3과 m3의 역행렬의 곱은 단위 행렬이 나와야 함.
# 행렬이 실수이기 때문에, 실수의 오차로 인해 완전한 단위 행렬이 나오지 않음
# [[ 1.00000000e+00, -1.66533454e-16, 0.00000000e+00],
# [ 6.31439345e-16, 1.00000000e+00, -1.38777878e-16],
# [ 5.21110932e-15, -2.38697950e-15, 1.00000000e+00]]
np.eye(3) # 크기 n이 3인 단위 행렬 반환
# [[1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.]]
4. QR 분해 - qr()
# 하나의 행렬을 직교 행렬(Q)와 상삼각 행렬(R)로 분해
m3 = np.array([[1, 2, 3],
[5, 7,11],
[21,29,31]])
q, r = linalg.qr(m3)
# q 직교 행렬
# [[-0.04627448, 0.98786672, 0.14824986],
# [-0.23137241, 0.13377362, -0.96362411],
# [-0.97176411, -0.07889213, 0.22237479]]
# r 상삼각 행렬
# [[-21.61018278, -29.89331494, -32.80860727],
# [ 0. , 0.62427688, 1.9894538 ],
# [ 0. , 0. , -3.26149699]]
q.dot(r) # linalg.qr() 으로 분해된 두 행렬을 곱하면 기존의 m3이 나옴
# [[ 1., 2., 3.],
# [ 5., 7., 11.],
# [21., 29., 31.]]
# q, r이 실수 행렬이기 때문에 실수 오차가 있을 수는 있지만 거의 동일
5. 행렬식 (Determinant) - det()
linalg.det(m3) # 행렬 m3의 행렬식 반환
# 43.99999999999997
# 44에 근사
6. 고유값 & 고유벡터 - eig()
eigenvalues, eigenvectors = linalg.eig(m3)
# eigenvalues
# [42.26600592, -0.35798416, -2.90802176]
# eigenvectors
# [[-0.08381182, -0.76283526, -0.18913107],
# [-0.3075286 , 0.64133975, -0.6853186 ],
# [-0.94784057, -0.08225377, 0.70325518]]
# m3.dot(eigenvectors) 은 eigenvalues * eigenvectors 와 근사
7. Diagonal & trace - diag(), trace()
m3 = np.array([[1, 2, 3],
[5, 7,11],
[21,29,31]])
np.diag(m3) # 왼쪽 위부터 오른쪽 아래까지의 대각선 출력
# [1, 7, 31]
m3.trace() # np.diag(m3) 의 합 출력, np.diag(m3).sum()와 동일
# 39
8. 선형방정식 풀이
coeffs = np.array([[2, 6], [5, 3]])
depvars = np.array([6, -9])
# 2x + 6y = 6
# 5x + 3y = -9
# 이 선형 방정식의 해 x, y 반환
solution = linalg.solve(coeffs, depvars)
# solution
# [-3. 2.]
# coeffs.dot(solution) 검산
# 각 방정식에 값을 대입하는 것이므로 depvars가 반환
# [6, -9]
9. 저장과 로드(Saving & Loading)
# ------------이진 형식으로 저장 및 불러오기-------------
a = np.random.rand(2,3)
a
# a
# [[0.75364614, 0.959335 , 0.28280936],
# [0.79190904, 0.20888001, 0.56242152]]
np.save("my_array", a) # my_array.npy 파일 생성됨
# save로 저장한 파일은 open으로 가져올 수 있음
with open("my_array.npy", "rb") as f:
content = f.read()
a_loaded = np.load("my_array.npy")
a_loaded
# a_loaded
# [[0.75364614, 0.959335 , 0.28280936],
# [0.79190904, 0.20888001, 0.56242152]]
# -----------텍스트 형식으로 저장 및 불러오기------------
np.savetxt("my_array.csv", a)
# a 파일의 내용을 tab을 이용해서 구분
# 7.536461424436469159e-01 9.593349967998759942e-01 2.828093592023200875e-01
# 7.919090428118645830e-01 2.088800108775373809e-01 5.624215216016786867e-01
np.savetxt("my_array.csv", a, delimiter=",")
# a 파일의 내용을 쉼표(,)을 이용해서 구분
a_loaded = np.loadtxt("my_array.csv", delimiter=",")
#a_loaded
# [[0.75364614, 0.959335 , 0.28280936],
# [0.79190904, 0.20888001, 0.56242152]])
# -------------여러 배열을 압축하여 저장--------------
b = np.arange(24, dtype=np.uint8).reshape(2, 3, 4)
# b
# [[[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]],
# [[12, 13, 14, 15],
# [16, 17, 18, 19],
# [20, 21, 22, 23]]], dtype=uint8)
np.savez("my_arrays", my_a=a, my_b=b) # my_arrays.npz 라는 파일이 생성됨
# 내부에 a는 my_a, b는 my_b라는 키(key)로 저장됨
my_arrays = np.load("my_arrays.npz")
my_arrays.keys()
# KeysView(NpzFile 'my_arrays.npz' with keys: my_a, my_b)
my_arrays["my_a"]
# [[0.75364614, 0.959335 , 0.28280936],
# [0.79190904, 0.20888001, 0.56242152]]
# 실습 문제: my_arrays에 포함된 narray b가 출력되도록 코드 작성
my_arrays["my_b"]
# [[[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]],
# [[12, 13, 14, 15],
# [16, 17, 18, 19],
# [20, 21, 22, 23]]], dtype=uint8)