AI(ML & DL)

[기계학습] Python NumPy 란 ?? ( 4 )

ch010104 2025. 3. 31. 20:06

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)