Pandas & NumPy Academy · レッスン

固有値とSVDの概要

np.linalg.eigで固有値と固有ベクトルを計算し、SVDがPCAによる次元削減をどのように支えているか理解します。

レッスン 4/413 ステップ

「固有値とSVDの概要」はCoddyKit上の無料Pandas & NumPy Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPandas & NumPy Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

固有値と固有ベクトルとは

正方行列 A の固有ベクトルとは、A @ v = lambda * v を満たすゼロではないベクトル v のことです。A を掛けても v の方向は変わらず、拡大・縮小されるだけです。スカラーlambdaを、v に対応する固有値と呼びます。固有値から、線形変換に固有の「伸縮率」がわかります。たとえば固有値が 2 なら、行列は固有ベクトルの方向の長さを 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 の対角成分)は常に非負で、通常は降順に並べられます。ゼロではない特異値の個数は、行列のランクに等しくなります。ほぼゼロの特異値は、行または列がほぼ線形従属であることを示します。最大特異値は行列のスペクトルノルムを表し、最大の非ゼロ特異値と最小の非ゼロ特異値の比は、数値的な安定性を測るために使われる条件数です。

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 個の特異値とベクトルだけを残し、元の行列の近似を再構成します。これは画像圧縮や推薦のための協調フィルタリングの基礎です。切り truncated 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 では、各反復を @ による 1 回の行列とベクトルの積で実行できます。

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 ファイルをチャンク単位でストリーミングして、大規模なデータセットを扱う方法に取り組みます。

無料で開始

AI チューターと学ぶ Python — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「固有値とSVDの概要」レッスンは無料ですか?

はい。「固有値とSVDの概要」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Pandas & NumPy Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Pandas & NumPy Academyコースには全4レッスンが含まれています。

「固有値とSVDの概要」で何を学びますか?

np.linalg.eigで固有値と固有ベクトルを計算し、SVDがPCAによる次元削減をどのように支えているか理解します。 ブラウザで直接実行するハンズオンコードでPandas & NumPy Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Pandas & NumPy Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPandas & NumPy Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「固有値とSVDの概要」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPandas & NumPy Academyレッスンでコードを書いて実行できますか?

はい。すべてのPandas & NumPy Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. np.matmulと@による行列の乗算
  2. 行列式、逆行列、転置行列
  3. 連立一次方程式を解く
  4. 固有値とSVDの概要
← Pandas & NumPy Academyに戻る