Ch.6 §6.7 — 특이값 분해 (Singular Value Decomposition, SVD)

모든 행렬을 분해하는 선형대수의 클라이맥스 — A = UΣVᵀ의 구조·직관·응용

SVD는 정방행렬뿐 아니라 임의의 m×n 행렬을 세 직교/대각 행렬의 곱으로 완전히 분해한다. 고유값 분해의 한계를 극복하고, 네 가지 기본 부분공간에 직교정규 기저를 동시에 제공한다. 이미지 압축·PCA·추천 시스템·의사역행렬 등 현대 데이터 사이언스의 핵심 도구임을 수식과 직관으로 설명한다.

Math
Linear Algebra
저자

Kwangmin Kim

공개

2026년 04월 11일

1 왜 SVD가 필요한가 — 고유값 분해의 한계

현실에서 만나는 데이터 행렬 \(\mathbf{X} \in \mathbb{R}^{1000 \times 50}\) (1000명의 사용자, 50개의 특성)을 생각해보자. 이 행렬은 정방 행렬이 아니므로 고유값 분해를 적용할 수 없다. 억지로 정방 행렬을 만들어 고유값 분해를 시도해도, 고유벡터가 직교한다는 보장이 없어 기하학적 의미를 해석하기 어렵다. 실무에서 다루는 행렬의 대부분은 직사각형이고, 고유값 분해는 이 사실 앞에서 멈춰선다.

고유값 분해 \(\mathbf{A} = \mathbf{S} \mathbf{\Lambda} \mathbf{S}^{-1}\) 는 강력하지만 세 가지 본질적 한계를 갖는다.

한계 내용 결과
직교성 없음 고유벡터가 직교하지 않을 수 있다 기하학적 해석이 어렵다
벡터 부족 결함 행렬(defective matrix)은 \(n\) 개 독립 고유벡터가 없다 대각화 불가
정방 행렬만 \(\mathbf{A}\mathbf{x} = \lambda \mathbf{x}\) 는 정방 행렬이어야 한다 데이터 행렬(직사각형)에 적용 불가

SVD는 이 세 가지 문제를 완벽하게 해결한다. \(m \times n\) 임의 행렬에 대해, 두 개의 직교 행렬 \(\mathbf{U}\), \(\mathbf{V}\) 와 대각 행렬 \(\mathbf{\Sigma}\) 로 분해한다. Strang은 SVD를 “선형대수 강의의 클라이맥스”라 불렀다 — 이 분해 하나가 네 가지 기본 부분공간의 차원·직교성·직교정규 기저를 동시에 해결하기 때문이다 (Strang, 2009, Ch.6.7).

더 근본적인 이유가 있다. SVD는 지금까지 배운 모든 것을 한 장면에 모은다:

  • Ch.2 소거법 이 “\(\mathbf{A}\mathbf{x} = \mathbf{b}\)를 어떻게 푸는가”를 물었다면,
  • Ch.3 부분공간 은 “해가 어디에 사는가”를 물었고,
  • Ch.4 직교성 은 “해가 얼마나 떨어져 있는가”를 물었다.
  • Ch.5 행렬식 & Ch.6 고유값 은 “행렬이 어떻게 작용하는가”를 물었다.

SVD는 이 질문들에 하나의 그림 으로 동시에 답한다: 모든 행렬은 직교 기저 \(\{\mathbf{v}_i\}\) 를 받아 직교 기저 \(\{\mathbf{u}_i\}\) 로, 각각 \(\sigma_i\) 배 늘려 보낸다. 그뿐이다. 이 한 문장이 데이터 압축, 차원 축소, 최소제곱, 추천 시스템, 딥러닝의 가중치 분석까지 — 현대 데이터 과학의 거의 모든 알고리즘이 뿌리내린 토대다.


2 특이값 분해 (SVD) 정의

정의: 특이값 분해 (Singular Value Decomposition)

\(m \times n\) 행렬 \(\mathbf{A}\) (rank \(r\))에 대해 다음 분해가 항상 존재한다:

\[\mathbf{A} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^\top\]

  • \(\mathbf{U}\): \(m \times m\) 직교 행렬 — 열벡터 \(\mathbf{u}_1, \ldots, \mathbf{u}_m\) (left singular vectors)
  • \(\mathbf{\Sigma}\): \(m \times n\) 대각 행렬 — 대각 원소 \(\sigma_1 \geq \sigma_2 \geq \cdots \geq \sigma_r > 0\) (singular values)
  • \(\mathbf{V}\): \(n \times n\) 직교 행렬 — 열벡터 \(\mathbf{v}_1, \ldots, \mathbf{v}_n\) (right singular vectors)

\[\mathbf{\Sigma} = \begin{bmatrix} \sigma_1 & & & \\ & \ddots & & \mathbf{0} \\ & & \sigma_r & \\ & \mathbf{0} & & \mathbf{0} \end{bmatrix}_{m \times n}\]

핵심 관계는 열벡터 단위로 보면 명확해진다:

\[\mathbf{A} \mathbf{v}_i = \sigma_i \mathbf{u}_i \quad (i = 1, \ldots, r)\]

이것이 SVD의 본질이다. \(\mathbf{v}_i\) (행 공간의 기저)를 \(\mathbf{A}\) 에 곱하면 \(\mathbf{u}_i\) (열 공간의 기저) 방향으로 \(\sigma_i\) 배 늘어난다.


3 기하학적 직관 — V^T → Σ → U

직관: SVD는 세 단계의 기하학적 변환이다

\[\mathbf{x} \xrightarrow{\mathbf{V}^\top} \text{(회전·반전)} \xrightarrow{\mathbf{\Sigma}} \text{(축 방향 신축)} \xrightarrow{\mathbf{U}} \text{(회전·반전)}\]

임의의 행렬 \(\mathbf{A}\) 는 아무리 복잡해 보여도, 결국 회전 → 신축 → 회전 세 단계로 분해된다.

비유: 찰흙 덩어리를 특정 방향으로 눌러 납작하게 만드는 과정을 떠올려보자.

  1. \(\mathbf{V}^\top\) (첫 번째 회전): 찰흙을 특정 기준 방향(좌표축)에 맞게 돌린다
  2. \(\mathbf{\Sigma}\) (신축): 각 축 방향으로 정해진 비율만큼 누르거나 늘린다 — \(\sigma_1\)이 가장 강하게, \(\sigma_r\)이 가장 약하게
  3. \(\mathbf{U}\) (두 번째 회전): 결과물을 최종 방향으로 다시 회전한다

