Skip to content

필사 모드: 線形代数学完全ガイド:ベクトルからSVDまでゼロからヒーローへ

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに

線形代数学(Linear Algebra)は現代数学と工学の根幹をなす分野です。データサイエンス、機械学習、コンピュータグラフィックス、量子力学まで、ほぼすべての技術分野で活用されています。本ガイドでは、ベクトルと行列の基礎から特異値分解(SVD)まで、線形代数の主要概念を体系的に解説します。

**参考資料:**

- Gilbert Strang, MIT OCW 18.06 Linear Algebra

- 3Blue1Brown: Essence of Linear Algebra (YouTube)

- NumPy公式ドキュメント(numpy.org)

- scikit-learn PCAドキュメント

1. ベクトル (Vectors)

ベクトルの定義と表現

ベクトルは**大きさ(magnitude)**と**向き(direction)**を持つ数学的オブジェクトです。$n$次元ベクトル $\mathbf{v}$ は列ベクトルとして表現されます:

$$\mathbf{v} = \begin{pmatrix} v_1 \\ v_2 \\ \vdots \\ v_n \end{pmatrix} \in \mathbb{R}^n$$

ベクトル演算

**加算とスカラー倍:**

$$\mathbf{u} + \mathbf{v} = \begin{pmatrix} u_1 + v_1 \\ u_2 + v_2 \end{pmatrix}, \quad c\mathbf{v} = \begin{pmatrix} cv_1 \\ cv_2 \end{pmatrix}$$

**内積(ドット積):**

$$\mathbf{u} \cdot \mathbf{v} = \sum_{i=1}^{n} u_i v_i = \|\mathbf{u}\| \|\mathbf{v}\| \cos\theta$$

内積が $0$ のとき、2つのベクトルは**直交(orthogonal)**しています。

**外積(クロス積)** — 3次元のみ:

$$\mathbf{u} \times \mathbf{v} = \begin{vmatrix} \mathbf{i} & \mathbf{j} & \mathbf{k} \\ u_1 & u_2 & u_3 \\ v_1 & v_2 & v_3 \end{vmatrix}$$

ノルム(Norm)

- **L1ノルム(マンハッタン距離):** $\|\mathbf{v}\|_1 = \sum_{i} |v_i|$

- **L2ノルム(ユークリッド距離):** $\|\mathbf{v}\|_2 = \sqrt{\sum_{i} v_i^2}$

- **Lpノルム:** $\|\mathbf{v}\|_p = \left(\sum_{i} |v_i|^p\right)^{1/p}$

**単位ベクトル(正規化):**

$$\hat{\mathbf{v}} = \frac{\mathbf{v}}{\|\mathbf{v}\|}$$

ベクトルの定義

a = np.array([1, 2, 3])

b = np.array([4, 5, 6])

加算

print("加算:", a + b) # [5 7 9]

スカラー倍

print("スカラー倍:", 3 * a) # [3 6 9]

内積

dot = np.dot(a, b)

print("内積:", dot) # 32

外積

cross = np.cross(a, b)

print("外積:", cross) # [-3 6 -3]

L2ノルム

norm_l2 = np.linalg.norm(a)

print("L2ノルム:", norm_l2) # 3.7416...

L1ノルム

norm_l1 = np.linalg.norm(a, ord=1)

print("L1ノルム:", norm_l1) # 6.0

単位ベクトル

unit = a / np.linalg.norm(a)

print("単位ベクトル:", unit)

print("大きさ確認:", np.linalg.norm(unit)) # 1.0

2ベクトルのなす角

cos_theta = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

angle = np.degrees(np.arccos(np.clip(cos_theta, -1, 1)))

print("なす角 (度):", angle)

直交確認

v1, v2 = np.array([1, 0]), np.array([0, 1])

print("直交確認:", np.dot(v1, v2)) # 0

2. 行列 (Matrices)

行列の定義と種類

$m \times n$ 行列は $m$ 行 $n$ 列の数値の矩形配列です:

