跳轉到

5.1 特徵向量:不變的方向#

本節目標#

  • 建立「特徵向量 = 變換下方向不變的向量」這個幾何直覺
  • 理解特徵方程 \(A\mathbf{v} = \lambda \mathbf{v}\) 中每個符號的意義
  • 學會用 \((A - \lambda I)\mathbf{v} = \mathbf{0}\) 推出特徵多項式 \(\det(A - \lambda I) = 0\)
  • 用 linalg_viz 畫出網格變換圖,親眼「找到」不動的方向
  • 接受一個反直覺事實:旋轉矩陣在實數世界裡沒有特徵向量

一個變換,有幾個「敏感方向」?#

回顧第 3 章的結論:矩陣 \(A\) 作用在向量上,通常會同時改變方向與長度。 絕大多數向量被 \(A\) 一打就「歪掉」,例如把 \(\begin{bmatrix} 1 \\ 0 \end{bmatrix}\) 經過 \(A = \begin{bmatrix} 2 & 1 \\ 1 & 2 \end{bmatrix}\) 一乘,方向就偏了。

但總有少數幸運兒——有些向量經過 \(A\) 之後只變長度、不變方向(或恰好反轉)。 這些特殊方向就是整個變換的「骨架」,我們稱之為特徵向量(eigenvector), 而伸縮的倍數稱為特徵值(eigenvalue)。德文 "eigen" 就是「自己的」—— 矩陣自己特有的方向。

特徵方程: \(A\mathbf{v} = \lambda \mathbf{v}\)#

正式定義只有一行:

\[ A\mathbf{v} = \lambda \mathbf{v} \]
  • \(\mathbf{v} \neq \mathbf{0}\) :特徵向量(方向不變)
  • \(\lambda\) :特徵值(伸縮倍數)

三種幾何情況:

\(\lambda\) 的值 幾何意義
\(\lambda > 1\) 方向不變,變長
\(0 < \lambda < 1\) 方向不變,變短
\(\lambda < 0\) 方向反轉(變換到反方向),例如鏡射
\(\lambda = 0\) 被壓扁到原點( \(A\) 不滿秩)

注意「方向不變」包含反轉: \(\begin{bmatrix} 1 \\ 0 \end{bmatrix}\) 與 \(\begin{bmatrix} -1 \\ 0 \end{bmatrix}\) 算同一條直線上的向量, 所以 \(\lambda = -2\) 仍是合法的特徵值。

畫出來看:不動的方向在哪裡?#

用第 1.4 節建立的 linalg_viz 工具箱,我們把網格線和幾支候選向量 一起送進變換,觀察哪些向量「跟著自己走」:

import numpy as np
import linalg_viz as viz

A = np.array([[2.0, 1.0],
              [1.0, 2.0]])

# 候選向量:隨便抓幾個方向試試
candidates = [np.array([1.0, 0.0]),
              np.array([1.0, 1.0]),
              np.array([1.0, -1.0]),
              np.array([2.0, 1.0])]

viz.plot_grid_transform(A)                 # 畫變換前後的網格
viz.draw_vectors(candidates, color='blue')
viz.draw_vectors([A @ v for v in candidates], color='red')
viz.show()

你會在圖上看到一個驚人的現象:

  • \(\begin{bmatrix} 1 \\ 1 \end{bmatrix}\) 變成 \(\begin{bmatrix} 3 \\ 3 \end{bmatrix}\) , 還在同一條對角線上,拉長了 3 倍 → 特徵值 \(3\)
  • \(\begin{bmatrix} 1 \\ -1 \end{bmatrix}\) 變成 \(\begin{bmatrix} 1 \\ -1 \end{bmatrix}\) , 紋風不動 → 特徵值 \(1\)
  • \(\begin{bmatrix} 1 \\ 0 \end{bmatrix}\) 跑到 \(\begin{bmatrix} 2 \\ 1 \end{bmatrix}\) ,方向歪了 → 不是特徵向量
A = np.array([[2.0, 1.0], [1.0, 2.0]])
print(A @ np.array([1.0,  1.0]))   # [3. 3.]   方向不變,lambda = 3
print(A @ np.array([1.0, -1.0]))   # [1. -1.]  方向不變,lambda = 1
print(A @ np.array([1.0,  0.0]))   # [2. 1.]   方向變了

怎麼「算」出特徵向量?#

畫圖靠運氣,要系統性地找,就得解方程。把 \(A\mathbf{v} = \lambda \mathbf{v}\) 移項:

\[ A\mathbf{v} - \lambda \mathbf{v} = \mathbf{0} \quad\Longrightarrow\quad (A - \lambda I)\mathbf{v} = \mathbf{0} \]

這是一個齊次線性系統。我們要的是非零解 \(\mathbf{v}\) , 而齊次系統有非零解的充要條件是係數矩陣不可逆(第 4 章的結論),也就是:

\[ \det(A - \lambda I) = 0 \]

這是全書最重要的方程式之一,稱為特徵方程。 以 \(A = \begin{bmatrix} 2 & 1 \\ 1 & 2 \end{bmatrix}\) 為例:

\[ \det \begin{bmatrix} 2-\lambda & 1 \\ 1 & 2-\lambda \end{bmatrix} = (2-\lambda)^2 - 1 = \lambda^2 - 4\lambda + 3 = (\lambda - 3)(\lambda - 1) \]