어떤 선형 변환도 이 세 단계로 분해할 수 있다. “복잡한 변환”은 없다 — 다만 회전과 신축의 조합일 뿐이다.

2D에서 단위원에 \(\mathbf{A}\) 를 곱하면 타원이 된다:

  • \(\mathbf{V}^\top\): 단위원 위의 점들을 회전하여 \(\mathbf{v}_i\) 방향을 좌표축에 맞춘다
  • \(\mathbf{\Sigma}\): 각 축 방향으로 \(\sigma_1, \sigma_2, \ldots\) 배 신축한다 → 타원
  • \(\mathbf{U}\): 타원을 다시 최종 방향으로 회전한다

\(\sigma_1 \geq \sigma_2 \geq \cdots\) 이므로 \(\sigma_1\) 방향이 가장 많이 늘어난다. 이것이 가장 중요한 방향 이다.

결정적 관찰: 타원의 반축(semi-axis) = \(\sigma_i \mathbf{u}_i\)

단위원 \(\{\mathbf{x} : \|\mathbf{x}\| = 1\}\) 의 이미지 \(\mathbf{A}\{\mathbf{x}\}\)타원(또는 고차원의 초타원체)이다. 이 타원의:

  • 장축 방향: \(\mathbf{u}_1\) (첫 번째 left singular vector)
  • 장축 반지름: \(\sigma_1\)
  • 단축 방향: \(\mathbf{u}_2\)
  • 단축 반지름: \(\sigma_2\)

즉 특이값 \(\sigma_i\) 는 타원의 \(i\)번째 반축 길이이고, \(\mathbf{u}_i\) 는 그 축 방향이다. 반면 \(\mathbf{v}_i\) 는 “원래 단위원에서 어느 방향의 벡터가 타원의 \(i\)번째 축 끝으로 가는가”를 알려준다.

이 한 문장 — “원은 타원이 된다” — 이 SVD의 기하학적 전부다.


4 네 가지 기본 부분공간과 SVD

SVD의 가장 심오한 결과는 네 가지 기본 부분공간에 직교정규 기저를 동시에 제공한다는 것이다.

행렬 열벡터 부분공간
\(\mathbf{V}\) 의 첫 \(r\) \(\mathbf{v}_1, \ldots, \mathbf{v}_r\) 행 공간 \(C(\mathbf{A}^\top) \subset \mathbb{R}^n\)
\(\mathbf{V}\) 의 마지막 \(n-r\) \(\mathbf{v}_{r+1}, \ldots, \mathbf{v}_n\) 영공간 \(N(\mathbf{A}) \subset \mathbb{R}^n\)
\(\mathbf{U}\) 의 첫 \(r\) \(\mathbf{u}_1, \ldots, \mathbf{u}_r\) 열 공간 \(C(\mathbf{A}) \subset \mathbb{R}^m\)
\(\mathbf{U}\) 의 마지막 \(m-r\) \(\mathbf{u}_{r+1}, \ldots, \mathbf{u}_m\) 좌영공간 \(N(\mathbf{A}^\top) \subset \mathbb{R}^m\)
SVD와 선형대수 기본정리의 완성

Ch.3에서 네 부분공간의 차원 을 다뤘다. Ch.4에서 부분공간의 직교성 을 다뤘다. Ch.6.7 SVD에서 네 부분공간의 직교정규 기저 를 동시에 구성한다.

이것이 선형대수 기본정리의 완성이다 (Strang, 2009, Ch.6.7).

4.1 왜 이렇게 되는가 — 직관 증명

네 부분공간과 \(\mathbf{U}, \mathbf{V}\) 의 대응은 우연이 아니다. \(\mathbf{A}\mathbf{v}_i = \sigma_i \mathbf{u}_i\) 한 줄에서 모두 따라 나온다.

1. \(\mathbf{v}_1, \ldots, \mathbf{v}_r\) 은 행 공간의 기저이다. \(\mathbf{A}\mathbf{v}_i = \sigma_i \mathbf{u}_i \neq \mathbf{0}\) 이므로 \(\mathbf{v}_i\) 는 영공간에 없다. 영공간의 직교 여공간이 행 공간이므로, \(\mathbf{v}_i\) 는 행 공간 안에 있다. \(r\) 개의 직교 벡터가 \(r\) 차원 행 공간을 채우므로 기저가 된다.

2. \(\mathbf{v}_{r+1}, \ldots, \mathbf{v}_n\) 은 영공간의 기저이다. \(\sigma_i = 0\) 이면 \(\mathbf{A}^\top\mathbf{A}\mathbf{v}_i = 0 \cdot \mathbf{v}_i = \mathbf{0}\), 따라서 \(\|\mathbf{A}\mathbf{v}_i\|^2 = \mathbf{v}_i^\top\mathbf{A}^\top\mathbf{A}\mathbf{v}_i = 0\), 즉 \(\mathbf{A}\mathbf{v}_i = \mathbf{0}\). 이 벡터들이 영공간에 들어간다.

3. \(\mathbf{u}_1, \ldots, \mathbf{u}_r\) 은 열 공간의 기저이다. \(\mathbf{u}_i = \mathbf{A}\mathbf{v}_i / \sigma_i\) — 즉 \(\mathbf{u}_i\)\(\mathbf{A}\) 의 열들의 선형 결합이므로 자동으로 열 공간 안에 있다. \(r\) 개가 직교하므로 독립이고, 열 공간의 차원이 \(r\) 이므로 기저가 된다.

4. \(\mathbf{u}_{r+1}, \ldots, \mathbf{u}_m\) 은 좌영공간의 기저이다. \(\mathbf{U}\) 의 모든 열이 직교하므로 \(\mathbf{u}_i\) (\(i > r\)) 는 열 공간과 직교한다. 열 공간의 직교 여공간이 좌영공간이므로 이 벡터들이 좌영공간을 채운다.

하나의 식 \(\mathbf{A}\mathbf{v}_i = \sigma_i \mathbf{u}_i\) 가 네 부분공간을 동시에 조립한다. 이것이 SVD를 “기본정리의 완성”이라 부르는 이유다.


5 변분적 정의 — 최대화 문제로서의 SVD

SVD를 이해하는 또 하나의 시각이 있다. 특이값은 최대화 문제의 해 로도 정의할 수 있다.

\[\sigma_1 = \max_{\|\mathbf{x}\| = 1} \|\mathbf{A}\mathbf{x}\|\]