$$A = \begin{pmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{pmatrix}$$

**主要な特殊行列:**

| 種類 | 定義 | 性質 |

| --------------------- | --------------------------- | ----------------- |

| 単位行列 (Identity) | $I_{ij} = 1$ (i=j), 0 (i≠j) | $AI = IA = A$ |

| 対角行列 (Diagonal) | 対角以外はすべて0 | — |

| 対称行列 (Symmetric) | $A = A^T$ | 実数固有値を持つ |

| 直交行列 (Orthogonal) | $A^T A = I$ | $\det(A) = \pm 1$ |

行列演算

**行列の積(Matrix Multiplication):**

$(AB)_{ij} = \sum_{k=1}^{n} a_{ik} b_{kj}$

行列の積は一般に交換法則が成立しません:$AB \neq BA$

**転置行列(Transpose):** $(A^T)_{ij} = A_{ji}$

**逆行列(Inverse):** $A^{-1}$ は $AA^{-1} = A^{-1}A = I$ を満たします。$\det(A) \neq 0$ のときのみ存在します。

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

B = np.array([[5, 6], [7, 8]])

行列の和

print("A + B:\n", A + B)

行列の積

C = A @ B

print("A @ B:\n", C)

アダマール積(要素ごとの積)

print("A * B (Hadamard):\n", A * B)

転置行列

print("転置 A^T:\n", A.T)

逆行列

A_inv = np.linalg.inv(A)

print("逆行列 A^(-1):\n", A_inv)

print("A @ A^(-1) = I:\n", np.round(A @ A_inv))

単位行列

print("3x3単位行列:\n", np.eye(3))

対角行列

print("対角行列:\n", np.diag([1, 2, 3]))

対称行列の確認

S = A + A.T

print("対称行列か:", np.allclose(S, S.T))

フロベニウスノルム

print("フロベニウスノルム:", np.linalg.norm(A, 'fro'))

3. 行列式 (Determinant)

行列式の定義と計算

行列式(determinant)は正方行列に定義されるスカラー値で、行列の重要な性質をエンコードします。

**2×2行列式:**

$$\det\begin{pmatrix} a & b \\ c & d \end{pmatrix} = ad - bc$$

**3×3行列式(余因子展開):**

$$\det(A) = a_{11}(a_{22}a_{33} - a_{23}a_{32}) - a_{12}(a_{21}a_{33} - a_{23}a_{31}) + a_{13}(a_{21}a_{32} - a_{22}a_{31})$$

行列式の幾何学的意味

行列式の絶対値は、行ベクトルが作る**平行六面体の体積**に等しくなります。行列式が0の場合、行列は空間を「潰す」変換を表します。

行列式の重要な性質

1. $\det(I) = 1$

2. $\det(AB) = \det(A)\det(B)$

3. $\det(A^T) = \det(A)$

4. $\det(A^{-1}) = 1/\det(A)$

5. $\det(A) = 0 \iff$ 行列は特異(逆行列なし)

クラメルの公式 (Cramer's Rule)

$A\mathbf{x} = \mathbf{b}$ に対して:

$$x_i = \frac{\det(A_i)}{\det(A)}$$

2x2行列式

A2 = np.array([[3, 1], [2, 4]])

print("det([[3,1],[2,4]]):", np.linalg.det(A2)) # 10.0

3x3行列式

A3 = np.array([[1, 2, 3],

[4, 5, 6],

[7, 8, 10]])

print("det(A3):", np.linalg.det(A3)) # -3.0

性質の検証

B = np.array([[2, 0], [0, 3]])

print("det(A2)*det(B):", np.linalg.det(A2) * np.linalg.det(B))

print("det(A2@B):", np.linalg.det(A2 @ B))

特異行列

singular = np.array([[1, 2], [2, 4]]) # 2行目 = 2倍の1行目

print("特異行列 det:", np.linalg.det(singular)) # 約0

クラメルの公式

def cramers_rule(A, b):

det_A = np.linalg.det(A)

n = len(b)

x = np.zeros(n)

for i in range(n):

Ai = A.copy().astype(float)

Ai[:, i] = b

x[i] = np.linalg.det(Ai) / det_A

return x

A_sys = np.array([[2, 1], [5, 3]], dtype=float)

b_sys = np.array([1, 2])

print("\nクラメルの公式:", cramers_rule(A_sys, b_sys))

print("numpy solve:", np.linalg.solve(A_sys, b_sys))

4. 連立方程式とガウス消去法

線形連立方程式

$n$ 個の未知数に対する $m$ 個の線形方程式:$A\mathbf{x} = \mathbf{b}$

解の種類:

- **不能**(解なし):方程式系が矛盾する場合

- **唯一解**:$\det(A) \neq 0$ の場合

- **不定**(無限に多くの解):方程式が冗長な場合

ガウス消去法 (Gaussian Elimination)

行の基本変換で**行階段形(Row Echelon Form)**を作ります:

1. 行の交換:$R_i \leftrightarrow R_j$

2. 行のスカラー倍:$R_i \leftarrow c \cdot R_i$

3. 行の和:$R_i \leftarrow R_i + c \cdot R_j$

**ガウス-ジョルダン消去法**では**簡約行階段形(RREF)**まで変換します。

LU分解

$A = LU$:下三角行列 $L$ と上三角行列 $U$ の積への分解。

from scipy import linalg

連立方程式の解法

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

[-3, -1, 2],

[-2, 1, 2]], dtype=float)

