Gilbert Strang, Linear Algebra and Learning from Data, 2019. Part I — Highlights of Linear Algebra, I.8 — Singular Values and Singular Vectors in the SVD, pp. 56–70
특잇값 하나가 이 대칭행렬의 고유값 +σi,−σi 한 쌍으로 나타납니다. 나머지 m+n−2r개의 고유값은 0입니다.
행과 열을 제거하면 최대 특잇값은 커지지 않는다
부분행렬 B에 들어갈 입력을 원래 크기의 벡터에 0으로 채우고, 출력에서 필요한 성분만 선택한다고 생각하면
∥B∥2≤∥A∥2
를 얻습니다. 0을 채우는 과정은 입력 길이를 유지하고, 출력 성분을 버리는 과정은 길이를 늘리지 않기 때문입니다.
11. 교재의 확장: 미분·적분과 유한차분
벡터의 내적을 함수의 적분 내적으로 바꾸어도 직교 방향별 배율이라는 생각은 유용합니다. 교재는 [0,2π]에서 상수항을 제외한 주기적 cosine·sine 모드의 예를 듭니다. k≥1에 대해
∫0scos(kt)dt=k1sin(ks),dsdsin(ks)=kcos(ks).
정규화한 cosine 입력과 sine 출력 사이에서 적분은 1/k, 미분은 k라는 배율을 갖습니다. 적분은 높은 주파수를 작게 만들고 미분은 크게 만듭니다. 여기서는 경계·주기 조건과 함수공간을 정한 모드에 대한 설명이며, 상수까지 포함한 모든 함수에서 미분과 적분이 양쪽 역연산이라는 뜻은 아닙니다.
DTD의 고유값은 2+2,2,2−2이고, D의 양의 특잇값은 이들의 제곱근입니다. DDT는 같은 세 양의 고유값에 0 하나가 추가되며, 상수벡터가 그 영공간을 이룹니다. 대응 기저를 이산 sine·cosine 모드로 표현할 수 있어 신호 처리와 연결됩니다.
12. 교재의 확장: 극분해 A = QS
정사각 실수 행렬의 SVD에서 인수를 다시 묶으면
A=UΣVT=(UVT)(VΣVT)=QS.
Q=UVT는 직교행렬이고 S=VΣVT는 대칭 PSD입니다. 또한
S2=ATA,S=(ATA)1/2.
이 극분해는 방향을 바꾸는 부분과 대칭적으로 늘이는 부분을 분리합니다. A가 가역이면 S는 SPD이고 Q=AS−1로 유일하게 결정됩니다. 특이행렬에서는 영공간에서의 직교 작용 선택 때문에 Q가 유일하지 않을 수 있습니다. 반대쪽으로 묶는 A=KQ, K=UΣUT도 가능합니다.
13. 자유도와 데이터 분석으로의 연결
정사각 n×n 직교행렬은 n2개 성분 중 정규직교 조건 n(n+1)/2개를 만족하여 연속 자유도가 n(n−1)/2입니다. 예를 들어 2차원 회전은 각도 하나, 3차원 회전은 국소적으로 세 매개변수로 표현할 수 있습니다. 반사의 유무는 별도의 이산 선택입니다.
랭크 r 축약 SVD에서 Ur의 자유도는 mr−r(r+1)/2, Vr는 nr−r(r+1)/2, 양의 특잇값은 r개입니다. 서로 다른 특잇값을 갖는 일반적인 경우 합은
r(m+n−r)
이며, 이는 랭크 r 행렬의 자유도입니다. 중복 특잇값에서는 SVD 기저 표현의 중복 선택을 따로 고려해야 합니다.
교재가 언급하는 Karhunen–Loève 전개와 PCA도 직교 방향별 분산으로 연결됩니다. 평균이 0인 확률벡터의 공분산 C를 고유값 분해하면, 해당 기저의 좌표는 서로 무상관입니다. 일반적으로 독립까지 보장하는 것은 아니며, 결합 Gaussian 같은 추가 조건이 필요합니다. 큰 고유값의 방향부터 남기는 것이 평균 제곱 오차를 줄이는 근거가 됩니다.
14. 지정 문제 1번: 고유벡터 좌표의 에너지
대칭행렬 S의 정규직교 고유벡터를 v1,…,vn, 고유값을 λi라 하고 x=∑icivi로 씁니다. 그러면
xTx=i,j∑cicjviTvj=i∑ci2,
xTSx=i,j∑cicjλjviTvj=i∑λici2.
교차항이 사라지는 이유는 정규직교성입니다. S=ATA, λi=σi2로 놓으면 이 풀이가 바로 특잇값의 최대 배율 해석을 줍니다. 지정 문제 6번의 전체 계산은 위 5절에 있습니다.
15. NumPy로 확인하기
import numpy as np
A = np.array([[3., 4.], [0., 5.]]) U = np.array([[1., -1.], [1., 1.]]) / np.sqrt(2) s = np.array([3 * np.sqrt(5), np.sqrt(5)]) V = np.array([[1., -3.], [3., 1.]]) / np.sqrt(10) assert np.allclose(U.T @ U, np.eye(2)) assert np.allclose(V.T @ V, np.eye(2)) assert np.allclose(A @ V, U @ np.diag(s)) assert np.allclose(A, U @ np.diag(s) @ V.T) assert np.allclose(np.linalg.eigvalsh(A.T @ A), [5., 45.]) assert np.isclose(abs(np.linalg.det(A)), np.prod(s))
# NumPy returns V transpose (Vh), not V. Un, sn, Vh = np.linalg.svd(A, full_matrices=False) assert np.allclose(A, Un @ np.diag(sn) @ Vh) assert np.allclose(sn, s)
# A rectangular, rank-deficient example distinguishes economy and rank-r SVD. B = np.outer([1., 2., 3.], [1., -1.]) Ub, sb, Vhb = np.linalg.svd(B, full_matrices=False) assert Ub.shape == (3, 2) and Vhb.shape == (2, 2) tol = np.finfo(float).eps * max(B.shape) * sb[0] r = np.count_nonzero(sb > tol) assert r == 1 assert np.allclose(B, Ub[:, :r] @ np.diag(sb[:r]) @ Vhb[:r, :]) print("SVD, low-rank approximation, polar, and finite-difference checks passed.")
위 계산에서 ATA는 SVD를 유도하고 손으로 계산하기 위한 도구입니다. 실제 수치 계산에서는 np.linalg.svd(A)처럼 원래 행렬에 직접 SVD 알고리즘을 적용합니다. ATA를 먼저 만들면 열이 독립인 경우에도 2-노름 조건수가 제곱되어 작은 특잇값의 상대 정확도에 불리할 수 있습니다. 특이벡터의 부호가 위의 손계산과 달라도 재구성과 정규직교성이 맞으면 올바른 분해일 수 있습니다.
16. 복습 질문
SVD가 직사각형 행렬에도 가능한 이유를 Avi=σiui로 설명할 수 있는가?
σi=0일 때 ui=Avi/σi 대신 무엇을 해야 하는가?
ATA와 AAT의 고유값 중 일치하는 부분과 달라질 수 있는 부분은 무엇인가?
타원의 축 방향과 반축 길이는 U, V, Σ 중 어디에 들어 있는가?
랭크 축약형과 NumPy의 경제형 SVD는 언제 크기가 달라지는가?
∏iσi가 detA가 아니라 ∣detA∣인 이유는 무엇인가?
다음 Lecture 7은 교재 I.9 — Principal Components and the Best Low Rank Matrix, pp. 71–80으로 이어집니다. 아직 정리 글은 예정 상태이며 Lecture 7 원강의를 먼저 볼 수 있습니다.
참고 자료
Gilbert Strang, Linear Algebra and Learning from Data, 2019. Part I, I.8, pp. 56–70. 저자 공식 교재 페이지.