\(\sigma_1\) 은 “단위 벡터에 \(\mathbf{A}\) 를 곱했을 때 가장 크게 늘어난 길이” 다. 최대를 달성하는 \(\mathbf{x}\) 가 바로 \(\mathbf{v}_1\) 이고, 그때의 이미지가 \(\sigma_1 \mathbf{u}_1\) 이다.

두 번째 특이값은 \(\mathbf{v}_1\)제외한 방향 중에서 최대값이다:

\[\sigma_2 = \max_{\substack{\|\mathbf{x}\| = 1 \\ \mathbf{x} \perp \mathbf{v}_1}} \|\mathbf{A}\mathbf{x}\|\]

계속해서 \(\mathbf{v}_1, \ldots, \mathbf{v}_{k-1}\) 에 모두 직교하는 방향 중 최대 신축률이 \(\sigma_k\) 다. 이것을 Courant-Fischer 최소최대 정리 라 한다.

이 관점이 왜 중요한가

변분적 정의는 “SVD는 신축률을 순서대로 나열한 것”이라는 점을 명확히 한다.

  • \(\sigma_1\): 가장 크게 늘어나는 방향
  • \(\sigma_2\): 그다음으로 크게 늘어나는 (직교) 방향

이 관점에서 PCA가 자연스럽게 나온다: “데이터에서 분산이 가장 큰 방향” = “\(\|\mathbf{X}\mathbf{x}\|\) 를 최대화하는 방향” = “\(\mathbf{X}\) 의 첫 번째 right singular vector \(\mathbf{v}_1\)”. PCA는 SVD를 최적화 문제로 본 것일 뿐이다.

또한 스펙트럼 노름(operator norm)의 정의 \(\|\mathbf{A}\|_2 = \sigma_1\) 도 이 관점에서 나온다 — 행렬의 “크기”는 그것이 벡터를 얼마나 크게 늘릴 수 있는가다.


6 SVD 구하는 방법

6.1 Step 1: V와 특이값 구하기

\(\mathbf{A}^\top \mathbf{A}\)\(n \times n\) 대칭 양반정치 행렬이다. 스펙트럼 정리에 의해:

\[\mathbf{A}^\top \mathbf{A} = \mathbf{V} \mathbf{D} \mathbf{V}^\top, \quad \mathbf{D} = \text{diag}(\sigma_1^2, \ldots, \sigma_r^2, 0, \ldots, 0)\]

\(\mathbf{V}\) 의 열벡터(고유벡터)가 right singular vectors이고, 고유값의 양의 제곱근이 특이값이다:

\[\sigma_i = \sqrt{\lambda_i(\mathbf{A}^\top \mathbf{A})} \geq 0\]

왜 양반정치인가: \(\mathbf{x}^\top (\mathbf{A}^\top \mathbf{A}) \mathbf{x} = \|\mathbf{A}\mathbf{x}\|^2 \geq 0\) 이므로, 고유값은 항상 0 이상이다. 따라서 특이값은 항상 실수이고 비음수다.

6.2 Step 2: U 구하기

행 공간에서 \(\mathbf{v}_i\)\(\mathbf{A}\) 에 곱하면 열 공간의 벡터 \(\mathbf{u}_i\) 를 얻는다:

\[\mathbf{u}_i = \frac{\mathbf{A} \mathbf{v}_i}{\sigma_i} \quad (i = 1, \ldots, r)\]

직관: 입력 기저 → 출력 기저 매핑
  • \(\mathbf{v}_i\): 행 공간 \(\mathbb{R}^n\)의 직교정규 입력 기저
  • \(\mathbf{u}_i\): 열 공간 \(\mathbb{R}^m\)의 직교정규 출력 기저
  • \(\sigma_i\): 해당 방향의 “증폭률” (얼마나 늘어나는가)

\(\mathbf{A}\)는 서로 다른 공간의 기저를 짝지어 매핑한다. \(\mathbf{v}_i\) 방향으로 들어온 벡터는 \(\mathbf{u}_i\) 방향으로 나가되, 크기가 \(\sigma_i\)배 된다. 직교 입력 기저 집합이 직교 출력 기저 집합으로 완벽하게 변환된다.

\(\mathbf{u}_i\) 들이 자동으로 직교함을 증명할 수 있다:

\[(\mathbf{A} \mathbf{v}_i)^\top (\mathbf{A} \mathbf{v}_j) = \mathbf{v}_i^\top (\mathbf{A}^\top \mathbf{A}) \mathbf{v}_j = \mathbf{v}_i^\top (\sigma_j^2 \mathbf{v}_j) = 0 \quad (i \neq j)\]

나머지 \(m - r\) 개의 \(\mathbf{u}_i\) 는 좌영공간의 직교정규 기저로 채운다.

6.3 Step 3: 동일한 특이값이 AA^T에서도 나온다

\[\mathbf{A} \mathbf{A}^\top = \mathbf{U} \mathbf{\Sigma} \mathbf{\Sigma}^\top \mathbf{U}^\top\]

\(\mathbf{A}^\top \mathbf{A}\)\(\mathbf{A} \mathbf{A}^\top\)같은 0이 아닌 고유값 을 가진다. 따라서 특이값은 어느 쪽에서 구해도 같다.


7 손계산 예시 — 2×2 행렬의 SVD

이론이 실제로 어떻게 작동하는지 확인해보자. Strang의 예시 (Strang, 2009, Ch.6.7)를 단계별로 따라간다:

\[\mathbf{A} = \begin{bmatrix} 2 & 2 \\ -1 & 1 \end{bmatrix}\]

Step 1: \(\mathbf{A}^\top \mathbf{A}\) 계산

\[\mathbf{A}^\top \mathbf{A} = \begin{bmatrix} 2 & -1 \\ 2 & 1 \end{bmatrix} \begin{bmatrix} 2 & 2 \\ -1 & 1 \end{bmatrix} = \begin{bmatrix} 5 & 3 \\ 3 & 5 \end{bmatrix}\]

Step 2: 고유값·고유벡터 구하기

\[\det(\mathbf{A}^\top \mathbf{A} - \lambda \mathbf{I}) = (5-\lambda)^2 - 9 = 0 \implies \lambda_1 = 8, \quad \lambda_2 = 2\]

\[\sigma_1 = 2\sqrt{2}, \quad \sigma_2 = \sqrt{2}\]

\[\mathbf{v}_1 = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 1 \end{bmatrix}, \quad \mathbf{v}_2 = \frac{1}{\sqrt{2}} \begin{bmatrix} -1 \\ 1 \end{bmatrix}\]

Step 3: U 구하기