b = np.array([8, -11, -3], dtype=float)

numpy solve

x = np.linalg.solve(A, b)

print("解:", x) # [2. 3. -1.]

print("検証 A@x:", A @ x)

ガウス-ジョルダン消去法の実装

def gauss_jordan(A, b):

n = len(b)

aug = np.hstack([A.astype(float), b.reshape(-1,1).astype(float)])

for col in range(n):

max_row = np.argmax(np.abs(aug[col:, col])) + col

aug[[col, max_row]] = aug[[max_row, col]]

aug[col] = aug[col] / aug[col, col]

for row in range(n):

if row != col:

aug[row] -= aug[row, col] * aug[col]

return aug[:, -1]

x_gj = gauss_jordan(A.copy(), b.copy())

print("ガウス-ジョルダン解:", x_gj)

LU分解

P, L, U = linalg.lu(A)

print("\nL行列:\n", np.round(L, 4))

print("U行列:\n", np.round(U, 4))

LU分解で連立方程式を解く

y = linalg.solve_triangular(L, P.T @ b, lower=True)

x_lu = linalg.solve_triangular(U, y)

print("LU分解解:", x_lu)

5. ベクトル空間 (Vector Spaces)

ベクトル空間の定義

集合 $V$ がベクトル空間であるためには、加算とスカラー倍に関する8つの公理を満たす必要があります:

1. 加算の閉包性:$\mathbf{u} + \mathbf{v} \in V$

2. 加算の交換法則:$\mathbf{u} + \mathbf{v} = \mathbf{v} + \mathbf{u}$

3. 加算の結合法則

4. 零ベクトルの存在

5. 加法逆元の存在

6. スカラー倍の閉包性:$c\mathbf{v} \in V$

7. 分配法則1:$c(\mathbf{u}+\mathbf{v}) = c\mathbf{u} + c\mathbf{v}$

8. 分配法則2:$(c+d)\mathbf{v} = c\mathbf{v} + d\mathbf{v}$

線形独立 (Linear Independence)

ベクトル集合 $\{\mathbf{v}_1, \ldots, \mathbf{v}_k\}$ が**線形独立**であるとは:

$$c_1\mathbf{v}_1 + c_2\mathbf{v}_2 + \cdots + c_k\mathbf{v}_k = \mathbf{0} \implies c_1 = c_2 = \cdots = c_k = 0$$

基底 (Basis) と次元 (Dimension)

**基底**とはベクトル空間を張る(span)線形独立なベクトルの集合です。基底の元の個数が**次元**です。

4つの基本部分空間

行列 $A \in \mathbb{R}^{m \times n}$, $r = \text{rank}(A)$ に対して:

| 部分空間 | 所属 | 次元 |

| ---------------------- | -------------- | ----- |

| 行空間(Row space) | $\mathbb{R}^n$ | $r$ |

| 列空間(Column space) | $\mathbb{R}^m$ | $r$ |

| 零空間(Null space) | $\mathbb{R}^n$ | $n-r$ |

| 左零空間 | $\mathbb{R}^m$ | $m-r$ |

**ランク・零化域定理:** $\text{rank}(A) + \text{nullity}(A) = n$

from scipy.linalg import null_space

A = np.array([[1, 2, 3],

[4, 5, 6],

[2, 4, 6]]) # 3行目は1行目の2倍(線形従属)

print("ランク:", np.linalg.matrix_rank(A)) # 2

零空間の基底

ns = null_space(A)

