跳轉到

5.3 對角化與矩陣冪次#

本節目標#

  • 理解 \(A = PDP^{-1}\) 的幾何意義:換到特徵基底下,變換只是單純的伸縮
  • 掌握可對角化的條件與手算流程
  • 學會 \(A^n = PD^nP^{-1}\) 這個「神器」,並用 NumPy 驗證
  • 用 np.linalg.eig 實作對角化,對照 np.linalg.matrix_power
  • 知道什麼情況下對角化會失敗(Jordan 標準型預告)

幾何直覺:換一個好用的座標系#

第 1 章說過:矩陣就是座標系之間的翻譯官。同一個變換, 用不同的基底描述,難度天差地別。

\(A = \begin{bmatrix} 4 & 1 \\ 2 & 3 \end{bmatrix}\) 在標準基底下看起來 「亂七八糟」,但我們已經找到它的兩個特徵方向 \(\mathbf{v}_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}\) (伸縮 5 倍)、 \(\mathbf{v}_2 = \begin{bmatrix} 1 \\ -2 \end{bmatrix}\) (伸縮 2 倍)。

如果改用 \(\mathbf{v}_1, \mathbf{v}_2\) 當基底,這個變換就變得無聊透頂: 沿 \(\mathbf{v}_1\) 拉 5 倍、沿 \(\mathbf{v}_2\) 拉 2 倍,僅此而已。 用矩陣語言說:在特徵基底下, \(A\) 變成對角矩陣——

\[ D = \begin{bmatrix} 5 & 0 \\ 0 & 2 \end{bmatrix} \]

把三個基底之間的翻譯串起來,就是本節的核心公式:

\[ A = PDP^{-1} \]

其中 \(P\) 的行是特徵向量: \(P = \begin{bmatrix} | & | \\ \mathbf{v}_1 & \mathbf{v}_2 \\ | & | \end{bmatrix}\) 。 讀這條式子的正確方式是從右往左:

  1. \(P^{-1}\) :把座標換到特徵基底
  2. \(D\) :在特徵基底上各自伸縮(超簡單!)
  3. \(P\) :換回標準基底

對角化的手算流程#

條件: \(n \times n\) 矩陣 \(A\) 可對角化 ⟺ \(A\) 有 \(n\) 個線性獨立的特徵向量。

流程(以 5.2 節的 \(A\) 為例):

  1. 求特徵值: \(\lambda = 5, 2\) (相異實根 → 一定可對角化)
  2. 解出特徵向量: \(\mathbf{v}_1 = \begin{bmatrix} 1 \\ 1 \end{bmatrix}\) 、 \(\mathbf{v}_2 = \begin{bmatrix} 1 \\ -2 \end{bmatrix}\)
  3. 組裝:
\[ P = \begin{bmatrix} 1 & 1 \\ 1 & -2 \end{bmatrix}, \qquad D = \begin{bmatrix} 5 & 0 \\ 0 & 2 \end{bmatrix} \]
  1. 驗證 \(PDP^{-1} = A\) (或等價地 \(AP = PD\) ,手算時這個更好檢查)。
import numpy as np

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

vals, P = np.linalg.eig(A)
D = np.diag(vals)

print(P @ D @ np.linalg.inv(P))   # 應還原出 A
print(np.allclose(P @ D @ np.linalg.inv(P), A))   # True

\(A^n = PD^nP^{-1}\) :對角化的真正威力#

為什麼費這麼大勁換座標?因為對角矩陣的冪次超好算—— 對角線各自乘 \(n\) 次方就好:

\[ D^n = \begin{bmatrix} 5 & 0 \\ 0 & 2 \end{bmatrix}^{\!n} = \begin{bmatrix} 5^n & 0 \\ 0 & 2^n \end{bmatrix} \]

而中間的 \(P^{-1}P\) 會互相抵消:

\[ A^n = (PDP^{-1})(PDP^{-1})\cdots(PDP^{-1}) = PD^nP^{-1} \]

複雜的矩陣連乘,瞬間化簡成「換座標 → 算 \(n\) 次方 → 換回來」。

對照實驗:算 \(A^{10}\) ,一路是 \(5^{10} \approx 9765625\) 這種大數字, 傳統矩陣乘法要跑 9 次矩陣乘法,對角化只要一次 \(D^{10}\) :

import numpy as np

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

# 方法一:暴力連乘
A10_direct = np.linalg.matrix_power(A, 10)

# 方法二:對角化
vals, P = np.linalg.eig(A)
A10_diag = P @ np.diag(vals ** 10) @ np.linalg.inv(P)

print(np.allclose(A10_direct, A10_diag))   # True
print(A10_direct)

