고유값 분해란 무엇인가?
고윳값 분해(Eigen Decomposition)는 정방행렬(square matrix)을 고유값(eigenvalues)과 고유벡터(eigenvectors)를 사용해 분해하는 방법이다. 고윳값 분해를 통해 행렬의 구조와 성질을 분석하고 계산을 단순화할 수 있다.
고윳값 분해 수식은 다음과 같다.
A=VΛV−1A=VΛV−1
AA: n x n 정방행렬
VV: 고유 벡터를 열벡터로 표현한 행렬
ΛΛ: 고유값을 대각 행렬로 표현한 행렬
수식을 사용한 고유값 분해
이곳에서는 다음 AA 행렬에 대한 고유값 분해를 수행한다.
A=(4123)A=(4123)
1. 고유값 구하기
고유값 분해를 위해서는 먼저 고유값을 구해야한다. 이를 위해 다음 식을 만족하는 λλ 값을 찾아보자.
det(A−λI)=0det(A−λI)=0
계산 과정은 다음과 같다.
det(4−λ123−λ)=0det(4−λ123−λ)=0
(4−λ)(3−λ)−2=λ2−7λ+10=0(4−λ)(3−λ)−2=λ2−7λ+10=0
그러면 고유값이 다음과 같이 나온다.
λ1=5,λ2=2λ1=5,λ2=2
2. 고유 벡터 구하기
이제 각 고유값에 대한 고유 벡터를 계산해보자. 먼저 5에 대한 고유벡터는 다음과 같이 계산된다.
(A−5I)v=0(A−5I)v=0
(4−5123−5)(v1v2)=(−112−2)(v1v2)=0(4−5123−5)(v1v2)=(−112−2)(v1v2)=0
그러면 고유 벡터는 다음과 같다.
v1=(11)v1=(11)
이번에는 고유값 2에 대한 고유 벡터를 구해보자. 위와 같은 방식으로 구하면 된다.
(A−2I)v=0(A−2I)v=0
(4−2123−2)(v1v2)=(2121)(v1v2)=0(4−2123−2)(v1v2)=(2121)(v1v2)=0
그러면 고유 벡터는 다음과 같아진다.
v2=(1−2)v2=(1−2)
3. 고유값 분해 실행하기
위에서 계산한 고유 벡터들로 행렬을 만들면 다음과 같아진다.
V=(111−2)V=(111−2)
그 다음 고유값을 대각 행렬로 만들면 다음과 같아진다.
Λ=(5002)Λ=(5002)
그러면 이제 고유값 분해가 완료됐다. 다음 수식을 계산해보면 좌변과 우변이 같아지는 것을 볼 수 있다.
A=VΛV−1A=VΛV−1
파이썬을 사용한 고유값 분해
Numpy를 사용한 고유값 분해
Numpy를 사용해 고유값 분해를 하기 위해서는 이전 시간에 다뤘던 linalg.eig 함수를 사용하면 된다.
이 함수를 사용해 고유값과 고유 벡터를 계산한 후, 고유값은 np.diag 함수를 통해 대각행렬로 만들면 이것이 바로 ΛΛ 가 된다.
import numpy as np
# 행렬 정의
A = np.array([[4, 1],
[2, 3]])
# 고유값과 고유벡터 계산
eigenvalues, V = np.linalg.eig(A)
# 대각 행렬 Λ 생성
Lambda = np.diag(eigenvalues)
# 고유벡터의 역행렬 계산
V_inv = np.linalg.inv(V)
# A 재구성
A_reconstructed = V @ Lambda @ V_inv
print("원래 행렬 A:\n", A)
print("재구성된 행렬 A:\n", A_reconstructed)
이제 이 코드를 실행해보면 다음과 같은 결과를 얻을 수 있다.

TensorFlow를 사용한 고유값 분해
TensorFlow를 사용해 고유값 분해를 할 때도 tensorflow 패키지의 linalg.eig 함수를 사용하면 된다.
이 함수를 사용해 고유값과 고유 벡터를 계산한 후, linalg.diag 함수를 통해 고유값들(eigenvalues)을 대각행렬로 만들면 이것이 바로 ΛΛ 가 된다.
import tensorflow as tf
# 행렬 정의
A = tf.constant([[4, 1],
[2, 3]], dtype=tf.float32)
# 고유값과 고유벡터 계산
eigenvalues, V = tf.linalg.eig(A)
# 대각 행렬 Λ 생성
Lambda = tf.linalg.diag(eigenvalues)
# 고유벡터의 역행렬 계산
V_inv = tf.linalg.inv(V)
# A 재구성
A_reconstructed = tf.matmul(tf.matmul(V, Lambda), V_inv)
print("원래 행렬 A:\n", A)
print("재구성된 행렬 A:\n", A_reconstructed)
코드를 실행해보면 같은 결과가 나오는 것을 볼 수 있다.

PyTorch를 사용한 고유값 분해
PyTorch를 사용해 고유값 분해를 할 때는 torch.linalg.eig 함수를 사용하면 된다. 1.9버전 미만에서는 torch.eig 함수를 사용했던 것 같은데, 최신 버전에서는 torch.linalg.eig을 사용하면 되도록 바꼈다.
이 함수를 사용해 고유값과 고유 벡터를 계산한 후, diag 함수를 통해 고유값들(eigenvalues)을 대각행렬로 만들면 이것이 바로 ΛΛ 가 된다.
import torch
# 행렬 정의
A = torch.tensor([[4, 1],
[2, 3]], dtype=torch.float)
# 고유값과 고유벡터 계산
eigenvalues, V = torch.linalg.eig(A)
# 대각 행렬 Λ 생성
Lambda = torch.diag(eigenvalues)
# 고유벡터의 역행렬 계산
V_inv = torch.inverse(V)
# A 재구성
A_reconstructed = torch.mm(torch.mm(V, Lambda), V_inv)
print("원래 행렬 A:\n", A)
print("재구성된 행렬 A:\n", A_reconstructed)
코드를 실행해보면 예상한 것과 같은 결과가 나오는 것을 볼 수 있다.
