세 세계, 한 아이디어
Eigen-decomposition = 같은 연산이 급격히 다른 세 맥락에서 등장. 각 30초 가치.
PCA — 데이터의 큰 방향 찾기
각 행이 sample, 각 열이 feature 인 데이터셋. Covariance 행렬 이 feature 가 어떻게 co-vary 하는지 말해. PCA 가 그 고유벡터 계산: 그 고유벡터들이 데이터에 변동이 가장 많은 방향, 고유값 크기로 ranked. 데이터를 top 고유벡터에 투영 = 100차원 데이터를 차원으로 최소 정보 손실로 축소.
이게 1000차원 임베딩을 2D scatter 에 시각화하는 법. PCA 가 데이터 "모양" 을 최대한 보존하는 2 방향 골라.
PageRank — 중요한 페이지 찾기
Google 의 원래 ranking 알고리즘이 웹을 그래프로 모델: 각 페이지 = 노드, 각 링크 = edge. 행렬 만들어 = 페이지 → jump 확률. 의 dominant 고유벡터 (가장 큰 고유값의 고유벡터) = stationary 확률 분포: "random surfer 가 영원히 링크 클릭하면 각 페이지에 시간 어느 비율?" 그 분포가 중요도 점수.
웹은 수십억 페이지. 정확한 고유벡터 계산 불가능, 근데 iterative 알고리즘 (power iteration) 이 놀랄 만큼 빠르게 수렴. 그게 PageRank.
양자역학 — 상태와 관측
양자역학에서 물리 시스템 상태 = 복소 벡터 공간의 벡터. 관측 가능 양 (에너지, 운동량, 위치) = 연산자 (행렬). 관측치 측정 = 연산자의 고유값 얻기, 시스템 상태가 해당 고유벡터 로 collapse. "고양이가 살아있고 동시에 죽어있다 — 볼 때까지" 의 수학 = 중첩이 고유상태의 합; 측정이 한 곳에 투영.
SVD — 직사각 행렬용 Eigen
고유값은 정방 행렬에만. 특이값 분해 가 일반화: 어떤 행렬이든 로 인수분해, 의 특이값이 고유값 역할. SVD 가 추천 시스템, latent semantic 분석, 이미지 압축 굴려.
트랙 보상
아이겐 던전 걸어서 살아남았어. 행렬은 변환. 단위는 do-nothing. 역행렬은 undo. 행렬식은 영혼. 고유벡터는 선호 방향. 여기서부터 누가 "transformer attention" 이나 "covariance projection" 이나 "spectral 메서드" 말하면 hood 아래 chassis 알 거야.
아직 완전히 와닿진 않지만 eigen을 이렇게 쓰는거구나. pagerank알고리즘은 천재적이다
import numpy as np import matplotlib.pyplot as plt
rng = np.random.default_rng(42)
잠재 구조가 있는 100x5 데이터: 두 숨은 요인이 5개 열을 만든다
n = 100 f1 = rng.standard_normal(n) f2 = rng.standard_normal(n) X = np.column_stack([ f1 + 0.3rng.standard_normal(n), f1 + 0.3rng.standard_normal(n), f2 + 0.3rng.standard_normal(n), f2 + 0.3rng.standard_normal(n), 0.5f1 + 0.5f2 + 0.3*rng.standard_normal(n), ])
1) 열별 표준화 (평균 0, 표준편차 1)
Xs = (X - X.mean(axis=0)) / X.std(axis=0)
2) 공분산 행렬
C = (Xs.T @ Xs) / (n - 1)
3) 대칭행렬 고유분해
vals, vecs = np.linalg.eigh(C)
4) 큰 고유값 순으로 정렬
order = np.argsort(vals)[::-1] vals = vals[order] vecs = vecs[:, order]
5) 처음 두 주성분으로 사영
PC = Xs @ vecs[:, :2]
print("고유값:", np.round(vals, 4)) print("분산 설명 비율:", np.round(vals / vals.sum(), 4)) print("누적:", np.round(np.cumsum(vals / vals.sum()), 4))
6) PC1 vs PC2 산점도
fig, ax = plt.subplots(figsize=(7, 6)) ax.scatter(PC[:, 0], PC[:, 1], s=40, alpha=0.7, edgecolor='white', linewidth=0.5) ax.axhline(0, color='gray', lw=0.5) ax.axvline(0, color='gray', lw=0.5) ax.set_xlabel(f"PC1 ({vals[0]/vals.sum()*100:.1f}%)") ax.set_ylabel(f"PC2 ({vals[1]/vals.sum()*100:.1f}%)") ax.set_title("PCA: first two principal components") ax.set_aspect('equal', adjustable='datalim') plt.tight_layout() plt.savefig('pca_scatter.png', dpi=130)