print("零空間の次元:", ns.shape[1]) # 1

print("零空間:\n", ns)

検証:A @ ns ≈ 0

print("A @ 零空間:\n", np.round(A @ ns, 10))

線形独立性の確認

v1 = np.array([1, 0, 0])

v2 = np.array([0, 1, 0])

v3 = np.array([1, 1, 0]) # v1 + v2 → 線形従属

M = np.column_stack([v1, v2, v3])

print("\n[v1, v2, v3]のランク:", np.linalg.matrix_rank(M)) # 2(従属)

v3_ind = np.array([0, 0, 1])

M2 = np.column_stack([v1, v2, v3_ind])

print("[v1, v2, v3_ind]のランク:", np.linalg.matrix_rank(M2)) # 3(独立)

6. 線形変換 (Linear Transformations)

線形変換の定義

関数 $T: V \to W$ が**線形変換**であるとは:

1. $T(\mathbf{u} + \mathbf{v}) = T(\mathbf{u}) + T(\mathbf{v})$(加法性)

2. $T(c\mathbf{v}) = cT(\mathbf{v})$(斉次性)

核と像

**核(Kernel):** $\ker(T) = \{\mathbf{v} \in V : T(\mathbf{v}) = \mathbf{0}\}$

**像(Image):** $\text{Im}(T) = \{T(\mathbf{v}) : \mathbf{v} \in V\}$

**次元定理:** $\dim(\ker T) + \dim(\text{Im} T) = \dim V$

2次元の幾何変換

**回転行列(角度 $\theta$):**

$$R(\theta) = \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix}$$

**x軸に関する反射:**

$$F_x = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}$$

**せん断変換(Shear):**

$$H = \begin{pmatrix} 1 & k \\ 0 & 1 \end{pmatrix}$$

回転行列

def rotation_2d(deg):

theta = np.radians(deg)

return np.array([[np.cos(theta), -np.sin(theta)],

[np.sin(theta), np.cos(theta)]])

R90 = rotation_2d(90)

v = np.array([1.0, 0.0])

print("90度回転:", R90 @ v) # [0, 1]

R45 = rotation_2d(45)

print("45度回転:", np.round(R45 @ v, 4)) # [0.7071, 0.7071]

変換の合成(回転してから反射)

Fx = np.array([[1, 0], [0, -1]])

T = Fx @ R90

print("回転+反射:", T @ v) # [0, -1]

直交行列の性質

print("R^T @ R = I:", np.allclose(R90.T @ R90, np.eye(2)))

print("det(R) =", np.linalg.det(R90)) # 1.0

射影行列

u = np.array([1, 1]) / np.sqrt(2) # y=x方向の単位ベクトル

P = np.outer(u, u)

w = np.array([3, 1])

print("y=xへの射影:", P @ w) # [2, 2]

7. 内積空間 (Inner Product Spaces)

内積の定義

**内積** $\langle \cdot, \cdot \rangle: V \times V \to \mathbb{R}$ は以下を満たします:

1. **正定値性:** $\langle \mathbf{v}, \mathbf{v} \rangle \geq 0$(等号は $\mathbf{v} = \mathbf{0}$ のときのみ)

2. **対称性:** $\langle \mathbf{u}, \mathbf{v} \rangle = \langle \mathbf{v}, \mathbf{u} \rangle$

3. **双線形性:** $\langle a\mathbf{u} + b\mathbf{v}, \mathbf{w} \rangle = a\langle \mathbf{u}, \mathbf{w} \rangle + b\langle \mathbf{v}, \mathbf{w} \rangle$

コーシー-シュワルツ不等式

$$|\langle \mathbf{u}, \mathbf{v} \rangle| \leq \|\mathbf{u}\| \cdot \|\mathbf{v}\|$$

等号成立条件:$\mathbf{u}$ と $\mathbf{v}$ が平行なとき。

グラム-シュミット過程 (Gram-Schmidt Process)

線形独立なベクトル $\mathbf{v}_1, \ldots, \mathbf{v}_k$ から正規直交基底を構築します:

$$\mathbf{u}_j = \mathbf{v}_j - \sum_{i=1}^{j-1} \frac{\langle \mathbf{v}_j, \mathbf{u}_i \rangle}{\langle \mathbf{u}_i, \mathbf{u}_i \rangle} \mathbf{u}_i, \quad \mathbf{e}_j = \frac{\mathbf{u}_j}{\|\mathbf{u}_j\|}$$

