본문 바로가기

Mathematics/Linear Algebra

Eigendecomposition

<Eigendecomposition>

    1. Install Packages

    2. Geometry of Eigendecomposition

    3. Eigendecomposition

 


Install Packages

# visualization을 위한 helper code입니다.
from urllib.request import urlretrieve
URL = 'https://go.gwu.edu/engcomp4plot'
urlretrieve(URL, 'plot_helper.py')

import sys
sys.path.append('../scripts/')

# 다음 세 custom function (1)plot_vector, (2)plot_linear_transformation, (3) plot_linear_transformations
# 을 사용할 것입니다.
from plot_helper import *

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import scipy as sp
import scipy.linalg
import sympy as sy

sy.init_printing() 
np.set_printoptions(precision=3)
np.set_printoptions(suppress=True)

 


Geometry of Eigendecomposition

 

 

Eigenvectors of A = [[2, 1], [1, 2]]

 

Matrix A에 의한 vector i, j의 linear transformation 결과

A = np.array([[2,1], [1,2]])
print(A)
plot_linear_transformation(A)

Matrix A는 (1, 0) &rarr; (2, 1) / (0, 1) &rarr; (1, 2) 으로 옮기는 linear transformation

 

 

(1, 0), (0, 1) 외에 다른 vector들 linear transformation

# 길이(norm)가 1인 vector들
alpha = np.linspace(0, 2*np.pi, 41)  # x축과의 각도 (0~2pi)
vectors = list(zip(np.cos(alpha), np.sin(alpha)))
vectors = np.array(vectors)

newvectors = A @ vectors.T
newvectors = newvectors.T

plot_vector(vectors)  # plot_vector는 주어진 vector들을 plot하는 custom function 입니다.

plot_vector(newvectors)

 

→ Matrix A는 원을 타원으로 만드는 linear transformation

 

 

위 타원의 semi major axis(장축의 절반), semi minor axis(단축의 절반)

 = transform 된 newvectors의 길이가 가장 길고 짧은 두 vector

lengths = np.linalg.norm(newvectors, axis=1)  # newvectos 각각의 norm

semi_major_index = np.argmax(lengths)  # norm이 가장 긴 것이 타원의 장축
semi_major_vector = newvectors[semi_major_index]
semi_major_length = lengths[semi_major_index]

print(semi_major_vector)  # 장축 vector
print(semi_major_length)

→ 장축은 y = x 위에 있는 vector, 즉 x축과 45도를 이루는 vector

 

semi_minor_index = np.argmin(lengths)  # norm이 가장 짧은 것이 타원의 장축
semi_minor_vector = newvectors[semi_minor_index]
semi_minor_length = lengths[semi_minor_index]

print(semi_minor_vector)  # 단축 vector
print(semi_minor_length)

→ 단축은 y = -x 위에 있는 vector, 즉 x축과 -45도를 이루는 vector

 

 

두 vector (2.121, 2.121), (-0.707, 0.707)의 원래 vector 구현

A_inv = np.linalg.inv(A)
v1 = A_inv @ semi_major_vector
v2 = A_inv @ semi_minor_vector

print(v1)  # v1 -> A -> 장축
print(v2)  # v2 -> A -> 단축

  • v1과 semi major vector / v2와 semi minor vector는 각각 방향이 같다.

    (v1과 semi major vector는 y=x, v2와 semi minor vector는 y=-x 위에 존재)

  • Av1 = 3v1 / Av2 = 1v2
  • A는 원을 타원으로 바꾸는 Matrix
  • 이때, 타원의 장축, 단축이 각각 eigenvector가 된다.

→ A가 Symmetric Matrix 이기 때문에 성립

 

 

 

Scaling과 Rotation으로 A 만들기

plot_vector(vectors)

plot_vector(newvectors)

A로 만들어진 타원(newvectors)은 scaling과 rotation의 조합으로 만들 수 있어 보인다.

 

 

반지름인 1인 원(vectors)을 가로로 3배 늘린 다음, 시계 반대방향으로 45도 회전한다면?

 

가로로 3배 scaling

S = np.array([[3, 0], [0, 1]])    # 가로로 3배 scaling 하는 2x2 matrix
ellipse = (S @ vectors.T).T       # S에 의해서 늘려진 vector들.


plot_vector(ellipse)

반시계 방향으로 45도 회전

theta = np.pi/4
R = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])

rotated_ellipse = (R @ ellipse.T).T

plot_vector(rotated_ellipse)

 

  • S와 R의 linear transformation으로 생성된 조합은 A와 비슷해 보이지만 사실 다르다.

→ vector의 방향이 바뀌었기 때문

 

 

v1의 실제 변환 과정

v1 = -v1  # eigenvector에 non-zero 상수를 곱하면 여전히 eigenvector이기 때문에, -1을 곱해줍니다 (좌표를 양수로 만들기 위해)
print(v1)

scaled_v1 = (S @ v1.T).T
rotated_scaled_v1 = (R @ scaled_v1.T).T
plot_vector([v1, rotated_scaled_v1])

print(rotated_scaled_v1)

 

→ v1이 크기뿐 아니라 방향마저 바뀌었다.

∴ A ≠ RS

 

 

A의 Eigendecomposion

rotationscaling의 조합으로 A를 만드는 방법

  1. rotation을 시계방향으로 45도 회전
  2. 이를 scaling
  3. 다시 반시계 방향으로 45도 회전
theta_list = [np.pi/8, np.pi/4, np.pi/2, np.pi]