當 \(n\) 很大或矩陣很大時,差距更明顯: matrix_power 需要 \(O(\log n)\) 次矩陣乘法,每次是 \(O(n^3)\) ; 對角化路線則把問題降為純數字的 \(n\) 次方。 而且它給出閉式公式——例如 \((A^n)_{11}\) 是 \(\lambda_1^n\) 與 \(\lambda_2^n\) 的 線性組合,這正是下一節推 Fibonacci 通項公式的鑰匙。

不可對角化的例子#

回到 5.2 節的剪切矩陣 \(S = \begin{bmatrix} 1 & 1 \\ 0 & 1 \end{bmatrix}\) : 特徵值 \(\lambda = 1\) 是重根,但獨立特徵向量只有 \(\begin{bmatrix} 1 \\ 0 \end{bmatrix}\) 一個。 \(P\) 凑不出兩個獨立的行 → ** \(P\) 不可逆** → 對角化失敗。

S = np.array([[1.0, 1.0], [0.0, 1.0]])
vals, P = np.linalg.eig(S)
print(P)                                # 兩行幾乎相同
print(np.abs(np.linalg.det(P)))         # ~ 0,P 不可逆!

# 硬要做的話會得到垃圾:
try:
    print(P @ np.diag(vals) @ np.linalg.inv(P))
except np.linalg.LinAlgError as e:
    print("對角化失敗:", e)

直覺上:剪切的「歪掉程度」無法只用兩個方向的伸縮表達—— 它還需要一個「微微傾倒」的動作。完整的描述需要 Jordan 標準型 (在對角線旁邊加 1 的準對角形式),那是更進階課程的主題; 本書遇到不可對角化的情況時,一律改用數值方法(如第 6 章的 SVD)處理。

好消息是:不可對角化是稀有事件。隨機抽一個矩陣,幾乎必可對角化; 實對稱矩陣更是永遠可對角化(而且特徵向量還能取成互相垂直,譜定理)。

實驗:驗證 \(PDP^{-1} = A\)#

import numpy as np
import linalg_viz as viz

rng = np.random.default_rng(42)

for k in range(5):
    A = rng.integers(-4, 5, size=(2, 2)).astype(float)

    vals, P = np.linalg.eig(A)

    if np.linalg.matrix_rank(P) < 2:
        print(f"實驗 {k}: A = {A.tolist()} 不可對角化(特徵向量不足),跳過")
        continue

    D = np.diag(vals)
    A_back = P @ D @ np.linalg.inv(P)
    ok = np.allclose(A_back, A)
    print(f"實驗 {k}: A = {A.tolist()}  還原成功 = {ok}")

    # 幾何驗證:特徵方向在變換下只伸縮
    viz.plot_grid_transform(A)
    viz.draw_eigenvectors(vals, P)   # 特徵方向 = 不變的軸
    viz.title(f"實驗 {k}: 特徵值 {np.round(vals, 2)}")
    viz.show()

跑完五次實驗你會發現:只要 \(P\) 滿秩, \(PDP^{-1}\) 總是精準還原 \(A\) ; 偶爾撞上不可對角化的矩陣(例如恰好抽到剪切型)時, eig 回傳的兩行特徵向量會幾乎平行——那就是警訊。

小結與練習#

本節重點#

  1. \(A = PDP^{-1}\) :特徵基底下,變換只是各方向的伸縮; \(P\) 的行是特徵向量, \(D\) 的對角線是特徵值
  2. 可對角化 ⟺ 有 \(n\) 個線性獨立特徵向量(相異特徵值保證成立;重根可能不成立)
  3. \(A^n = PD^nP^{-1}\) :把矩陣冪次化為純數字冪次,並能導出閉式公式
  4. 剪切矩陣不可對角化;完整的理論需要 Jordan 標準型(本書點到為止)
  5. 實對稱矩陣永遠可對角化

練習#

  1. 對角化 \(A = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}\) (手算), 並用 NumPy 驗證 \(PDP^{-1} = A\) 。這個矩陣的幾何意義是什麼?
  2. 用 \(A^n = PD^nP^{-1}\) 手算練習 1 中 \(A^{2}\) 、 \(A^{3}\) , 你發現規律了嗎?(提示: \(A^2 = I\) 。)
  3. 寫函式 diagonalize(A):回傳 (P, D, 可否對角化), 用 np.linalg.matrix_rank 判斷。測試 5 個隨機矩陣與剪切矩陣。
  4. 計算 \(\begin{bmatrix} 2 & 0 \\ 0 & 3 \end{bmatrix}^{100}\) 的對角線, 估算數量級(用 np.log10),體會冪次成長之快。
  5. 挑戰:證明若 \(A\mathbf{v} = \lambda\mathbf{v}\) ,則 \(A^n\mathbf{v} = \lambda^n\mathbf{v}\) , 並說明這與 \(A^n = PD^nP^{-1}\) 是同一件事的兩種講法。