これはQR分解の基礎となります。

def gram_schmidt(vectors):

"""グラム-シュミット正規直交化"""

basis = []

for v in vectors:

w = np.array(v, dtype=float)

for b in basis:

w -= np.dot(w, b) * b

norm = np.linalg.norm(w)

if norm > 1e-10:

basis.append(w / norm)

return np.array(basis)

グラム-シュミット適用

v1 = np.array([1, 1, 0])

v2 = np.array([1, 0, 1])

v3 = np.array([0, 1, 1])

Q = gram_schmidt([v1, v2, v3])

print("正規直交基底:")

for i, q in enumerate(Q):

print(f" e{i+1} = {np.round(q, 4)}")

直交性確認

print("\n直交性確認 (Q @ Q^T = I):\n", np.round(Q @ Q.T))

QR分解(グラム-シュミットと等価)

A = np.column_stack([v1, v2, v3])

Q_qr, R = np.linalg.qr(A)

print("QR分解Q:\n", np.round(Q_qr, 4))

print("R(上三角):\n", np.round(R, 4))

8. 固有値と固有ベクトル (Eigenvalues & Eigenvectors)

定義

正方行列 $A$ に対して次を満たすスカラー $\lambda$ と零でないベクトル $\mathbf{v}$:

$$A\mathbf{v} = \lambda\mathbf{v}$$

- $\lambda$:**固有値(eigenvalue)**

- $\mathbf{v}$:$\lambda$ に対応する**固有ベクトル(eigenvector)**

固有ベクトルは $A$ による変換で方向が変わらず、大きさだけが $\lambda$ 倍になります。

特性方程式

$$\det(A - \lambda I) = 0$$

この多項式(特性多項式)の根が固有値です。

**例:**

$$A = \begin{pmatrix} 4 & 1 \\ 2 & 3 \end{pmatrix} \implies \lambda^2 - 7\lambda + 10 = (\lambda-2)(\lambda-5) = 0$$

固有値:$\lambda_1 = 2$, $\lambda_2 = 5$

固有値分解(対角化)

対角化可能な行列 $A$ は:

$$A = P \Lambda P^{-1}$$

ここで $\Lambda = \text{diag}(\lambda_1, \ldots, \lambda_n)$、$P$ の列は固有ベクトル。

**応用:** $A^k = P\Lambda^k P^{-1}$ — 行列の累乗が簡単に計算可能!

対称行列のスペクトル定理

実対称行列 $A = A^T$ は:

1. すべての固有値が**実数**

2. 異なる固有値の固有ベクトルは**直交**

3. $A = Q\Lambda Q^T$(直交対角化可能)

from scipy.linalg import eigh

固有値分解

A = np.array([[4, 1],

[2, 3]])

eigenvalues, eigenvectors = np.linalg.eig(A)

print("固有値:", eigenvalues) # [5., 2.]

print("固有ベクトル(列):\n", eigenvectors)

検証: A @ v = lambda * v

for i in range(len(eigenvalues)):

lam = eigenvalues[i]

v = eigenvectors[:, i]

print(f"\nlambda = {lam:.1f}:")

print(" A @ v:", np.round(A @ v, 4))

print(" lambda * v:", np.round(lam * v, 4))

print(" 一致:", np.allclose(A @ v, lam * v))

対角化: A = P @ Lambda @ P_inv

P = eigenvectors

Lambda = np.diag(eigenvalues)

A_diag = P @ Lambda @ np.linalg.inv(P)

print("\n対角化から再構成:\n", np.round(A_diag.real))

行列の累乗: A^10

k = 10

A_k = P @ np.diag(eigenvalues**k) @ np.linalg.inv(P)

print("A^10 (固有値分解):\n", np.round(A_k.real))

print("A^10 (直接計算):\n", np.linalg.matrix_power(A, k))

対称行列(eigh使用)

B = np.array([[4, 2, 0],

[2, 3, 1],

[0, 1, 5]])

evals, evecs = eigh(B)

print("\n対称行列の固有値:", evals)

print("直交性 Q^T @ Q = I:\n", np.round(evecs.T @ evecs))

トレース = 固有値の和、行列式 = 固有値の積

