6.3 特徵值與對角化:找到變換的「天然座標軸」#
本節目標#
- 理解特徵值與特徵向量的定義與幾何意義(伸縮方向)
- 學會用
eigenvals()、eigenvects()、charpoly()做特徵分析 - 學會用
diagonalize()對角化矩陣,並用 \(A = PDP^{-1}\) 快速計算 \(A^n\) - 實驗:畫出矩陣對單位圓的變換,親眼看到特徵方向
特徵值與特徵向量:不轉彎的方向#
一個線性變換 \(A\) 作用在向量上,通常會同時旋轉和伸縮。但總有某些特別的方向, \(A\) 作用上去只伸縮、不轉彎:
滿足此式的非零向量 \(\mathbf{v}\) 稱為特徵向量(eigenvector),對應的倍率 \(\lambda\) 稱為特徵值(eigenvalue)。
幾何意義: \(\mathbf{v}\) 指出「變換下的不動方向」, \(\lambda\) 說明該方向被拉長( \(|\lambda| > 1\) )、壓縮( \(|\lambda| < 1\) )或翻轉( \(\lambda < 0\) )。例如 \(\lambda = 2\) 表示沿這個方向一切長度加倍。
如何求特徵值?把定義改寫成 \((A - \lambda I)\mathbf{v} = \mathbf{0}\) 。要存在非零解 \(\mathbf{v}\) ,係數矩陣必須不可逆(否則只有零解),也就是:
這條以 \(\lambda\) 為未知數的方程稱為特徵多項式。
用 eigenvals() 求特徵值#
from sympy import Matrix
A = Matrix([[4, 1],
[2, 3]])
print(A.eigenvals())
# {5: 1, 2: 1}
輸出是字典:鍵是特徵值,值是它的代數重數(重根次數)。這裡特徵值是 \(\lambda = 5\) 和 \(\lambda = 2\) 。
檢驗一下定義 \(A\mathbf{v} = \lambda \mathbf{v}\) :
v = Matrix([1, 1]) # 待會會看到它是 λ=5 的特徵向量
print(A * v) # Matrix([[5], [5]]) ← 正好是 5*v!
用 eigenvects() 一次拿到全部#
eigenvects() 回傳特徵值、重數與對應特徵向量空間的一組基底:
from sympy import Matrix
A = Matrix([[4, 1],
[2, 3]])
for val, mult, vecs in A.eigenvects():
print(f"特徵值 {val}(重數 {mult}),特徵向量:{vecs}")
# 特徵值 5(重數 1),特徵向量:[Matrix([[1/2], [1]])]
# 特徵值 2(重數 1),特徵向量:[Matrix([[-1], [1]])]
驗證第二組: \(A \begin{pmatrix} -1 \\ 1 \end{pmatrix} = \begin{pmatrix} -2 \\ 2 \end{pmatrix} = 2 \begin{pmatrix} -1 \\ 1 \end{pmatrix}\) ,確實是 \(\lambda = 2\) 。
特徵多項式 charpoly#
特徵多項式可以用 charpoly() 取得:
from sympy import Matrix, Symbol
lam = Symbol('lambda')
A = Matrix([[4, 1],
[2, 3]])
cp = A.charpoly(lam)
print(cp.as_expr()) # lambda**2 - 7*lambda + 10
print(cp.as_expr().factor()) # (lambda - 5)*(lambda - 2)
手算核對: \(\det(A - \lambda I) = (4-\lambda)(3-\lambda) - 2 = \lambda^2 - 7\lambda + 10\) 。特徵多項式的根就是特徵值。兩個根的和等於矩陣的蹤(trace,對角線和: \(4+3=7\) ),積等於行列式( \(10\) ),這兩個小結論常常能心算驗證答案。
對角化 diagonalize()#
如果 \(n \times n\) 矩陣有 \(n\) 個線性獨立的特徵向量,就能寫成
其中 \(D\) 是對角矩陣(對角線放特徵值), \(P\) 的行是對應的特徵向量。diagonalize() 一次回傳 \(P\) 和 \(D\) :
from sympy import Matrix
A = Matrix([[4, 1],
[2, 3]])
P, D = A.diagonalize()
print(P) # Matrix([[1/2, -1], [1, 1]]):行是特徵向量
print(D) # Matrix([[5, 0], [0, 2]]):對角線是特徵值
# 驗證 A = P*D*P^{-1}
print(P * D * P.inv() == A) # True
print(D == P.inv() * A * P) # True
為什麼要對角化?因為對角矩陣的次方極好算——只要把對角線元素各自乘方。於是:
from sympy import Matrix
A = Matrix([[4, 1],
[2, 3]])
P, D = A.diagonalize()
n = 10
print(A**10) # 直接算
print(P * D**10 * P.inv()) # 對角化算,結果相同
不是所有矩陣都能對角化(例如 \(A = \begin{pmatrix} 1 & 1 \\ 0 & 1 \end{pmatrix}\) 特徵值 1 重根,但特徵向量只有一個方向)。可以先用 is_diagonalizable() 檢查:
print(A.is_diagonalizable()) # True
print(Matrix([[1, 1], [0, 1]]).is_diagonalizable()) # False
應用預告:Fibonacci 數列(7.3 節)#
Fibonacci 數列 \(F_{n+1} = F_n + F_{n-1}\) 可以寫成矩陣遞迴:
對這個矩陣做特徵分析,就能得到 Fibonacci 數列的封閉公式(Binet 公式):
from sympy import Matrix
F = Matrix([[1, 1],
[1, 0]])
print(F.eigenvals()) # {(1 + sqrt(5))/2: 1, (1 - sqrt(5))/2: 1}
特徵值正是黃金比例 \(\varphi = \frac{1+\sqrt{5}}{2}\) 與其共軛!詳細推導與 \(A^n\) 的應用留待 7.3 節。
動手實驗:畫出矩陣對單位圓的變換#
線性變換把單位圓變成橢圓。橢圓的主軸方向正是特徵向量方向,主軸半長正是特徵值的絕對值。讓我們畫圖驗證:
import matplotlib.pyplot as plt
import numpy as np
from sympy import Matrix
A = Matrix([[3, 1],
[1, 3]])
# 單位圓上的點
theta = np.linspace(0, 2 * np.pi, 200)
circle = np.vstack([np.cos(theta), np.sin(theta)]) # 2 x 200
# 作用變換
Anp = np.array(A, dtype=float)
ellipse = Anp @ circle
# 特徵向量(畫成直線)
for val, mult, vecs in A.eigenvects():
v = np.array(vecs[0], dtype=float).flatten()
v = v / np.linalg.norm(v)
plt.plot([-5 * v[0], 5 * v[0]], [-5 * v[1], 5 * v[1]],
'--', label=f"特徵方向 λ={val}")
plt.plot(circle[0], circle[1], 'gray', label='單位圓')
plt.plot(ellipse[0], ellipse[1], 'b', label='變換後的橢圓')
plt.axis('equal')
plt.legend()
plt.title("矩陣 $A = [[3,1],[1,3]]$ 對單位圓的變換")
plt.show()
執行後你會看到:圓被拉成一個橢圓,而虛線畫的兩條特徵方向恰好是橢圓的長短軸。特徵值 \(\lambda = 4, 2\) 分別對應長軸半長 \(4\) 、短軸半長 \(2\) 。
換一個會「翻轉」的矩陣玩玩:
B = Matrix([[0, 1],
[1, 0]]) # 沿直線 y=x 鏡射
print(B.eigenvals()) # {1: 1, -1: 1}
\(\lambda = 1\) 的特徵向量在鏡射軸上(不變), \(\lambda = -1\) 的特徵向量垂直於鏡射軸(方向反轉)——負特徵值就代表「翻轉」。
小結與練習#
本節重點:
- 特徵向量是變換下「不轉彎」的方向,特徵值是該方向的伸縮倍率
- 特徵值來自特徵多項式 \(\det(A - \lambda I) = 0\) ;
eigenvals()、eigenvects()、charpoly()是三件套 - 對角化 \(A = PDP^{-1}\) 把 \(A^n\) 變成 \(PD^nP^{-1}\) ;
diagonalize()回傳 \(P, D\) - 不是所有矩陣都可對角化(特徵向量不夠時不行)
- Fibonacci 矩陣的特徵值是黃金比例——伏筆在 7.3 節
練習:
- 求 \(A = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}\) (旋轉 \(90°\) )的特徵值,並解釋為什麼實數特徵值不存在(提示:旋轉不改變長度,哪來的伸縮方向?)。
- 對 \(A = \begin{pmatrix} 2 & 0 \\ 0 & 5 \end{pmatrix}\) 求特徵值與特徵向量,你能不經計算就說出答案嗎?(提示:對角矩陣的特徵結構一目了然)
- 用
diagonalize()求 \(A = \begin{pmatrix} 4 & 1 \\ 2 & 3 \end{pmatrix}\) 的 \(A^5\) ,並與A**5對照。 - 驗證:特徵值總和等於
A.trace(),特徵值乘積等於A.det()(任取一個 \(3 \times 3\) 矩陣)。 - 修改實驗程式,用 \(A = \begin{pmatrix} 1 & 2 \\ 0 & 1 \end{pmatrix}\) (剪切變換)畫單位圓的變換。觀察:它可對角化嗎?橢圓的主軸和特徵向量還重合嗎?