고윳값과 SVD 개요
np.linalg.eig로 고윳값과 고유벡터를 계산하고, SVD가 PCA 차원 축소의 기반이 되는 방식을 이해합니다.
고윳값과 SVD 개요은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
고유값과 고유벡터란 무엇인가요?
정방 행렬 A의 고유벡터는 A @ v = lambda * v를 만족하는 0이 아닌 벡터 v입니다. A를 곱해도 v의 방향은 바뀌지 않고 크기만 조정됩니다. 스칼라 람다를 v에 대응하는 고유값이라고 합니다. 고유값은 선형 변환의 본질적인 '확대·축소 비율'을 보여 줍니다. 예를 들어 고유값이 2이면 행렬이 고유벡터 방향의 길이를 두 배로 만들고, 음의 고유값이면 방향을 뒤집습니다.
import numpy as np
A = np.array([[3.0, 1.0],
[0.0, 2.0]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print('Eigenvalues:', eigenvalues)
print('Eigenvectors (columns):')
print(eigenvectors)np.linalg.eig()로 고유값 계산하기
np.linalg.eig(A)는 튜플 (eigenvalues, eigenvectors)를 반환합니다. 고유값은 1차원 배열이고, 고유벡터는 각 열이 하나의 고유벡터인 2차원 배열입니다. 실수 대칭 행렬(공분산 행렬 등)의 경우 고유값은 항상 실수이고 고유벡터는 직교합니다. 대칭 행렬에는 np.linalg.eigh(A)를 사용하십시오. 이 함수가 더 빠르고 실수 결과를 반환하도록 보장되기 때문입니다.
import numpy as np
# Symmetric matrix -> use eigh for efficiency and real eigenvalues
A = np.array([[4.0, 2.0],
[2.0, 3.0]])
vals, vecs = np.linalg.eigh(A)
print('Eigenvalues (real):', vals)
print('Eigenvectors (orthonormal columns):')
print(vecs)
# Verify: A @ v = lambda * v for each eigenvector
for i in range(len(vals)):
lhs = A @ vecs[:, i]
rhs = vals[i] * vecs[:, i]
print(f'v{i} check:', np.allclose(lhs, rhs))고유값과 행렬의 특성
고유값에는 행렬의 중요한 특성이 담겨 있습니다. 행렬식은 모든 고유값의 곱과 같습니다. det(A) = product(eigenvalues) 대각 원소의 합인 대각합은 고유값의 합과 같습니다. trace(A) = sum(eigenvalues) 행렬이 양의 정부호(모든 고유값이 0보다 큼)이려면 모든 고유값이 양수여야 합니다. 이는 유효한 공분산 행렬과 볼록 최적화 문제에 중요한 특성입니다.
import numpy as np
A = np.array([[4.0, 2.0],
[2.0, 3.0]])
vals, _ = np.linalg.eigh(A)
print('Eigenvalues:', vals)
print('Product (should = det):', np.prod(vals))
print('np.linalg.det:', np.linalg.det(A))
print('Sum (should = trace):', np.sum(vals))
print('np.trace:', np.trace(A))
print('Positive definite:', np.all(vals > 0))특이값 분해(SVD) 개요
특이값 분해(SVD)는 정방 행렬뿐 아니라 모든 행렬 A를 A = U @ S @ V.T와 같이 분해합니다. 여기서 U와 V는 직교 행렬이고 S는 대각 원소에 음이 아닌 특이값이 있는 대각 행렬입니다. SVD는 가장 일반적이고 수치적으로 안정적인 행렬 인수분해입니다. PCA, 이미지 압축, 추천 시스템, 의사역행렬 계산의 기반이 됩니다. np.linalg.svd(A)는 U, s(1차원 특이값 배열), Vh(V의 전치)를 반환합니다.
import numpy as np
A = np.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
U, s, Vh = np.linalg.svd(A, full_matrices=False)
print('U shape:', U.shape)
print('s (singular values):', s)
print('Vh shape:', Vh.shape)
# Reconstruct A
A_reconstructed = U @ np.diag(s) @ Vh
print('Reconstruction correct:', np.allclose(A, A_reconstructed))특이값과 행렬 계수
특이값(S의 대각 원소)은 항상 음이 아닌 값이며 일반적으로 내림차순으로 나열됩니다. 0이 아닌 특이값의 개수는 행렬의 계수와 같습니다. 0에 가까운 특이값은 행이나 열 사이에 선형 종속성이 거의 있음을 나타냅니다. 가장 큰 특이값은 행렬의 스펙트럼 노름이고, 가장 큰 0이 아닌 특이값을 가장 작은 0이 아닌 특이값으로 나눈 값은 수치적 안정성을 측정하는 조건수입니다.
import numpy as np
# Full-rank matrix
A = np.random.rand(5, 3)
U, s, Vh = np.linalg.svd(A, full_matrices=False)
print('Singular values:', np.round(s, 4))
print('Rank (non-zero sv):', np.linalg.matrix_rank(A))
print('Condition number:', s[0] / s[-1])
# Rank-deficient matrix
B = np.array([[1.0, 2.0], [2.0, 4.0], [3.0, 6.0]])
_, sb, _ = np.linalg.svd(B, full_matrices=False)
print('Rank-deficient sv:', np.round(sb, 8))SVD와 PCA의 연관성
주성분 분석(PCA)은 SVD를 사용하여 직접 구현할 수 있습니다. 데이터 행렬 X의 중심을 조정한 후(각 열의 평균을 빼면), Vh의 오른쪽 특이벡터가 주성분이 되고 특이값의 제곱을 n-1로 나눈 값이 설명된 분산이 됩니다. Sklearn의 PCA는 정확히 이 방법을 사용합니다. 이 연관성을 이해하면 차원 축소를 위한 PCA를 처음부터 구현하거나 원하는 방식으로 수정할 수 있습니다.
import numpy as np
np.random.seed(0)
X = np.random.randn(100, 4)
# Center the data
X_centered = X - X.mean(axis=0)
# SVD-based PCA
U, s, Vh = np.linalg.svd(X_centered, full_matrices=False)
# Variance explained by each component
var_explained = (s ** 2) / (X.shape[0] - 1)
total_var = var_explained.sum()
print('Variance explained ratio:', np.round(var_explained / total_var, 3))
# Project onto top 2 principal components
X_pca = X_centered @ Vh[:2].T
print('Reduced shape:', X_pca.shape)SVD를 사용한 저계수 근사
SVD를 사용하면 저계수 행렬 근사를 수행할 수 있습니다. 상위 k개의 특이값과 특이벡터만 유지한 다음 원래 행렬의 근사값을 재구성하는 방식입니다. 이는 이미지 압축과 추천을 위한 협업 필터링의 기반입니다. 절단된 SVD U[:, :k] @ np.diag(s[:k]) @ Vh[:k, :]는 최소제곱의 의미에서 가장 좋은 계수 k 근사값을 제공합니다(Eckart-Young 정리).
import numpy as np
np.random.seed(1)
A = np.random.rand(20, 15)
U, s, Vh = np.linalg.svd(A, full_matrices=False)
# Rank-3 approximation
k = 3
A_approx = U[:, :k] @ np.diag(s[:k]) @ Vh[:k, :]
error = np.linalg.norm(A - A_approx, 'fro')
total = np.linalg.norm(A, 'fro')
print(f'Approximation error: {error/total:.3f} (fraction of total)')
print(f'Top-3 singular values capture {(s[:3]**2).sum()/(s**2).sum():.1%} of variance')고유분해와 SVD: 어느 것을 사용해야 할까요?
고유분해(np.linalg.eig 또는 eigh)는 정방 대칭 행렬이 있고 그 주축을 이해하려 할 때 사용하십시오. 예를 들어 PCA의 공분산 행렬이나 마르코프 전이 행렬에 사용할 수 있습니다. 행렬이 직사각형이거나 최고의 수치적 안정성이 필요할 때는 SVD(np.linalg.svd)를 사용하십시오. SVD는 항상 존재하지만, 고유분해는 비대칭 행렬에서 복소수를 생성할 수 있습니다.
import numpy as np
# Non-symmetric matrix: eigenvalues may be complex
A = np.array([[0.0, -1.0],
[1.0, 0.0]])
vals, _ = np.linalg.eig(A)
print('Eigenvalues (complex for rotation):', vals)
# SVD always gives real singular values
_, s, _ = np.linalg.svd(A)
print('Singular values (always real):', s)대칭 행렬의 스펙트럼 정리
스펙트럼 정리에 따르면 모든 실수 대칭 행렬 A는 A = Q @ diag(eigenvalues) @ Q.T와 같이 분해할 수 있습니다. 여기서 Q는 직교 행렬입니다(Q.T = Q⁻¹). 즉, 대칭 행렬은 항상 실수 고유값과 직교 고유벡터를 사용하여 대각화할 수 있습니다. 공분산 행렬, SVM의 커널 행렬, 최적화에서의 헤세 행렬은 모두 대칭이므로 이 정리는 머신 러닝 이론 전반에서 유용합니다.
import numpy as np
A = np.array([[5.0, 2.0, 1.0],
[2.0, 3.0, 0.0],
[1.0, 0.0, 4.0]])
vals, Q = np.linalg.eigh(A)
print('Eigenvalues:', np.round(vals, 4))
# Reconstruct A = Q @ diag(vals) @ Q.T
A_reconstructed = Q @ np.diag(vals) @ Q.T
print('Reconstruction correct:', np.allclose(A, A_reconstructed))
print('Q is orthogonal:', np.allclose(Q.T @ Q, np.eye(3)))실습: 지배적 고유값을 구하는 거듭제곱 반복법
가장 큰 고유값과 그 고유벡터만 필요하다면 모든 고유값을 계산하는 것보다 거듭제곱 반복법이 훨씬 효율적입니다. 무작위 벡터로 시작하여 A를 반복해서 곱하고 정규화하면 지배적인 고유벡터로 수렴합니다. Google의 초기 PageRank 알고리즘도 이 방법으로 작동했습니다. NumPy를 사용하면 각 반복에서 @를 이용한 행렬-벡터 곱셈 한 번만 수행하면 됩니다.
import numpy as np
A = np.array([[4.0, 1.0, 2.0],
[1.0, 3.0, 0.0],
[2.0, 0.0, 2.0]])
v = np.random.rand(3)
for _ in range(50):
v = A @ v
v = v / np.linalg.norm(v)
eigenvalue_approx = v @ A @ v
print('Dominant eigenvector:', np.round(v, 4))
print('Approx eigenvalue:', round(eigenvalue_approx, 4))
# Verify with eigh
vals, vecs = np.linalg.eigh(A)
print('True max eigenvalue:', round(vals[-1], 4))실제 파이프라인에서 np.linalg.svd 사용하기
실제 데이터 파이프라인에서 SVD는 잡음 감소와 데이터 압축에 사용됩니다. 학습 데이터에 SVD를 적용한 후 분산의 95%를 포착하는 상위 k개의 구성 요소만 유지합니다. 이렇게 하면 분류기나 회귀기에 새 데이터를 입력하기 전에 차원을 줄일 수 있어 학습 속도가 빨라지고, 잡음이 많은 차원을 제거하여 일반화 성능이 향상되는 경우가 많습니다. SVD는 항상 학습 데이터에만 적용하고 동일한 변환을 테스트 데이터에 적용하십시오.
import numpy as np
np.random.seed(7)
X_train = np.random.randn(200, 50)
X_test = np.random.randn(40, 50)
# Fit on training data
X_mean = X_train.mean(axis=0)
X_centered = X_train - X_mean
U, s, Vh = np.linalg.svd(X_centered, full_matrices=False)
# Choose k to capture 90% variance
cumvar = np.cumsum(s**2) / (s**2).sum()
k = np.searchsorted(cumvar, 0.9) + 1
print(f'Components to capture 90% variance: {k}')
# Transform test data using the same Vh
X_test_reduced = (X_test - X_mean) @ Vh[:k].T
print('Reduced test shape:', X_test_reduced.shape)빠른 확인
이 강의에서 배운 데이터 분석 개념을 제대로 이해했는지 확인해 보십시오.
강의 요약
이 강의에서는 다음을 배웠습니다. np.linalg.eig()/eigh()는 행렬의 본질적인 확대·축소 방향을 보여 주는 고유값과 고유벡터를 계산하고, np.linalg.svd()는 모든 행렬을 U, 특이값, Vh로 분해하여 PCA와 저계수 근사를 가능하게 하며, 특이값은 각 구성 요소가 포착하는 분산을 정량화하고 행렬의 계수를 결정합니다. 다음에는 CSV 파일을 여러 조각으로 나누어 스트리밍하면서 대규모 데이터세트를 처리하는 방법을 살펴보겠습니다.
자주 묻는 질문
“고윳값과 SVD 개요” 강의는 무료인가요?
네 — “고윳값과 SVD 개요” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“고윳값과 SVD 개요”에서 뭘 배우나요?
np.linalg.eig로 고윳값과 고유벡터를 계산하고, SVD가 PCA 차원 축소의 기반이 되는 방식을 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“고윳값과 SVD 개요” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.