\[\mathbf{A} \mathbf{v}_1 = \begin{bmatrix} 2 & 2 \\ -1 & 1 \end{bmatrix} \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 2\sqrt{2} \\ 0 \end{bmatrix} = 2\sqrt{2} \cdot \begin{bmatrix} 1 \\ 0 \end{bmatrix} \implies \mathbf{u}_1 = \begin{bmatrix} 1 \\ 0 \end{bmatrix}\]

\[\mathbf{A} \mathbf{v}_2 = \begin{bmatrix} 2 & 2 \\ -1 & 1 \end{bmatrix} \frac{1}{\sqrt{2}} \begin{bmatrix} -1 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ \sqrt{2} \end{bmatrix} = \sqrt{2} \cdot \begin{bmatrix} 0 \\ 1 \end{bmatrix} \implies \mathbf{u}_2 = \begin{bmatrix} 0 \\ 1 \end{bmatrix}\]

최종 SVD

\[\begin{bmatrix} 2 & 2 \\ -1 & 1 \end{bmatrix} = \underbrace{\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}}_{\mathbf{U}} \underbrace{\begin{bmatrix} 2\sqrt{2} & 0 \\ 0 & \sqrt{2} \end{bmatrix}}_{\mathbf{\Sigma}} \underbrace{\begin{bmatrix} 1/\sqrt{2} & 1/\sqrt{2} \\ -1/\sqrt{2} & 1/\sqrt{2} \end{bmatrix}}_{\mathbf{V}^\top}\]

이 경우 \(\mathbf{A}\mathbf{A}^\top\) 가 대각행렬이어서 \(\mathbf{U} = \mathbf{I}\) 가 됐다. 일반적으로는 \(\mathbf{U}\) 도 회전 행렬이다.


8 랭크-k 근사 (Truncated SVD)

SVD의 식 (4)를 외적(rank-1 행렬)의 합으로 쓸 수 있다:

\[\mathbf{A} = \sigma_1 \mathbf{u}_1 \mathbf{v}_1^\top + \sigma_2 \mathbf{u}_2 \mathbf{v}_2^\top + \cdots + \sigma_r \mathbf{u}_r \mathbf{v}_r^\top\]

\(\sigma_1 \geq \sigma_2 \geq \cdots \geq \sigma_r > 0\) 이므로 앞쪽 항들이 더 중요하다. 처음 \(k\) 개 항만 사용하면:

\[\mathbf{A}_k = \sum_{i=1}^{k} \sigma_i \mathbf{u}_i \mathbf{v}_i^\top\]

비유: 각 항 \(\sigma_i \mathbf{u}_i \mathbf{v}_i^\top\)은 하나의 rank-1 패턴이다. 이미지로 비유하면, 첫 번째 항은 전반적인 밝기(저주파), 두 번째 항은 굵은 윤곽선, 세 번째 항은 더 세밀한 질감… 순서대로 세부 정보가 더해진다. \(k\)를 늘릴수록 원본에 가까워지고, \(k=r\)이면 완전히 복원된다.

정리: Eckart-Young-Mirsky (최적 저차원 근사)

rank \(k\) 행렬 중에서 \(\|\mathbf{A} - \mathbf{B}\|_F\) (Frobenius 노름)를 최소화하는 행렬은 \(\mathbf{A}_k\) 이다:

\[\|\mathbf{A} - \mathbf{A}_k\|_F = \sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2}\]

직관: \(\mathbf{A}_k\)\(\mathbf{A}\) 의 “가장 중요한 \(k\) 방향”만 남긴 최적 근사다.

8.1 피타고라스로 보는 Eckart-Young

왜 이것이 최적 인가? SVD는 \(\mathbf{A}\) 를 서로 직교하는 rank-1 성분들의 합으로 분해한다:

\[\mathbf{A} = \underbrace{\sigma_1 \mathbf{u}_1 \mathbf{v}_1^\top}_{\text{성분 1}} + \underbrace{\sigma_2 \mathbf{u}_2 \mathbf{v}_2^\top}_{\text{성분 2}} + \cdots + \underbrace{\sigma_r \mathbf{u}_r \mathbf{v}_r^\top}_{\text{성분 } r}\]

이 성분들은 Frobenius 내적에 대해 직교한다. 직교이므로 피타고라스 정리 가 적용된다:

\[\|\mathbf{A}\|_F^2 = \sigma_1^2 + \sigma_2^2 + \cdots + \sigma_r^2\]

\(\mathbf{A}_k\) 로 앞의 \(k\) 개 성분만 남기면, 버린 부분의 “길이”가 바로:

\[\|\mathbf{A} - \mathbf{A}_k\|_F^2 = \sigma_{k+1}^2 + \cdots + \sigma_r^2\]

이건 피타고라스 정리에서 “버린 변들의 제곱합” 이다. 큰 성분을 버리면 오차가 커지므로, 작은 \(\sigma_i\) 부터 버리는 것이 당연히 최적이다. SVD는 이미 크기 순으로 정렬된 직교 분해를 제공하므로 탐색이 필요 없다.

이것이 이미지 압축, PCA, 추천 시스템 등의 수학적 근거다.


9 이미지 압축 응용

\(m \times n\) 이미지 행렬 \(\mathbf{A}\) 를 그대로 저장하려면 \(mn\) 개의 수가 필요하다. rank-\(k\) 근사 \(\mathbf{A}_k\) 는:

  • \(\mathbf{U}\) 에서 \(mk\)
  • \(\mathbf{\Sigma}\) 에서 \(k\)
  • \(\mathbf{V}^\top\) 에서 \(nk\)

\(k(m + n + 1)\) 개의 수만 저장한다. 압축비 = \(\dfrac{mn}{k(m+n+1)}\)

예시: \(256 \times 512\) 이미지, \(k=5\) 이면 압축비 \(\approx 34:1\)

\(\sigma_1\) 이 가장 큰 방향(전반적 밝기)을 포착하고, \(\sigma_2, \sigma_3, \ldots\) 는 점점 세밀한 패턴을 더한다. \(k\) 를 키울수록 화질이 회복된다.


10 의사역행렬 (Pseudoinverse)

\(\mathbf{A} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^\top\) 에서 의사역행렬(Moore-Penrose pseudoinverse)을 자연스럽게 정의한다:

\[\mathbf{A}^+ = \mathbf{V} \mathbf{\Sigma}^+ \mathbf{U}^\top\]

여기서 \(\mathbf{\Sigma}^+\)\(\mathbf{\Sigma}\) 의 0이 아닌 대각 원소 \(\sigma_i\)\(1/\sigma_i\) 로 바꾼 행렬이다.

