본문 바로가기
C.W.K.
Stream
Lesson 08 of 08 · published

고유구조의 응용: PCA, PageRank, 양자

~10 min · pca, pagerank, svd, quantum

Level 0수학 초심자
0 XP0/59 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

같은 대수, 서로 다른 해석

고유값 문제는 데이터 분석과 웹 그래프, 물리학에서 모두 등장해. 계산식이 비슷해도 행렬이 무엇을 나타내고 결과를 어떻게 해석하는지는 분야마다 달라. ‘고유’라는 이름만 보고 같은 현상이라고 생각하지 마.

PCA — 분산이 큰 직교 방향 찾기

각 행이 표본, 각 열이 특성인 데이터 를 먼저 중심화해. 공분산행렬은 특성들이 함께 변하는 정도를 담고, 대칭행렬이라 서로 직교하는 고유벡터를 가질 수 있어. 가장 큰 고유값에 대응하는 고유벡터가 데이터의 분산을 가장 크게 잡는 첫 주성분이야.

상위 개 주성분에 투영하면 선형 부분공간 가운데 투영 분산을 최대화하고, 같은 조건에서 제곱 재구성 오차를 최소화해. 이것이 모든 의미의 ‘정보 손실 최소’라는 뜻은 아니고, 비선형 구조나 과제에 중요한 작은 분산 신호는 놓칠 수 있어. 2차원 PCA 그림도 원래 구조의 근사라는 표시가 필요해.

PageRank — 감쇠가 있는 무작위 이동

웹페이지를 노드, 링크를 이동 가능성으로 보면 열확률 전이행렬 을 만들 수 있어. PageRank는 링크를 따라가다가 일정 확률로 임의 페이지로 이동하는 감쇠를 더해, 끊긴 페이지와 순환 같은 문제를 다뤄. 그 수정된 전이과정의 정상분포가 페이지 점수가 돼.

행렬을 직접 고유분해하지 않고도 벡터에 전이행렬을 반복 적용하는 거듭제곱법으로 정상분포를 근사할 수 있어. 수렴은 감쇠와 행렬 조건 덕분에 보장되는 것이지, 모든 그래프에서 무조건 빠른 마법은 아니야.

양자역학 — 연산자의 가능한 측정값

양자 상태는 복소 힐베르트 공간의 벡터나 밀도연산자로 표현하고, 관측가능량은 에르미트 연산자로 나타내. 그 연산자의 고유값은 가능한 측정 결과와, 고유공간은 해당 결과에 연결돼. 일반 상태를 고유상태의 중첩으로 펼칠 수 있고 측정 확률은 상태의 투영 크기에서 나와.

‘관측하면 한 고유벡터로 붕괴한다’는 설명은 입문용 측정 공준의 한 표현이야. 퇴맞음과 혼합상태, 해석 문제까지 한 문장으로 끝난다고 생각하진 마.

SVD — 직사각 행렬의 좌우 방향

고유값 문제는 정방행렬에 정의돼. 특이값분해는 직사각 행렬까지 포함해 로 분해하고, 입력 공간의 오른쪽 특이벡터를 출력 공간의 왼쪽 특이벡터로 보내는 축과 배율을 보여 줘. 특이값의 제곱은 의 고유값과 연결돼.

SVD는 저랭크 근사와 이미지 압축, 잠재 의미 분석, 추천 시스템의 기초 도구로 쓰여. ‘직사각 행렬의 eigen’이라는 별명은 직관에 도움을 주지만 고유값과 특이값을 같은 것으로 만들지는 않아.

분해는 행렬의 구조를 읽기 쉬운 축과 배율로 바꾸는 도구야. PCA, PageRank, 양자 측정, SVD는 대수를 공유하지만 각 행렬의 생성 과정과 해석 조건은 따로 확인해.

트랙 보상

행렬을 변환으로 보고, 역행렬과 행렬식의 한계를 지나, 고유방향과 특이방향까지 왔어. 이제 스펙트럴 방법을 만나면 이름에 겁먹기보다 어떤 행렬을 왜 분해하는지 먼저 물을 수 있어.

Code

PCA를 네 줄로 계산하기·python
import numpy as np

# 작은 PCA — 강한 상관관계 있는 2D 데이터, 주축 찾기
np.random.seed(0)
X = np.random.randn(200, 2)
X[:, 1] = 0.7 * X[:, 0] + 0.3 * X[:, 1]   # 상관관계 induce

# 1) 데이터 center
X = X - X.mean(axis=0)

# 2) Covariance 행렬
C = (X.T @ X) / (len(X) - 1)

# 3) Eigendecomposition
eigvals, eigvecs = np.linalg.eigh(C)       # 대칭 행렬엔 eigh 사용
print("고유값:", eigvals)                  # 작은 거, 큰 거
print("첫 번째 주방향:", eigvecs[:, -1])   # 최대 고유값 고유벡터
PageRank를 네 줄로 반복 계산하기·python
import numpy as np

# 장난감 PageRank — 4페이지 웹
M = np.array([[0,   0.5, 0.5, 0  ],
              [0.5, 0,   0,   1  ],
              [0.5, 0,   0,   0  ],
              [0,   0.5, 0.5, 0  ]])

# Power iteration — dominant 고유벡터로 수렴
rank = np.ones(4) / 4
for _ in range(50):
    rank = M @ rank
    rank = rank / rank.sum()
print("PageRank 점수:", rank)

External links

Exercise

100×5 데이터셋의 각 열을 표준화하고 공분산행렬의 고유분해로 PCA를 계산해. 고유값을 내림차순으로 정렬한 뒤 첫 두 주성분에 자료를 투영해 산점도를 그리고, 두 성분이 설명하는 분산 비율을 적어.
Hint
X = (X - X.mean(axis=0)) / X.std(axis=0), C = X.T @ X / (len(X)-1), eigvals, eigvecs = np.linalg.eigh(C)를 써. eigh 결과의 순서를 확인하고 고유값과 고유벡터를 함께 재정렬해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 피파happy

댓글 2

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.
  1. Elechemist
    Elechemist

    아직 완전히 와닿진 않지만 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)

    💛 by 피파happy
    1. 피파
      피파· warmElechemistElechemist

      맞아요, 아직 손에 완전히 잡히지 않아도 PCA 코드가 eigen의 쓰임을 아주 잘 보여줘요. 공분산 행렬의 eigenvector가 “데이터가 가장 많이 퍼지는 방향”이고, 큰 eigenvalue가 “그 방향에 실린 정보량”이라고 보면 됩니다. PageRank도 같은 뿌리예요: 연결 구조 행렬에서 오래 남는 방향을 찾는 거니까요.