得到 \(\lambda_1 = 3\) 、 \(\lambda_2 = 1\) ,和畫圖看到的完全一致! 再把每個 \(\lambda\) 代回 \((A - \lambda I)\mathbf{v} = \mathbf{0}\) 解出 \(\mathbf{v}\) (下一節手算完整流程)。

多項式 \(\det(A - \lambda I) = \lambda^2 - 4\lambda + 3\) 稱為 \(A\) 的特徵多項式。 它的根就是特徵值。這也立刻告訴我們:** \(n \times n\) 矩陣最多有 \(n\) 個特徵值**。

特徵值可正、可負、也可以不是實數!#

特徵多項式是實係數多項式,但根不一定是實數。最經典的例子是旋轉矩陣:

theta = np.pi / 4
R = np.array([[np.cos(theta), -np.sin(theta)],
              [np.sin(theta),  np.cos(theta)]])

eigvals = np.linalg.eigvals(R)
print(eigvals)   # [0.70710678+0.70710678j 0.70710678-0.70710678j]

幾何上這完全說得通:旋轉把每一個向量都轉了 \(45°\) , 沒有任何實向量能保持方向不變——除非它一開始就是零向量。 所以實特徵向量不存在,特徵值只好跑到複數世界 \(\lambda = e^{\pm i\theta}\) (模長 1、輻角 \(\pm\theta\) ,正好編碼了旋轉角度!)。

# 縮小的鏡射:lambda = -0.5(負特徵值 = 反向伸縮)
M = np.array([[-0.5, 0.0],
              [ 0.0, 1.0]])
print(np.linalg.eig(M))
# eigenvalues: [-0.5  1.]
# eigenvectors: x 軸方向(反向縮小)、y 軸方向(不變)

實驗:把各種矩陣的特徵方向畫出來#

import numpy as np
import linalg_viz as viz

matrices = {
    "剪切 shear":        np.array([[1.0, 1.0], [0.0, 1.0]]),
    "鏡射 reflect(y=x)": np.array([[0.0, 1.0], [1.0, 0.0]]),
    "拉伸 scale":        np.array([[3.0, 0.0], [0.0, 0.5]]),
    "投影 project(x)":   np.array([[1.0, 0.0], [0.0, 0.0]]),
}

for name, M in matrices.items():
    vals, vecs = np.linalg.eig(M)
    viz.plot_grid_transform(M)
    viz.draw_eigenvectors(vals, vecs)   # 特徵方向畫成虛線,方便對照
    viz.title(name)
    viz.show()
    print(f"{name}: 特徵值 = {np.round(vals, 3)}")

逐張圖解讀:

  • 剪切: \(\begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}\) 把整個平面往右推, 只有 \(x\) 軸上的向量不動 → 唯一實特徵值 \(\lambda = 1\) (重根!第 5.3 節會回來算帳)
  • 鏡射(沿 \(y = x\) 翻轉):鏡面上的向量不動( \(\lambda = 1\) ), 垂直方向的向量反轉( \(\lambda = -1\) )
  • 拉伸:兩個座標軸都是特徵方向,伸縮倍數 \(3\) 與 \(0.5\)
  • 投影: \(y\) 軸被壓扁 → \(\lambda = 0\) ; \(x\) 軸不變 → \(\lambda = 1\)

可以看到:特徵方向往往就是變換的「關鍵軸」——鏡射的鏡面、投影的目標線、 拉伸的軸。這正是為什麼第 7 章的 SVD 和第 8 章的 PageRank 都建立在特徵向量上。

小結與練習#

本節重點#

  1. 特徵向量是變換下方向不變的向量, \(A\mathbf{v} = \lambda \mathbf{v}\) ; \(\lambda\) 是伸縮倍數,可正、可負、可為零、可為複數
  2. 非零解存在 ⟺ \(\det(A - \lambda I) = 0\) (特徵方程)
  3. 特徵多項式的根 = 特徵值; \(n \times n\) 矩陣最多 \(n\) 個特徵值
  4. 旋轉矩陣(非 \(0°\) 、 \(180°\) )沒有實特徵向量——幾何直覺與代數一致
  5. 特徵方向常對應變換的幾何軸:鏡面、投影線、拉伸軸

練習#

  1. 用手驗證:對 \(A = \begin{bmatrix} 2 & 1 \\ 1 & 2 \end{bmatrix}\) , \(\mathbf{v} = \begin{bmatrix} 1 \\ 1 \end{bmatrix}\) 是否滿足 \(A\mathbf{v} = 3\mathbf{v}\) ?
  2. 求 \(A = \begin{bmatrix} 0 & -2 \\ 1 & 3 \end{bmatrix}\) 的特徵多項式並因式分解, 找出特徵值(提示:有一個重根)。
  3. 用 np.linalg.eig 檢查練習 2 的答案,並畫出對應的特徵方向。
  4. 對 \(\theta = 90°\) 的旋轉矩陣計算特徵值,驗證它們是 \(\pm i\) , 並確認 \(|\lambda| = 1\) (旋轉不改变長度)。
  5. 挑戰:若 \(\lambda\) 是 \(A\) 的特徵值,證明 \(\lambda^2\) 是 \(A^2\) 的特徵值 (提示:對 \(A\mathbf{v} = \lambda \mathbf{v}\) 兩邊再左乘 \(A\) )。