의미: \(\mathbf{A}^+\)\(\mathbf{A}\mathbf{x} = \mathbf{b}\)최소제곱 최소노름 해 를 준다:

\[\hat{\mathbf{x}} = \mathbf{A}^+ \mathbf{b}\]

  • \(\mathbf{A}\) 가 정방 가역이면 \(\mathbf{A}^+ = \mathbf{A}^{-1}\) 과 일치
  • 과결정 시스템(\(m > n\), 방정식 수 > 미지수): 유일한 최소제곱 해
  • 미결정 시스템(\(m < n\), 방정식 수 < 미지수): 가능한 해 중 노름이 최소인 해
직관: 왜 \(\mathbf{\Sigma}^+\)인가

\(\mathbf{\Sigma}\) 의 역할은 각 방향을 \(\sigma_i\)배 늘리는 것이다. 역(pseudo-inverse)은 그것을 \(1/\sigma_i\)배로 되돌린다. 단, \(\sigma_i = 0\)인 방향(영공간 방향)은 정보가 없으므로 0으로 둔다 — 없는 정보를 임의로 되살리지 않는다.

\[\mathbf{\Sigma}^+ = \begin{bmatrix} 1/\sigma_1 & & \\ & \ddots & \\ & & 1/\sigma_r \\ & \mathbf{0} & \end{bmatrix}^\top\]

이 처리 방식이 “최소제곱 + 최소노름”이라는 이중 최적성을 보장한다.

수치 계산에서는 \(\sigma_i\) 가 매우 작을 때 직접 역수를 취하면 수치 불안정이 생긴다. 임계값 \(\epsilon\) 을 설정해 \(\sigma_i < \epsilon\) 이면 0으로 처리하는 절사 의사역행렬(truncated pseudoinverse) 을 사용한다.


11 고유값 분해 vs SVD 비교

항목 고유값 분해 \(\mathbf{A} = \mathbf{S}\mathbf{\Lambda}\mathbf{S}^{-1}\) SVD \(\mathbf{A} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^\top\)
적용 대상 정방 행렬만 임의 \(m \times n\) 행렬
직교성 \(\mathbf{S}\) 가 직교행렬이 아닐 수 있다 \(\mathbf{U}\), \(\mathbf{V}\) 는 항상 직교
항상 존재 결함 행렬이면 불가 항상 존재 (유일하지는 않음)
대각 원소 고유값 (복소수 가능) 특이값 (항상 실수, 비음수)
언제 동일 \(\mathbf{A}\) 가 양반정치 대칭행렬일 때 \(\mathbf{U}=\mathbf{V}=\mathbf{Q}\), \(\mathbf{\Sigma}=\mathbf{\Lambda}\)
주요 용도 동적 시스템, 마르코프 행렬 데이터 분석, 저차원 근사, 수치 선형대수
언제 SVD = 고유값 분해인가

\(\mathbf{A}\) 가 양반정치 대칭행렬 (\(\mathbf{A} = \mathbf{Q}\mathbf{\Lambda}\mathbf{Q}^\top\), \(\lambda_i \geq 0\)) 이면:

\[\mathbf{U} = \mathbf{V} = \mathbf{Q}, \quad \mathbf{\Sigma} = \mathbf{\Lambda}\]

즉 SVD와 고유값 분해가 일치한다.

흔한 오해 3가지

오해 1. “특이값 = 고유값” 일반 행렬에서는 다르다. \(\mathbf{A}^\top\mathbf{A}\)의 고유값이 \(\sigma_i^2\)이고, \(\mathbf{A}\) 자체의 고유값은 복소수일 수도 있다. 양반정치 대칭행렬에서만 특이값 = 고유값이 된다.

오해 2. “\(\mathbf{U} = \mathbf{V}\) \(m \neq n\)이면 \(\mathbf{U}\)\(\mathbf{V}\)의 크기 자체가 다르다. 일반적으로 \(\mathbf{U} \neq \mathbf{V}\).

오해 3. “SVD가 항상 유일하다” 특이값의 순서를 고정해도, \(\sigma_i = \sigma_j\)인 경우 해당 부분공간의 기저 선택이 자유롭다. 부호 선택도 자유롭다 (\(\mathbf{u}_i\)\(-\mathbf{u}_i\)는 모두 유효). 실용적으로는 \(\sigma_1 \geq \sigma_2 \geq \cdots\) 순서로 정규화해서 사용한다.


12 ML/DS 응용 분야

12.1 주성분 분석 (PCA)

“분산이 가장 큰 방향을 찾아라” — 이것이 PCA의 핵심 질문이다. SVD는 이 질문에 직접 답한다.

데이터 행렬 \(\mathbf{X} \in \mathbb{R}^{n \times p}\) (중심화됨)의 공분산 행렬은 \(\mathbf{C} = \frac{1}{n-1}\mathbf{X}^\top \mathbf{X}\).

두 가지 경로가 같은 답을 준다:

경로 계산 결과
공분산 경로 \(\mathbf{C} = \frac{1}{n-1}\mathbf{X}^\top\mathbf{X}\) 의 고유값 분해 고유값 \(\lambda_i\), 고유벡터 \(\mathbf{q}_i\)
직접 SVD 경로 \(\mathbf{X} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^\top\) 특이값 \(\sigma_i\), right singular vectors \(\mathbf{v}_i\)

두 경로의 대응:

\[\mathbf{q}_i = \mathbf{v}_i, \qquad \lambda_i = \frac{\sigma_i^2}{n-1}\]

왜 같은가? \(\mathbf{X}^\top\mathbf{X} = \mathbf{V}\mathbf{\Sigma}^\top\mathbf{\Sigma}\mathbf{V}^\top = \mathbf{V}\,\text{diag}(\sigma_i^2)\,\mathbf{V}^\top\) 이므로 \(\mathbf{V}\) 의 열이 \(\mathbf{X}^\top\mathbf{X}\) 의 고유벡터이고, 고유값은 \(\sigma_i^2\) 이다.

SVD: - \(\mathbf{V}\) 의 열: 주성분 방향 (principal directions) - \(\sigma_i^2 / (n-1)\): 각 주성분의 분산 - \(\mathbf{U}\mathbf{\Sigma}\) 의 열: 주성분 점수 (principal component scores) - \(k\) 개 주성분으로 차원 축소: \(\mathbf{X}_k = \mathbf{U}_k \mathbf{\Sigma}_k \mathbf{V}_k^\top\)