print("\ntrace(A) =", np.trace(A), "= 固有値の和:", np.sum(eigenvalues).real)

print("det(A) =", np.linalg.det(A), "= 固有値の積:", np.prod(eigenvalues).real)

9. 特異値分解 (SVD - Singular Value Decomposition)

SVDの定義

任意の $m \times n$ 実行列 $A$ は次のように分解されます:

$$A = U \Sigma V^T$$

- $U \in \mathbb{R}^{m \times m}$:**左特異ベクトル**($AA^T$ の固有ベクトル)

- $\Sigma \in \mathbb{R}^{m \times n}$:特異値の対角行列 $\sigma_1 \geq \sigma_2 \geq \cdots \geq 0$

- $V \in \mathbb{R}^{n \times n}$:**右特異ベクトル**($A^TA$ の固有ベクトル)

幾何学的意味

$A = U\Sigma V^T$ は3段階の変換の合成:

1. $V^T$:回転/反射

2. $\Sigma$:座標軸方向の伸縮

3. $U$:回転/反射

低ランク近似

最良ランク $k$ 近似:

$$A_k = \sum_{i=1}^{k} \sigma_i \mathbf{u}_i \mathbf{v}_i^T$$

これが**画像圧縮**や**協調フィルタリング**の基礎です。

PCAとの関係

平均中心化されたデータ行列 $X$ に SVD を適用すると、右特異ベクトル $V$ が**主成分(principal components)**になります。

from sklearn.decomposition import PCA

from sklearn.datasets import load_iris

基本SVD

A = np.array([[3, 2, 2],

[2, 3, -2]], dtype=float)

U, S, Vt = np.linalg.svd(A)

print("U:\n", np.round(U, 4))

print("特異値:", np.round(S, 4))

print("Vt:\n", np.round(Vt, 4))

再構成

m, n = A.shape

Sigma = np.zeros((m, n))

Sigma[:min(m,n), :min(m,n)] = np.diag(S)

A_rec = U @ Sigma @ Vt

print("再構成誤差:", np.linalg.norm(A - A_rec))

低ランク近似

def low_rank_approx(A, k):

U, S, Vt = np.linalg.svd(A, full_matrices=False)

return U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]

np.random.seed(42)

M = np.random.randn(50, 50)

print("\n低ランク近似(50x50行列):")

for k in [1, 5, 10, 25]:

M_k = low_rank_approx(M, k)

rel_err = np.linalg.norm(M - M_k, 'fro') / np.linalg.norm(M, 'fro')

storage = k * (50 + 50 + 1) / (50 * 50)

print(f" k={k:2d}: 相対誤差={rel_err:.4f}, 圧縮比={storage:.3f}")

SVDを使ったPCA

iris = load_iris()

X = iris.data - iris.data.mean(axis=0) # 中心化

U_d, S_d, Vt_d = np.linalg.svd(X, full_matrices=False)

explained_ratio = S_d**2 / (S_d**2).sum()

print("\nIrisデータセット SVD-PCA:")

print("説明分散比(上位4つ):", np.round(explained_ratio, 4))

sklearn PCAとの比較

pca = PCA(n_components=2)

X_pca = pca.fit_transform(X)

print("sklearn PCA説明分散比:", np.round(pca.explained_variance_ratio_, 4))

print("累積寄与率:", round(pca.explained_variance_ratio_.sum(), 4))

10. 行列分解 (Matrix Factorizations)

主要な行列分解の比較

| 分解 | 形式 | 条件 | 主な用途 |

| ---------- | --------------------- | ---------- | -------------- |

| LU分解 | $A = LU$ | 正方行列 | 連立方程式 |

| QR分解 | $A = QR$ | 任意行列 | 最小二乗法 |

| Cholesky | $A = LL^T$ | 対称正定値 | 最適化 |

| SVD | $A = U\Sigma V^T$ | 任意行列 | PCA、圧縮 |

| 固有値分解 | $A = P\Lambda P^{-1}$ | 対角化可能 | スペクトル解析 |

擬似逆行列(Moore-Penrose pseudo-inverse)

$A = U\Sigma V^T$ のとき:

$$A^+ = V\Sigma^+ U^T$$

ここで $\Sigma^+$ は $\Sigma$ の非零対角要素を逆数に置き換えたものです。

from scipy import linalg

