Netflixがあなたに映画を推薦するとき、その裏では「ユーザー×映画」の巨大な評価行列が分解されています。数百万人のユーザーと数万本の映画がつくる巨大な行列から、「アクション好き」「ロマンス好き」といった数個の潜在的な嗜好パターンを抽出しているのです。この分解を可能にする数学的道具が特異値分解(SVD)です。
固有値分解は正方行列にしか適用できません。しかし、現実のデータ行列は $m \times n$($m \neq n$)であることがほとんどです。100人の身体測定データ(身長、体重、胸囲、…)なら $100 \times 10$ の行列になりますし、文書×単語の頻度行列は数千×数万の巨大な長方形行列です。
このような任意のサイズの行列に対して使える最も強力な分解法が特異値分解(Singular Value Decomposition, SVD)です。SVDはあらゆる行列に適用可能であり、「行列の本質的な構造を取り出す」という点で、線形代数の最も重要な定理の一つです。
SVDのアイデアを日常的なたとえで説明しましょう。写真を「暗い部屋で懐中電灯を順に当てる」ことを想像してください。最も明るい懐中電灯(第1特異値に対応)は写真の大まかな明暗を照らし、2番目の懐中電灯は細かい模様を、3番目はさらに微細な詳細を照らします。SVDは、行列に含まれる情報を「重要度順」に分解する方法なのです。
SVDを理解すると、以下のような応用が開けます。
- 機械学習: 主成分分析(PCA)、推薦システム(Netflix問題の低ランク行列補完)
- 自然言語処理: 潜在意味解析(LSA)は文書×単語行列のSVD
- 画像処理: 画像圧縮(低ランク近似による情報圧縮)
- 数値計算: 擬似逆行列、最小二乗法、ランクの数値的決定
- 制御工学: システムの平衡実現(balanced realization)、モデル低次元化
本記事の内容
- SVDの定義と存在定理
- SVDの導出(固有値分解との関係)
- SVDの幾何学的意味
- 低ランク近似(エッカート・ヤングの定理)
- 擬似逆行列とSVD
- Pythonによる実装(画像圧縮の例)
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- 固有値分解の理論と応用 — 固有値分解の基礎
SVDとは
直感的な理解
任意の $m \times n$ 行列 $\bm{A}$ による線形変換 $\bm{y} = \bm{A}\bm{x}$ を考えます。この変換は次の3つのステップに分解できます。
- 回転($\bm{V}^T$): 入力空間で適切な直交基底に変換する
- スケーリング($\bm{\Sigma}$): 各軸方向に特異値倍だけ引き伸ばす(次元が変わることも)
- 回転($\bm{U}$): 出力空間で適切な直交基底に戻す
「回転→引き伸ばし→回転」という分解がSVDの本質です。
固有値分解 $\bm{A} = \bm{P}\bm{\Lambda}\bm{P}^{-1}$ との違いを整理しましょう。固有値分解では入力空間と出力空間が同じ(正方行列のみ)であり、同じ基底 $\bm{P}$ で回転と逆回転を行います。一方SVDでは、入力空間の基底 $\bm{V}$ と出力空間の基底 $\bm{U}$ が独立に選ばれるため、長方形行列にも適用できます。
2次元の例で直感を掴みましょう。$\bm{A} = \begin{pmatrix} 3 & 1 \\ 1 & 3 \end{pmatrix}$ を考えます。この行列は単位円を楕円に変換しますが、SVDはこの楕円の長軸と短軸の方向と長さを教えてくれます。長軸の長さが第1特異値 $\sigma_1$、短軸の長さが第2特異値 $\sigma_2$ に対応し、それぞれの方向が左特異ベクトル $\bm{u}_1$、$\bm{u}_2$ で表されます。
数学的定義
定理(特異値分解): 任意の $m \times n$ 行列 $\bm{A}$($\text{rank}(\bm{A}) = r$)に対して、次の分解が存在する。
$$ \begin{equation} \bm{A} = \bm{U}\bm{\Sigma}\bm{V}^T \end{equation} $$
- $\bm{U}$: $m \times m$ 直交行列(左特異ベクトル)
- $\bm{\Sigma}$: $m \times n$ 対角行列(特異値 $\sigma_1 \geq \sigma_2 \geq \cdots \geq \sigma_r > 0$)
- $\bm{V}$: $n \times n$ 直交行列(右特異ベクトル)
特異値 $\sigma_i$ は $\bm{A}^T\bm{A}$ の固有値の正の平方根であり、$\bm{V}$ の列は $\bm{A}^T\bm{A}$ の固有ベクトル、$\bm{U}$ の列は $\bm{A}\bm{A}^T$ の固有ベクトルです。
導出
SVDの導出は、$\bm{A}^T\bm{A}$ と $\bm{A}\bm{A}^T$ という2つの対称行列の固有値分解から出発します。
ステップ1: $\bm{A}^T\bm{A}$ の固有値分解
$\bm{A}^T\bm{A}$ は $n \times n$ の半正定値対称行列です。半正定値である理由は、任意のベクトル $\bm{x}$ に対して $\bm{x}^T(\bm{A}^T\bm{A})\bm{x} = (\bm{A}\bm{x})^T(\bm{A}\bm{x}) = \|\bm{A}\bm{x}\|^2 \geq 0$ が成り立つからです。
対称行列なのでスペクトル定理により直交行列で対角化でき、固有値分解 $\bm{A}^T\bm{A} = \bm{V}\bm{\Lambda}\bm{V}^T$ が存在します。固有値を $\lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_n \geq 0$ と降順に並べ、特異値を $\sigma_i = \sqrt{\lambda_i}$ と定義します。
ステップ2: 左特異ベクトルの構成
$r = \text{rank}(\bm{A})$ 個の正の特異値に対応する右特異ベクトル $\bm{v}_1, \ldots, \bm{v}_r$ から、左特異ベクトルを
$$ \bm{u}_i = \frac{\bm{A}\bm{v}_i}{\sigma_i} \quad (i = 1, \ldots, r) $$
で定義します。
ステップ3: $\bm{u}_i$ の正規直交性の確認
$\bm{u}_i$ が正規直交系をなすことを確認しましょう。内積を計算すると
$$ \bm{u}_i^T\bm{u}_j = \frac{(\bm{A}\bm{v}_i)^T(\bm{A}\bm{v}_j)}{\sigma_i\sigma_j} = \frac{\bm{v}_i^T\bm{A}^T\bm{A}\bm{v}_j}{\sigma_i\sigma_j} $$
$\bm{A}^T\bm{A}\bm{v}_j = \lambda_j \bm{v}_j = \sigma_j^2 \bm{v}_j$ を代入すると
$$ \bm{u}_i^T\bm{u}_j = \frac{\sigma_j^2 \bm{v}_i^T\bm{v}_j}{\sigma_i\sigma_j} = \frac{\sigma_j}{\sigma_i} \delta_{ij} $$
$i = j$ のとき $\bm{u}_i^T\bm{u}_i = 1$、$i \neq j$ のとき $\bm{u}_i^T\bm{u}_j = 0$ です。よって $\{\bm{u}_1, \ldots, \bm{u}_r\}$ は正規直交系をなします。
ステップ4: 完全な直交行列への拡張
$\bm{u}_1, \ldots, \bm{u}_r$ は $\mathbb{R}^m$ の部分空間の正規直交基底です。グラム・シュミットの直交化法で $\bm{u}_{r+1}, \ldots, \bm{u}_m$ を追加すれば、$m \times m$ の完全な直交行列 $\bm{U}$ が構成できます。
これにより $\bm{A} = \bm{U}\bm{\Sigma}\bm{V}^T$ が得られます。実際に $\bm{A}\bm{v}_i = \sigma_i \bm{u}_i$ であることから $\bm{A}\bm{V} = \bm{U}\bm{\Sigma}$ が成り立ち、$\bm{V}$ が直交行列なので $\bm{A} = \bm{U}\bm{\Sigma}\bm{V}^T$ が導かれます。
コンパクトSVD
非零の特異値 $r$ 個だけを使ったコンパクトSVD(薄いSVD)は
$$ \begin{equation} \bm{A} = \bm{U}_r \bm{\Sigma}_r \bm{V}_r^T = \sum_{i=1}^{r} \sigma_i \bm{u}_i \bm{v}_i^T \end{equation} $$
各 $\sigma_i \bm{u}_i \bm{v}_i^T$ はランク1行列であり、SVDは行列をランク1行列の重み付き和として分解します。
具体的な数値計算例
$3 \times 2$ 行列のSVDを手計算で求めてみましょう。
$$ \bm{A} = \begin{pmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \end{pmatrix} $$
ステップ1: $\bm{A}^T\bm{A}$ を計算
$$ \bm{A}^T\bm{A} = \begin{pmatrix} 1 & 0 & 1 \\ 1 & 1 & 0 \end{pmatrix} \begin{pmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \end{pmatrix} = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} $$
ステップ2: 固有値を求める
特性方程式 $\det(\bm{A}^T\bm{A} – \lambda\bm{I}) = 0$ を解きます。
$$ (2 – \lambda)^2 – 1 = 0 \implies \lambda^2 – 4\lambda + 3 = 0 \implies (\lambda – 3)(\lambda – 1) = 0 $$
固有値は $\lambda_1 = 3$、$\lambda_2 = 1$ です。特異値は $\sigma_1 = \sqrt{3}$、$\sigma_2 = 1$ です。
ステップ3: 右特異ベクトル $\bm{V}$ を求める
$\lambda_1 = 3$ の固有ベクトル: $(\bm{A}^T\bm{A} – 3\bm{I})\bm{v} = \bm{0}$ を解くと
$$ \begin{pmatrix} -1 & 1 \\ 1 & -1 \end{pmatrix} \bm{v} = \bm{0} \implies \bm{v}_1 = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\ 1 \end{pmatrix} $$
$\lambda_2 = 1$ の固有ベクトル: $(\bm{A}^T\bm{A} – \bm{I})\bm{v} = \bm{0}$ を解くと
$$ \begin{pmatrix} 1 & 1 \\ 1 & 1 \end{pmatrix} \bm{v} = \bm{0} \implies \bm{v}_2 = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\ -1 \end{pmatrix} $$
ステップ4: 左特異ベクトル $\bm{U}$ を求める
$\bm{u}_i = \bm{A}\bm{v}_i / \sigma_i$ で計算します。
$$ \bm{u}_1 = \frac{1}{\sqrt{3}} \bm{A} \bm{v}_1 = \frac{1}{\sqrt{3}} \begin{pmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \end{pmatrix} \frac{1}{\sqrt{2}} \begin{pmatrix} 1 \\ 1 \end{pmatrix} = \frac{1}{\sqrt{6}} \begin{pmatrix} 2 \\ 1 \\ 1 \end{pmatrix} $$
$$ \bm{u}_2 = \frac{1}{1} \bm{A} \bm{v}_2 = \begin{pmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \end{pmatrix} \frac{1}{\sqrt{2}} \begin{pmatrix} 1 \\ -1 \end{pmatrix} = \frac{1}{\sqrt{2}} \begin{pmatrix} 0 \\ -1 \\ 1 \end{pmatrix} $$
ステップ5: 検算
$\bm{U}_r \bm{\Sigma}_r \bm{V}_r^T$ を計算して元の $\bm{A}$ と一致するか確認します。
$$ \sigma_1 \bm{u}_1 \bm{v}_1^T = \sqrt{3} \cdot \frac{1}{\sqrt{6}} \begin{pmatrix} 2 \\ 1 \\ 1 \end{pmatrix} \cdot \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \end{pmatrix} = \frac{1}{2} \begin{pmatrix} 2 & 2 \\ 1 & 1 \\ 1 & 1 \end{pmatrix} $$
$$ \sigma_2 \bm{u}_2 \bm{v}_2^T = 1 \cdot \frac{1}{\sqrt{2}} \begin{pmatrix} 0 \\ -1 \\ 1 \end{pmatrix} \cdot \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & -1 \end{pmatrix} = \frac{1}{2} \begin{pmatrix} 0 & 0 \\ -1 & 1 \\ 1 & -1 \end{pmatrix} $$
和を取ると
$$ \bm{A} = \frac{1}{2}\begin{pmatrix} 2 & 2 \\ 1 & 1 \\ 1 & 1 \end{pmatrix} + \frac{1}{2}\begin{pmatrix} 0 & 0 \\ -1 & 1 \\ 1 & -1 \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \end{pmatrix} $$
確かに元の行列 $\bm{A}$ が復元されました。この例から、SVDが行列をランク1行列の重み付き和として分解していることが実感できます。第1成分($\sigma_1 = \sqrt{3}$)は行列の主要な構造を表し、第2成分($\sigma_2 = 1$)は残りの詳細を補っています。
SVDの理論を理解したところで、その最も重要な応用である低ランク近似を見てみましょう。
低ランク近似
エッカート・ヤングの定理
定理(エッカート・ヤング): $\bm{A}$ のSVDが $\bm{A} = \sum_{i=1}^r \sigma_i \bm{u}_i \bm{v}_i^T$ のとき、ランク $k$($k \leq r$)の行列で $\bm{A}$ に最も近い(フロベニウスノルムの意味で)行列は
$$ \begin{equation} \bm{A}_k = \sum_{i=1}^{k} \sigma_i \bm{u}_i \bm{v}_i^T \end{equation} $$
であり、近似誤差は
$$ \|\bm{A} – \bm{A}_k\|_F = \sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2} $$
つまり、SVDの上位 $k$ 個の特異値だけを残せば、情報の損失を最小にしたランク $k$ の近似が得られるのです。
この定理の重要性を強調しましょう。ランク $k$ の $m \times n$ 行列は全部で(連続的に)無限個あります。その中で最良の近似がSVDの上位 $k$ 成分で得られるというのは、非自明かつ強力な結果です。最適な近似を探索する必要がなく、SVDを計算するだけで自動的に最良の近似が得られます。
先ほどの $3 \times 2$ 行列の例でランク1近似を計算してみましょう。
$$ \bm{A}_1 = \sigma_1 \bm{u}_1 \bm{v}_1^T = \frac{1}{2}\begin{pmatrix} 2 & 2 \\ 1 & 1 \\ 1 & 1 \end{pmatrix} = \begin{pmatrix} 1 & 1 \\ 0.5 & 0.5 \\ 0.5 & 0.5 \end{pmatrix} $$
近似誤差は
$$ \|\bm{A} – \bm{A}_1\|_F = \sigma_2 = 1 $$
一方、全体のフロベニウスノルムは $\|\bm{A}\|_F = \sqrt{\sigma_1^2 + \sigma_2^2} = \sqrt{3 + 1} = 2$ です。ランク1近似で捉えられる情報量は $\sigma_1^2 / (\sigma_1^2 + \sigma_2^2) = 3/4 = 75\%$ です。つまり、たった1成分で元の行列の75%の情報を再現できています。
情報量の解釈
特異値の二乗 $\sigma_i^2$ は、$i$ 番目の成分が「捉えている情報量」(分散とも解釈できる)に対応します。上位 $k$ 個の特異値で捉えられる情報の割合は
$$ \frac{\sum_{i=1}^k \sigma_i^2}{\sum_{i=1}^r \sigma_i^2} $$
多くの実データでは特異値が急速に減衰するため、少数の成分で元の行列の大部分の情報を再現できます。たとえば、$1000 \times 1000$ の自然画像データでは、通常50個程度の特異値で元の情報の95%以上を再現できます。これが画像圧縮の原理です。
データ圧縮としての解釈
低ランク近似はデータ圧縮としても捉えられます。元の $m \times n$ 行列を保存するには $mn$ 個の数値が必要ですが、ランク $k$ 近似 $\bm{A}_k = \bm{U}_k \bm{\Sigma}_k \bm{V}_k^T$ では $mk + k + kn = k(m + n + 1)$ 個の数値だけで済みます。
たとえば $1000 \times 1000$ の行列(100万個の数値)のランク50近似では、$50 \times (1000 + 1000 + 1) = 100{,}050$ 個の数値で済み、元の約10分の1のストレージで95%以上の情報を保持できます。
擬似逆行列
$\bm{A}$ が正方でない場合の「逆行列」の代わりとなるのがムーア・ペンローズの擬似逆行列です。SVDを使って
$$ \begin{equation} \bm{A}^+ = \bm{V}\bm{\Sigma}^+\bm{U}^T \end{equation} $$
ここで $\bm{\Sigma}^+$ は $\bm{\Sigma}$ の非零対角成分の逆数を取り、転置した行列です。具体的には、$\bm{\Sigma}$ の対角成分 $\sigma_i > 0$ を $1/\sigma_i$ に置き換え、ゼロの対角成分はゼロのまま残し、行列を転置します。
最小二乗解 $\bm{x}^* = \arg\min \|\bm{A}\bm{x} – \bm{b}\|$ は $\bm{x}^* = \bm{A}^+\bm{b}$ で与えられます。
先ほどの $3 \times 2$ 行列の例で擬似逆行列を求めてみましょう。$\bm{\Sigma} = \begin{pmatrix} \sqrt{3} & 0 \\ 0 & 1 \\ 0 & 0 \end{pmatrix}$ なので
$$ \bm{\Sigma}^+ = \begin{pmatrix} 1/\sqrt{3} & 0 & 0 \\ 0 & 1 & 0 \end{pmatrix} $$
$\bm{A}^+ = \bm{V}\bm{\Sigma}^+\bm{U}^T$ は $2 \times 3$ 行列となります。これにベクトル $\bm{b} = (3, 1, 2)^T$ を掛けると、$\bm{A}\bm{x} = \bm{b}$ の最小二乗解が得られます。
擬似逆行列が通常の逆行列の一般化であることを確認しましょう。$\bm{A}$ が正方かつ正則ならば、すべての特異値が正なので $\bm{A}^+ = \bm{V}\bm{\Sigma}^{-1}\bm{U}^T = (\bm{U}\bm{\Sigma}\bm{V}^T)^{-1} = \bm{A}^{-1}$ となります。
SVDと主成分分析(PCA)
SVDの重要な応用の一つが主成分分析(PCA)です。データ行列 $\bm{X}$(各行が1つのデータ点、各列が特徴量)を中心化(列平均を引く)した後のSVDを考えると
$$ \bm{X}_c = \bm{U}\bm{\Sigma}\bm{V}^T $$
このとき、$\bm{V}$ の列が主成分方向を表し、$\sigma_i^2 / (n-1)$ が第 $i$ 主成分の分散に対応します。つまり、PCAは中心化データ行列のSVDそのものです。
PCAの目的は「データの分散が最大となる方向を見つける」ことですが、これはSVDの右特異ベクトル $\bm{v}_1$ の方向に他なりません。第1特異ベクトルの方向にデータを射影すると、最大の分散が得られます。第2特異ベクトルは第1に直交する方向で最大の分散を持つ方向です。
理論を学んだところで、Pythonで画像圧縮の例を実装しましょう。
Pythonでの実装と可視化
SVDの幾何学と低ランク近似
import numpy as np
import matplotlib.pyplot as plt
# ランダム行列のSVD
np.random.seed(42)
A = np.random.randn(5, 3) @ np.random.randn(3, 4) + 0.1 * np.random.randn(5, 4)
# これはランク3に近い5x4行列
U, S, Vt = np.linalg.svd(A, full_matrices=False)
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# (a) 特異値のスペクトル
ax = axes[0]
ax.bar(range(1, len(S)+1), S, color='steelblue', alpha=0.8)
ax.set_xlabel('Index i', fontsize=12)
ax.set_ylabel(r'$\sigma_i$', fontsize=12)
ax.set_title('Singular Values', fontsize=13)
ax.grid(True, alpha=0.3, axis='y')
# 情報量の累積
ax2 = ax.twinx()
cumulative = np.cumsum(S**2) / np.sum(S**2) * 100
ax2.plot(range(1, len(S)+1), cumulative, 'ro-', markersize=8)
ax2.set_ylabel('Cumulative energy (%)', fontsize=10, color='red')
ax2.tick_params(axis='y', labelcolor='red')
# (b) 低ランク近似の誤差
ax = axes[1]
errors = []
for k in range(1, len(S)+1):
A_k = U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
errors.append(np.linalg.norm(A - A_k, 'fro'))
ax.plot(range(1, len(S)+1), errors, 'bo-', markersize=8, linewidth=2)
ax.set_xlabel('Rank k', fontsize=12)
ax.set_ylabel(r'$\|A - A_k\|_F$', fontsize=12)
ax.set_title('Low-rank Approximation Error', fontsize=13)
ax.grid(True, alpha=0.3)
# (c) 画像圧縮のシミュレーション
ax = axes[2]
# 簡単な画像として行列を使う
m, n = 64, 64
X, Y = np.meshgrid(np.linspace(0, 1, n), np.linspace(0, 1, m))
image = np.sin(3*np.pi*X) * np.cos(5*np.pi*Y) + 0.5*np.exp(-((X-0.5)**2+(Y-0.5)**2)/0.1)
U_img, S_img, Vt_img = np.linalg.svd(image, full_matrices=False)
# 圧縮率を計算
ranks = [1, 5, 10, 20, 64]
compression_ratios = []
for k in ranks:
original_size = m * n
compressed_size = m * k + k + k * n # U_k + S_k + V_k^T
compression_ratios.append(original_size / compressed_size)
errors_img = np.linalg.norm(image - U_img[:,:k] @ np.diag(S_img[:k]) @ Vt_img[:k,:], 'fro')
ax.semilogy(range(1, len(S_img)+1), S_img, 'b-', linewidth=2)
ax.set_xlabel('Index', fontsize=12)
ax.set_ylabel(r'$\sigma_i$ (log scale)', fontsize=12)
ax.set_title('Singular Values of Synthetic Image', fontsize=13)
ax.grid(True, alpha=0.3, which='both')
plt.tight_layout()
plt.savefig('svd_detail.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフから、SVDの実用的な性質が確認できます。
-
左図(特異値スペクトル): 特異値が急速に減少し、最初の3つで累積エネルギーのほぼ100%を占めています。これは元の行列がランク3に近い構造(3つの独立なランク1行列の和にノイズを加えたもの)を反映しています。赤い点で示された累積エネルギーは、特異値の二乗和の累積比率 $\sum_{i=1}^k \sigma_i^2 / \sum_{i=1}^r \sigma_i^2$ です。$k = 3$ で99%以上に達しており、残りの特異値はほぼノイズに対応していることがわかります。
-
中央図(低ランク近似誤差): ランク $k$ を増やすにつれて近似誤差 $\|\bm{A} – \bm{A}_k\|_F$ が単調に減少し、$k = 3$ で誤差がほぼゼロになっています。これはエッカート・ヤングの定理から保証される性質であり、$\|\bm{A} – \bm{A}_k\|_F = \sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2}$ という公式と一致します。この単調減少は、各特異値成分が独立な情報を追加していることを意味しています。
-
右図(合成画像の特異値): 連続的な関数($\sin$ と $\cos$ とガウス関数の重ね合わせ)から生成された $64 \times 64$ の画像でも特異値は急速に減衰しています。対数スケールで直線的に減少していることから、特異値が指数的に減衰していることがわかります。このような急速な減衰は自然画像や滑らかなデータで一般的に見られる性質であり、低ランク近似が効果的であることの根拠です。
SVDの数値安定性
SVDは数値計算の観点からも非常に優れた性質を持っています。特異値は常に非負であり、条件数 $\kappa(\bm{A}) = \sigma_1 / \sigma_r$ が行列の「数値的な良さ」を直接測れます。
条件数が大きい行列(悪条件行列)は、最大特異値と最小特異値の比が大きく、数値計算で大きな丸め誤差が生じます。擬似逆行列の計算では、非常に小さい特異値を無視する(閾値以下をゼロとみなす)ことで、数値的な安定性を確保するのが一般的です。この閾値を決めるための基準として
$$ \text{tol} = \max(m, n) \cdot \sigma_1 \cdot \epsilon_{\text{machine}} $$
がよく使われます。NumPyの np.linalg.pinv もこの基準を採用しています。
まとめ
本記事では、特異値分解(SVD)の理論と応用について、直感的な説明から厳密な導出、具体的な数値計算例、Pythonによる実装まで一貫して解説しました。
- SVD $\bm{A} = \bm{U}\bm{\Sigma}\bm{V}^T$ は任意のサイズの行列に適用可能な分解であり、「回転→スケーリング→回転」と解釈できる
- 導出は $\bm{A}^T\bm{A}$ の固有値分解から出発し、特異値 $\sigma_i = \sqrt{\lambda_i}$ と右特異ベクトル $\bm{v}_i$ から左特異ベクトル $\bm{u}_i = \bm{A}\bm{v}_i / \sigma_i$ を構成する
- 特異値 $\sigma_i$ は $\bm{A}^T\bm{A}$ の固有値の正の平方根であり、行列の「重要度」の降順に並ぶ
- エッカート・ヤングの定理により、SVDの上位 $k$ 成分で最良のランク $k$ 近似が得られ、近似誤差は $\sqrt{\sigma_{k+1}^2 + \cdots + \sigma_r^2}$ で与えられる
- 低ランク近似はデータ圧縮として解釈でき、$k(m+n+1)$ 個の数値で元の $mn$ 個の数値を近似する
- 擬似逆行列 $\bm{A}^+ = \bm{V}\bm{\Sigma}^+\bm{U}^T$ で最小二乗解が求まり、通常の逆行列の一般化となる
- PCAは中心化データ行列のSVDそのものであり、機械学習の次元削減に不可欠
- 画像圧縮、推薦システム、潜在意味解析など幅広い応用を持つ
次のステップとして、以下の記事も参考にしてください。
- 固有値分解の理論と応用 — SVDの基礎となる固有値分解
- 行列式の定義・計算方法・幾何学的意味 — 行列の基本