실무에서 SVD 경로가 더 안정적이다

수학적으로 두 경로는 동일하지만, 수치적으로는 다르다. \(\mathbf{X}^\top\mathbf{X}\) 를 직접 만들면 조건수가 \(\kappa(\mathbf{X})^2\)제곱 되어 작은 특이값 정보가 날아간다. 실무 PCA 구현(sklearn.decomposition.PCA)이 내부적으로 공분산 행렬을 만들지 않고 SVD를 직접 호출하는 이유다.

PCA는 SVD의 특수 케이스다.

12.2 잠재 의미 분석 (LSA / LSI)

“고양이”와 “강아지”는 같은 문장에 자주 등장하지 않더라도 의미적으로 가깝다. LSA는 SVD를 통해 단어의 공동 출현 패턴에서 잠재적 의미를 추출한다.

문서-단어 행렬 \(\mathbf{A}\) (행: 문서, 열: 단어)에 SVD를 적용하면: - \(\mathbf{U}\): 문서의 잠재 토픽 표현 - \(\mathbf{V}\): 단어의 잠재 토픽 표현 - \(\sigma_i\): 토픽의 중요도

rank-\(k\) 근사로 동의어·맥락을 포착하는 의미 공간 을 구성한다.

12.3 추천 시스템 (Collaborative Filtering)

사용자 A가 본 영화를 사용자 B가 아직 보지 않았을 때, “B도 이 영화를 좋아할 것”이라고 예측하는 것이 협업 필터링이다. SVD는 사용자·아이템의 잠재 특성을 추출해 미관측 평점을 예측한다.

사용자-아이템 평점 행렬 \(\mathbf{R}\) 에 SVD를 적용: - \(\mathbf{R} \approx \mathbf{U}_k \mathbf{\Sigma}_k \mathbf{V}_k^\top\) - 결측값을 채워 사용자의 미관측 평점을 예측한다 - Netflix Prize의 핵심 알고리즘이었다

12.4 조건수와 수치 안정성

행렬 \(\mathbf{A}\)조건수 (condition number):

\[\kappa(\mathbf{A}) = \frac{\sigma_1}{\sigma_r} = \|\mathbf{A}\|_2 \cdot \|\mathbf{A}^{-1}\|_2\]

\(\kappa\) 가 크면 \(\mathbf{A}\mathbf{x} = \mathbf{b}\) 의 해가 \(\mathbf{b}\) 의 작은 변화에 민감하다 (수치적으로 불안정). SVD는 조건수를 직접 계산하는 가장 신뢰할 수 있는 방법이다.

응용 활용 SVD 역할
PCA 차원 축소, 특성 추출 분산이 큰 방향 추출
LSA 문서 검색, 토픽 모델 잠재 의미 공간 구성
추천 시스템 협업 필터링 저차원 잠재 인수 모델
의사역행렬 최소제곱 풀이 안정적 역행렬 대체
이미지 압축 저장 공간 절약 최적 rank-\(k\) 근사
조건수 계산 수치 안정성 진단 \(\sigma_1 / \sigma_r\)

13 코드 예시

import numpy as np
import matplotlib.pyplot as plt

# --------------------------------------------------
# 1. SVD 직접 계산 (원리 이해)
# --------------------------------------------------

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

# A^T A 고유값 분해로 V와 σ 구하기
ATA = A.T @ A
eigenvalues, V = np.linalg.eigh(ATA)          # 대칭 행렬 전용 (실수 고유값 보장)
idx = np.argsort(eigenvalues)[::-1]            # 내림차순 정렬
eigenvalues = eigenvalues[idx]
V = V[:, idx]

sigmas = np.sqrt(np.maximum(eigenvalues, 0))   # 특이값 (음수 방지)
r = np.sum(sigmas > 1e-10)                     # 실제 rank

# U 구하기: u_i = A v_i / σ_i
U = np.zeros((A.shape[0], A.shape[0]))
for i in range(r):
    U[:, i] = A @ V[:, i] / sigmas[i]

# 나머지 U 열: Gram-Schmidt로 채우기 (이미 직교이면 생략)
print("U =\n", U.round(4))
print("Sigma =", sigmas.round(4))
print("V =\n", V.round(4))

# 검증: A == U @ Sigma @ V^T
Sigma = np.diag(sigmas)
A_reconstructed = U @ Sigma @ V.T
print("\n재구성 오차:", np.linalg.norm(A - A_reconstructed))


# --------------------------------------------------
# 2. NumPy 내장 SVD (실무 활용)
# --------------------------------------------------

U2, s2, Vt2 = np.linalg.svd(A, full_matrices=True)
print("\nNumPy SVD:")
print("U =\n", U2.round(4))
print("s =", s2.round(4))
print("V^T =\n", Vt2.round(4))


# --------------------------------------------------
# 3. 이미지 압축 시뮬레이션
# --------------------------------------------------

def svd_compress(matrix, k):
    """rank-k SVD 근사"""
    U, s, Vt = np.linalg.svd(matrix, full_matrices=False)
    return U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :]

# 가상 이미지 행렬 (256 x 256)
np.random.seed(42)
# 저주파 패턴 + 노이즈로 구성된 이미지 시뮬레이션
x = np.linspace(0, 4 * np.pi, 256)
img = np.outer(np.sin(x), np.cos(x)) + 0.1 * np.random.randn(256, 256)

fig, axes = plt.subplots(1, 5, figsize=(15, 3))
axes[0].imshow(img, cmap='gray')
axes[0].set_title('Original')

for idx, k in enumerate([1, 5, 20, 50]):
    compressed = svd_compress(img, k)
    # 압축비 계산
    original_size = img.shape[0] * img.shape[1]
    compressed_size = k * (img.shape[0] + img.shape[1] + 1)
    ratio = original_size / compressed_size
    axes[idx+1].imshow(compressed, cmap='gray')
    axes[idx+1].set_title(f'k={k}\n(비율 {ratio:.1f}:1)')

plt.tight_layout()
plt.savefig('svd_compression.png', dpi=100, bbox_inches='tight')
plt.show()


# --------------------------------------------------
# 4. 특이값 감소 패턴 시각화
# --------------------------------------------------

_, s, _ = np.linalg.svd(img)
cumvar = np.cumsum(s**2) / np.sum(s**2)

fig, axes = plt.subplots(1, 2, figsize=(10, 4))
axes[0].semilogy(s, 'b-o', markersize=3)
axes[0].set_xlabel('인덱스 $i$')
axes[0].set_ylabel('특이값 $\\sigma_i$ (로그 스케일)')
axes[0].set_title('특이값 감소 패턴')
axes[0].grid(True)