np.random.seed(42)

QR分解と最小二乗法

過決定系(方程式 > 未知数)

A = np.random.randn(10, 3)

x_true = np.array([1.0, 2.0, 3.0])

b = A @ x_true + 0.05 * np.random.randn(10)

Q, R = np.linalg.qr(A)

x_qr = np.linalg.solve(R, Q.T @ b)

print("QR最小二乗解:", np.round(x_qr, 4))

print("真の値:", x_true)

numpy lstsq

x_lstsq, _, _, _ = np.linalg.lstsq(A, b, rcond=None)

print("lstsq解:", np.round(x_lstsq, 4))

Cholesky分解

B = np.array([[6, 3, 2],

[3, 5, 1],

[2, 1, 4]], dtype=float)

L = np.linalg.cholesky(B)

print("\nCholesky L:\n", np.round(L, 4))

print("L @ L^T = B:", np.allclose(L @ L.T, B))

擬似逆行列

A_rect = np.array([[1, 2], [3, 4], [5, 6]], dtype=float)

A_pinv = np.linalg.pinv(A_rect)

print("\n擬似逆行列:\n", np.round(A_pinv, 4))

print("A_pinv @ A = I_2:\n", np.round(A_pinv @ A_rect))

条件数(最大/最小特異値の比)

cond = np.linalg.cond(B)

print("\n条件数:", round(cond, 4))

print("数値的に安定?(条件数 < 1000):", cond < 1000)

11. AI/MLにおける線形代数

ニューラルネットワークと行列積

ニューラルネットワークの順伝播(forward pass)は連続する行列積で表現されます:

$$\mathbf{h}^{(l)} = f\!\left(W^{(l)} \mathbf{h}^{(l-1)} + \mathbf{b}^{(l)}\right)$$

バッチ処理では $n$ サンプルを行列 $X \in \mathbb{R}^{n \times d}$ として並列計算します。

Transformerのアテンション機構

スケールドドット積アテンション:

$$\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$

$Q$(クエリ)、$K$(キー)、$V$(バリュー)の3行列を使った純粋な線形代数演算です。

次元削減とPCA

PCAは共分散行列 $C = \frac{1}{n}X^TX$ の固有値分解によって分散が最大の方向を見つけます。

from sklearn.decomposition import PCA

from sklearn.datasets import load_iris

1. ニューラルネットワーク順伝播

np.random.seed(42)

batch_size, d_in, d_hidden, d_out = 32, 784, 128, 10

X_batch = np.random.randn(batch_size, d_in)

W1 = np.random.randn(d_in, d_hidden) * np.sqrt(2.0 / d_in)

b1 = np.zeros(d_hidden)

W2 = np.random.randn(d_hidden, d_out) * np.sqrt(2.0 / d_hidden)

b2 = np.zeros(d_out)

def relu(x): return np.maximum(0, x)

def softmax(x):

ex = np.exp(x - x.max(axis=1, keepdims=True))

return ex / ex.sum(axis=1, keepdims=True)

H1 = relu(X_batch @ W1 + b1)

logits = H1 @ W2 + b2

probs = softmax(logits)

print("順伝播形状:", X_batch.shape, "->", H1.shape, "->", probs.shape)

print("確率の和:", np.allclose(probs.sum(axis=1), 1))

2. スケールドドット積アテンション

def attention(Q, K, V):

d_k = Q.shape[-1]

scores = Q @ K.T / np.sqrt(d_k)

exp_s = np.exp(scores - scores.max(axis=-1, keepdims=True))

weights = exp_s / exp_s.sum(axis=-1, keepdims=True)

return weights @ V, weights

seq_len, d_model = 6, 32

Q = np.random.randn(seq_len, d_model)

K = np.random.randn(seq_len, d_model)

V = np.random.randn(seq_len, d_model)

out, w = attention(Q, K, V)

print("\nアテンション出力:", out.shape)

print("アテンション重みの和:", np.round(w.sum(axis=-1), 4))

3. PCAによる次元削減

iris = load_iris()

X_iris = iris.data

pca = PCA(n_components=2)

X_pca = pca.fit_transform(X_iris)

print("\nIrisデータPCA:")

print("元の次元:", X_iris.shape, "-> 削減後:", X_pca.shape)

print("説明分散比:", np.round(pca.explained_variance_ratio_, 4))