for theta in theta_list:
  R = np.array([[numpy.cos(theta), -numpy.sin(theta)],  # 반시계방향으로 45도 회전하는 matrix
                  [numpy.sin(theta), numpy.cos(theta)]])
  print(R)
  R_inv = np.linalg.inv(R)
  print(R_inv)
  print()

[[cos 𝜽, sin 𝜽], [-sin 𝜽, cos 𝜽]] = R^T

( rotation = orthogonal Matrix)

 

for theta in theta_list:
  R = np.array([[numpy.cos(theta), -numpy.sin(theta)],  # 반시계방향으로 45도 회전하는 matrix
                  [numpy.sin(theta), numpy.cos(theta)]])
  R_inv = np.linalg.inv(R)
  
  print(R.T)
  print(R_inv)
  print()

 

rotation과 scaling을 조합한 Matrix A

theta = np.pi/4
R = np.array([[np.cos(theta), -np.sin(theta)],  # 반시계방향으로 theta만큼 회전하는 matrix
              [np.sin(theta), np.cos(theta)]])
plot_linear_transformation(R @ S @ R.T)

v1, v2

 

visualize R^T (시계방향으로 45도 회전)

plot_linear_transformation(R.T, v1, v2)

visualize S (scaling)

rotated_v1 = R.T @ v1
rotated_v2 = R.T @ v2

scaled_rotated_v1 = S @ rotated_v1
scaled_rotated_v2 = S @ rotated_v2

plot_linear_transformation(S, rotated_v1, rotated_v2)

 

visualize R (반시계 방향으로 45도 회전)

rotated_scaled_rotated_v1 = R@scaled_rotated_v1
rotated_scaled_rotated_v2 = R@scaled_rotated_v2

plot_linear_transformation(R, scaled_rotated_v1, scaled_rotated_v2)
print(rotated_scaled_rotated_v1, rotated_scaled_rotated_v2)

 

v1 → 3v1 / v2 → v2가 된다.

 

결론적으로,

→ rotate(-𝜽)는 eigenvector v1, v2를 one-hot vector로 변환


Eigendecomposition

 

Symmetric Matrix

  • n x n Symmetric Matrix의 경우 항상 n개Orthogonal Eigenvector를 가질 수 있다.
F = np.random.rand(5,5)
F_symmetric = F + F.T  # A + A^T는 항상 symmetric입니다.
F_symmetric

eigenvalues, eigenvectors = np.linalg.eig(F_symmetric)
eigenvectors

from itertools import combinations
for i,j in combinations(range(5), 2):
  print(eigenvectors[:,i] @ eigenvectors[:,j])

# 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

 

모든 Eigenvector의 dot product가 0이 된다.

Symmetric Matrix로부터 n개Orthogonal Eigenvector를 얻을 수 있다.

 

 

Eigendecomposition

 

Eigendecomposition 유도

 

위 두 식을 matrix의 곱 형태로 표현

 

[s1v1, s2v2]는 다음과 같이 표현이 가능

 

V를 Eigenvector를 column으로 갖는 matrix(v1, v2)라고 하고, [[s1, 0], [0, s2]]를 D라고 하면 결론적으로,

AV = VD를 유도할 수 있다.

 

V의 역행렬이 존재할 시,

와 같은 형태로 A가 decompose 될 수 있으면, A를 diagonalizable이라고 한다.

 

 

 

V를 change of basis로 볼 시, VDV^-1의 의미

  • V^-1: standard basis ({i, j})에서 eigenbasis ({v1, v2})로 basis를 change
  • D = [[s1, 0], [0, s2]]: v1 방향의 성분 (eigenbasis에서의 좌표의 첫 번째 성분)에 s1을 곱해주고, v2 방향의 성분 (eigenbasis에서 좌표의 두 번째 성분)에 s2를 곱해준 다음, (i.e. elementwise scaling)
  • 다시 standard basis로 되돌리는 행위

'A, D가 similar 하다.'

→ 어떤 두 matrix가 같은 linear transformation을 나타내는데 basis만 다른 경우에, 두 matrix는 similar 한 관계에 있다.

 

 

 

non-Symmetric Matrix인 B = [[1, 0], [1, 3]]의 Eigendecomposition을 visualize

B = np.array([[1,0], [1,3]])
plot_eigen(B)

eigenvalues, eigenvectors = np.linalg.eig(B)
eigenvalues

eigenvectors

  • 갈색, 파란색 vector는 basis를 나타내고, 왼쪽 위의 빨간색 원은 길이가 1인 vector들의 set

    (x는 빨간색 원 위의 vector 하나하나를 표현)

  • V를 c라고 하고, v1, v2를 a, b라고 할 시(V = C, v1 = a, v2 = b), C^-1x는 standard basis에서 eigenbasis로 바꾸는 행위

    → basis i, j는 a, b로 변환, 빨간색 원은 바뀌지 않는다. 

    (∵ change of basis는 vector를 고정시킨 채 축만 바꾸기 때문에)

  • DC^-1x는 DC^-1x의 basis를 다시 standard basis로 되돌리는 행위

    → 마찬가지로 change of basis는 vector를 고정시킨 채 축만 바꾸기 때문에 빨간색 원은 바뀌지 않고, basis만 a, b는     i, j로 변환

 

 

Eigendecomposition은 Computational Advantage를 비롯해, 다양한 application에 사용된다.

'Mathematics > Linear Algebra' 카테고리의 다른 글

Advanced Eigendecomposition 2  (0) 2022.05.13
Advanced Eigendecomposition  (0) 2022.05.12
Gram-Schmidt orthonormalization & QR decomposition  (0) 2022.05.09
Determinant, Least Square  (0) 2022.05.04
Basis, Span, Change of Basis  (0) 2022.05.03