axes[1].plot(cumvar[:100], 'r-')
axes[1].axhline(0.9, color='gray', linestyle='--', label='90% 분산')
axes[1].axhline(0.99, color='black', linestyle='--', label='99% 분산')
axes[1].set_xlabel('k (사용하는 특이값 수)')
axes[1].set_ylabel('누적 분산 비율')
axes[1].set_title('누적 분산 — k 개 특이값')
axes[1].legend()
axes[1].grid(True)

plt.tight_layout()
plt.show()
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

# --------------------------------------------------
# PCA = SVD (중심화된 데이터)
# --------------------------------------------------

iris = load_iris()
X = iris.data                                  # 150 x 4
X_centered = X - X.mean(axis=0)               # 중심화

# SVD 기반 PCA
U, s, Vt = np.linalg.svd(X_centered, full_matrices=False)

# 주성분 방향 (V의 열 = Vt의 행)
principal_components = Vt.T                    # 4 x 4

# 데이터를 주성분 좌표계로 변환
scores = X_centered @ principal_components     # 150 x 4

# 각 주성분의 분산 설명 비율
n = X.shape[0]
explained_variance = s**2 / (n - 1)
total_variance = np.var(X_centered, axis=0, ddof=1).sum()
explained_ratio = explained_variance / total_variance

print("설명 분산 비율:")
for i, ratio in enumerate(explained_ratio):
    print(f"  PC{i+1}: {ratio:.4f} ({ratio*100:.1f}%)")

# 2D 시각화
plt.figure(figsize=(8, 6))
colors = ['red', 'green', 'blue']
for i, (target, color) in enumerate(zip(iris.target_names, colors)):
    mask = iris.target == i
    plt.scatter(scores[mask, 0], scores[mask, 1],
                c=color, label=target, alpha=0.7)
plt.xlabel(f'PC1 ({explained_ratio[0]*100:.1f}%)')
plt.ylabel(f'PC2 ({explained_ratio[1]*100:.1f}%)')
plt.title('PCA via SVD — Iris Dataset')
plt.legend()
plt.grid(True)
plt.show()
library(Matrix)
library(ggplot2)

# --------------------------------------------------
# 1. 기본 SVD
# --------------------------------------------------

A <- matrix(c(2, -1, 2, 1), nrow = 2, ncol = 2)  # 열 우선
cat("A =\n"); print(A)

svd_result <- svd(A)
U <- svd_result$u
s <- svd_result$d
Vt <- t(svd_result$v)

cat("\nU =\n"); print(round(U, 4))
cat("Sigma =", round(s, 4), "\n")
cat("V^T =\n"); print(round(Vt, 4))

# 재구성 검증
A_reconstructed <- U %*% diag(s) %*% Vt
cat("\n재구성 오차:", norm(A - A_reconstructed, "F"), "\n")


# --------------------------------------------------
# 2. rank-k 근사 함수
# --------------------------------------------------

svd_approx <- function(M, k) {
  sv <- svd(M)
  sv$u[, 1:k, drop = FALSE] %*%
    diag(sv$d[1:k], nrow = k) %*%
    t(sv$v[, 1:k, drop = FALSE])
}


# --------------------------------------------------
# 3. 특이값 감소 패턴 (임의 행렬)
# --------------------------------------------------

set.seed(42)
M <- matrix(rnorm(100 * 200), nrow = 100)
sv_M <- svd(M)

# 특이값 그래프
sv_df <- data.frame(
  i = seq_along(sv_M$d),
  sigma = sv_M$d,
  cum_var = cumsum(sv_M$d^2) / sum(sv_M$d^2)
)

p1 <- ggplot(sv_df, aes(x = i, y = sigma)) +
  geom_line(color = "steelblue") +
  geom_point(size = 0.5) +
  scale_y_log10() +
  labs(title = "특이값 감소 패턴 (로그 스케일)",
       x = "인덱스 i", y = expression(sigma[i])) +
  theme_bw()

p2 <- ggplot(sv_df[1:60, ], aes(x = i, y = cum_var)) +
  geom_line(color = "firebrick") +
  geom_hline(yintercept = 0.9, linetype = "dashed", color = "gray") +
  geom_hline(yintercept = 0.99, linetype = "dashed", color = "black") +
  labs(title = "누적 분산 비율",
       x = "k (사용하는 특이값 수)", y = "누적 분산 비율") +
  theme_bw()

gridExtra::grid.arrange(p1, p2, ncol = 2)


# --------------------------------------------------
# 4. PCA via SVD (iris 데이터)
# --------------------------------------------------

data(iris)
X <- as.matrix(iris[, 1:4])
X_c <- scale(X, center = TRUE, scale = FALSE)  # 중심화

sv <- svd(X_c)
scores <- X_c %*% sv$v                          # PC 점수
expl_var <- sv$d^2 / sum(sv$d^2)

cat("\n설명 분산 비율:\n")
for (i in seq_along(expl_var)) {
  cat(sprintf("  PC%d: %.4f (%.1f%%)\n", i, expl_var[i], expl_var[i]*100))
}

df_pca <- data.frame(PC1 = scores[,1], PC2 = scores[,2],
                     Species = iris$Species)
ggplot(df_pca, aes(PC1, PC2, color = Species)) +
  geom_point(alpha = 0.8, size = 2) +
  labs(title = "PCA via SVD — Iris",
       x = sprintf("PC1 (%.1f%%)", expl_var[1]*100),
       y = sprintf("PC2 (%.1f%%)", expl_var[2]*100)) +
  theme_bw()

위 계산 과정이 SVD의 표준 알고리즘이다. 실제 수치 계산에서는 \(\mathbf{A}^\top\mathbf{A}\)를 직접 만들지 않고 더 안정적인 방법(Golub-Reinsch)을 사용하지만, 원리는 동일하다.


14 SVD 증명의 핵심 아이디어

핵심 관계 (Strang, 2009, Ch.6.7):

\[\mathbf{A}^\top \mathbf{A} \mathbf{v}_i = \sigma_i^2 \mathbf{v}_i \implies \|\mathbf{A}\mathbf{v}_i\|^2 = \sigma_i^2\]

\[\mathbf{A}\mathbf{A}^\top (\mathbf{A}\mathbf{v}_i) = \sigma_i^2 (\mathbf{A}\mathbf{v}_i)\]