print("累積寄与率:", round(sum(pca.explained_variance_ratio_), 4))

4. 単語埋め込みの類似度

embeddings = {

"king": np.array([0.9, 0.1, 0.8, 0.2]),

"queen": np.array([0.8, 0.2, 0.7, 0.9]),

"man": np.array([0.8, 0.1, 0.2, 0.1]),

"woman": np.array([0.7, 0.2, 0.1, 0.8]),

}

def cos_sim(a, b):

return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

analogy = embeddings["king"] - embeddings["man"] + embeddings["woman"]

print("\n単語アナロジー(king - man + woman):")

for word, emb in embeddings.items():

print(f" {word}との類似度: {cos_sim(analogy, emb):.4f}")

12. クイズ

**答え**:2つのベクトルの内積が $0$ のとき、それらは直交します。

**説明**:内積の公式 $\mathbf{u} \cdot \mathbf{v} = \|\mathbf{u}\|\|\mathbf{v}\|\cos\theta$ より、$\theta = 90°$ のとき $\cos 90° = 0$ となるため内積が $0$ になります。正規直交基底の構築や射影の計算に活用されます。

**答え**:正方行列の行列式が $0$ でない($\det(A) \neq 0$)とき、逆行列が存在します。

**説明**:行列式が $0$ の行列は**特異行列(singular matrix)**と呼ばれ、逆行列は存在しません。これはランク(rank)が行列のサイズより小さいことを意味し、対応する連立方程式は唯一解を持ちません。

**答え**:固有ベクトルは線形変換によって方向が変わらないベクトル、固有値はそのベクトルが何倍に伸縮されるかを示します。

**説明**:$A\mathbf{v} = \lambda\mathbf{v}$ において、行列 $A$ による変換を施しても $\mathbf{v}$ の向きは保たれ、大きさだけが $\lambda$ 倍になります。$\lambda > 1$ なら伸び、$0 < \lambda < 1$ なら縮み、$\lambda < 0$ なら反転します。

**答え**:平均中心化されたデータ行列にSVDを適用すると、PCAと同じ結果が得られます。SVDの右特異ベクトル $V$ がPCAの主成分に対応します。

**説明**:データ行列 $X$ を中心化して SVD を行うと $X = U\Sigma V^T$ が得られます。$V$ の列ベクトルが主成分であり、特異値の二乗が分散の大きさに比例します。数値的安定性のため、scikit-learnの `PCA` も内部でSVDを使用しています。

**答え**:$m \times n$ 行列 $A$ に対して $\text{rank}(A) + \text{nullity}(A) = n$ が成立します。

**説明**:rank は列空間(column space)の次元、nullity は零空間(null space)の次元です。列の数 $n$ は常にこれら2つの次元の和に等しくなります。例えば、$3 \times 4$ 行列のランクが $3$ なら零空間の次元は $1$ です。この定理は連立方程式の解の構造理解に不可欠です。

まとめと学習ロードマップ

線形代数の主要概念は密接に関連しています:

ベクトル -> 行列 -> 行列式 -> 連立方程式

| |

ベクトル空間 -> 線形変換 -> 内積空間

|

固有値・固有ベクトル -> SVD -> AI/ML応用

**次のステップとして推奨する学習リソース:**

1. **Gilbert Strang, MIT OCW 18.06**:線形代数の最も体系的な講義。問題集も充実しています

2. **3Blue1Brown - Essence of Linear Algebra**:幾何学的直観を養うのに最適な動画シリーズ

3. **NumPy公式ドキュメント**:`numpy.linalg` モジュールで全概念を実践

4. **scikit-learn PCAドキュメント**:実際のMLパイプラインでの活用方法

5. **MIT 18.065(Matrix Methods in Data Analysis)**:データ科学・深層学習への応用

線形代数をマスターする秘訣は**幾何学的直観**を育てることです。行列演算が空間に対して何をしているのかを常に視覚化し、NumPyによる実装と組み合わせることで深い理解が得られます。

현재 단락 (1/452)

線形代数学(Linear Algebra)は現代数学と工学の根幹をなす分野です。データサイエンス、機械学習、コンピュータグラフィックス、量子力学まで、ほぼすべての技術分野で活用されています。本ガイドで...

작성 글자: 0원문 글자: 17,597작성 단락: 0/452