두 번째 식이 핵심이다. \(\mathbf{A}\mathbf{v}_i\)\(\mathbf{A}\mathbf{A}^\top\) 의 고유벡터임을 보인다. 따라서 \(\mathbf{u}_i = \mathbf{A}\mathbf{v}_i / \sigma_i\) 로 정의하면, \(\mathbf{u}_i\) 들은 \(\mathbf{A}\mathbf{A}^\top\) 의 직교 고유벡터가 된다.

\(\mathbf{u}_i\) 들의 직교성 증명:

\[(\mathbf{A}\mathbf{v}_i)^\top (\mathbf{A}\mathbf{v}_j) = \mathbf{v}_i^\top \mathbf{A}^\top \mathbf{A} \mathbf{v}_j = \sigma_j^2 \mathbf{v}_i^\top \mathbf{v}_j = 0 \quad (i \neq j)\]

\(\mathbf{v}_i\) 들이 직교하므로 \(\mathbf{u}_i\) 들도 자동으로 직교한다.


15 수치적 주의사항

상황 문제 해결
\(\mathbf{A}^\top \mathbf{A}\) 직접 계산 조건수가 \(\kappa(\mathbf{A})^2\) 으로 제곱됨 대형 행렬에서 수치 오차 증폭
작은 특이값 처리 \(1/\sigma_i\) 계산 시 수치 불안정 임계값(tolerance) 이하는 0으로 처리
비정방 행렬 np.linalg.svd 에서 full_matrices=False 경제형 SVD (reduced SVD) 사용
희소 행렬 scipy.sparse.linalg.svds 처음 \(k\) 개 특이값만 계산 (빠름)

15.1 \(\kappa^2\) 효과 — 왜 \(\mathbf{A}^\top\mathbf{A}\) 를 피해야 하는가

구체적인 숫자로 보자. \(\kappa(\mathbf{A}) = 10^6\) 인 행렬을 생각한다 (과학·공학에서 드물지 않다).

  • \(\mathbf{A}\) 에 SVD를 직접 적용: 배정밀도 부동소수점(약 \(10^{-16}\) 정밀도)에서 특이값을 약 10자리 까지 믿을 수 있다.
  • \(\mathbf{A}^\top\mathbf{A}\) 를 먼저 만들면 조건수가 \(\kappa^2 = 10^{12}\): 이제 특이값을 약 4자리 까지만 믿을 수 있다.

6자리의 유효숫자가 사라진다. 작은 특이값 근처(rank 결정, 희소 신호 검출 등)에서 치명적이다.

따라서 LAPACK의 svd 함수\(\mathbf{A}^\top \mathbf{A}\) 를 직접 계산하지 않고, 대신 \(\mathbf{A}\) 자체에 이분할(bidiagonalization) 과정을 적용하는 Golub-Reinsch 알고리즘 을 사용한다. NumPy/R의 svd() 함수도 모두 이 방식을 사용한다.

교훈: 수학 공식이 \(\mathbf{A}^\top\mathbf{A}\) 를 등장시킨다고 해서 코드에서도 그렇게 짜면 안 된다. “공식은 설명용, 구현은 수치 전용 루틴으로” — 이것이 수치 선형대수의 황금률이다.


16 정리 — SVD의 핵심 메시지

항목 내용
분해 \(\mathbf{A} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^\top\) — 임의 \(m \times n\) 행렬
특이값 \(\sigma_i = \sqrt{\lambda_i(\mathbf{A}^\top \mathbf{A})} \geq 0\)
부분공간 \(\mathbf{V}\): 행 공간 + 영공간 / \(\mathbf{U}\): 열 공간 + 좌영공간
변분적 정의 \(\sigma_1 = \max_{\|\mathbf{x}\|=1} \|\mathbf{A}\mathbf{x}\|\) (신축률 최대화)
기하 단위원의 이미지는 타원 — 반축 = \(\sigma_i \mathbf{u}_i\)
저차원 근사 \(\mathbf{A}_k = \sum_{i=1}^k \sigma_i \mathbf{u}_i \mathbf{v}_i^\top\) — rank \(k\) 행렬 중 최적
의사역행렬 \(\mathbf{A}^+ = \mathbf{V}\mathbf{\Sigma}^+\mathbf{U}^\top\) — 최소제곱 최소노름 해
조건수 \(\kappa(\mathbf{A}) = \sigma_1 / \sigma_r\) — 수치 안정성 척도

16.1 왜 “선형대수의 클라이맥스”인가

Strang의 표현이 과장이 아닌 이유는 SVD가 이전 챕터들의 모든 질문을 한 식으로 답하기 때문이다.

  1. 연립방정식 (\(\mathbf{A}\mathbf{x}=\mathbf{b}\)): \(\mathbf{A}^+\mathbf{b}\) 가 최선의 해 — 정확한 해가 없으면 최소제곱, 해가 여럿이면 최소노름. 의사역행렬 = SVD.

  2. 네 부분공간: \(\mathbf{V}\) 가 정의역 쪽(\(\mathbb{R}^n\))을 행 공간 ⊕ 영공간으로, \(\mathbf{U}\) 가 치역 쪽(\(\mathbb{R}^m\))을 열 공간 ⊕ 좌영공간으로 — 직교정규 기저까지 완성해 쪼갠다.

  3. 행렬의 “크기”: \(\|\mathbf{A}\|_2 = \sigma_1\), \(\|\mathbf{A}\|_F^2 = \sum\sigma_i^2\) — 모든 주요 노름이 특이값으로 표현된다.

  4. 고유값 분해의 일반화: 정방 행렬이어야만 했던 고유값 분해를 모든 행렬 로 확장하면서, \(\mathbf{U}\)\(\mathbf{V}\)항상 직교 라는 더 강한 성질까지 보장한다.

  5. 최적 저차원 근사: Eckart-Young 정리로 압축·차원 축소의 수학적 최적성 을 보장한다. PCA, LSA, 추천 시스템, 이미지 압축 — 모두 이 한 정리의 응용이다.

  6. 수치 선형대수의 기반: 조건수, rank 결정, 최소제곱 풀이, 널 공간 추출 — 모두 SVD로 안정적으로 계산할 수 있다.

한 줄로 말하면: “선형대수는 \(\mathbf{A}\mathbf{v}_i = \sigma_i\mathbf{u}_i\) 로 요약된다.” 이것이 Strang이 SVD를 학기의 마지막 주제로 배치한 이유다. 여기까지 오면, 선형대수가 말하고자 했던 거의 모든 것이 이 한 식에 담겨 있음을 보게 된다.


17 관련 주제

선행 지식

후속 주제

다른 카테고리 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: