6.4 對稱矩陣與譜定理#
本節目標#
- 認識對稱矩陣 \(A = A^T\) 的特殊性:它是一般矩陣中的「乖寶寶」
- 學會譜定理:對稱矩陣必有實特徵值與正交特徵基,即 \(A = Q\Lambda Q^T\)
- 用
np.linalg.eigh(比eig更穩更快)做特徵分解 - 從幾何理解:對稱矩陣沿特徵方向只伸縮、不旋轉
- 實驗:對稱 vs 非對稱特徵值對照、二次型 \(\mathbf{x}^T A\mathbf{x}\) 與正定的初步直覺
對稱矩陣:向自己對稱的矩陣#
把矩陣沿主對角線「翻面」,如果還是自己,就是對稱矩陣:
哪裡會遇到它?出乎意料地常見:
- 資料的協方差矩陣(第 \(i\) 行第 \(j\) 列 = 變數 \(i\) 與 \(j\) 的共變,當然對稱)
- 圖的鄰接矩陣(友誼是互相的, \(a_{ij} = a_{ji}\) )
- 內積矩陣、彈簧系統的能量矩陣、二次型
- 任何 \(B^T B\) 或 \(B B^T\) (例如最小平方法的 \(A^T A\) !)
import numpy as np
B = np.random.randn(4, 3)
S = B.T @ B # 永遠對稱
print(np.allclose(S, S.T)) # True
譜定理:對稱矩陣必可正交對角化#
一般矩陣的特徵值可能不存在(複數)、特徵向量可能不夠用(第 8 章的瑕疵矩陣)。 但對稱矩陣有整套保證,這就是譜定理(spectral theorem):
若 \(A = A^T\) ,則 1. 所有特徵值都是實數 2. 存在一組互相垂直的特徵向量,湊成完整的 orthonormal 基 3. 因此 \(A\) 可以寫成
注意 \(Q^{-1} = Q^T\) ,所以反矩陣免費:
特徵值像矩陣的「光譜」——把變換 \(A\) 拆成 \(n\) 個純粹的伸縮動作, 沿著一組互相垂直的軸各自放大 \(\lambda_i\) 倍。
用 np.linalg.eigh#
對稱矩陣請用專屬的 eigh,不要用一般性的 eig:
import numpy as np
A = np.array([[2., 1.],
[1., 3.]])
w, Q = np.linalg.eigh(A) # w = 特徵值(已排序),Q = 正交特徵向量
print(w) # 實數,且由小到大
print(Q) # orthonormal
# 驗證 A = Q Λ Q^T
print(Q @ np.diag(w) @ Q.T)
print(np.allclose(Q.T @ Q, np.eye(2))) # Q 真的是正交矩陣
eig | eigh | |
|---|---|---|
| 適用對象 | 任意方陣 | 對稱(Hermitian)矩陣 |
| 速度 | 較慢 | 快約 2~3 倍 |
| 穩定性 | 較低 | 較高(利用對稱性) |
| 特徵值 | 可能有複數虛部 | 保證實數、已排序 |
eigh直接利用你「知道矩陣對稱」這個資訊,所以更快更穩。 程式設計的教訓:能給演算法的結構資訊就別藏。
幾何:只伸縮、不旋轉#
回憶 3 章:一般矩陣作用在向量上,常常旋轉 + 伸縮同時發生。 但對稱矩陣沿著特徵方向 \(\mathbf{q}_i\) ,動作是純伸縮:
方向完全不轉,只拉長或縮短 \(\lambda_i\) 倍。任意向量呢?先用 \(Q^T\) 換到特徵座標、 逐軸伸縮、再轉回來:
import numpy as np
from linalg_viz import plot_vectors
A = np.array([[2., 1.],
[1., 3.]])
w, Q = np.linalg.eigh(A)
q1, q2 = Q[:, 0], Q[:, 1]
# 特徵方向上的向量:只變長度,方向不變
print(A @ q1, w[0] * q1) # 相同
print(A @ q2, w[1] * q2) # 相同
# 畫圖:灰箭頭是原向量,彩箭頭是 A v,特徵方向以虛線標示
plot_vectors([q1, q2], labels=['q1', 'q2'], color='gray')
plot_vectors([A @ q1, A @ q2], labels=['A q1', 'A q2'])
畫圖會看到: \(A\mathbf{q}_1\) 與 \(\mathbf{q}_1\) 在同一條線上( \(\lambda_1 < 0\) 時反向), \(A\mathbf{q}_2\) 同理,而且兩組箭頭保持垂直。
實驗一:對稱 vs 非對稱的特徵值#
import numpy as np
np.random.seed(1)
B = np.random.randn(5, 5)
S = (B + B.T) / 2 # 任意矩陣對稱化
print("對稱矩陣特徵值:")
print(np.linalg.eigvalsh(S)) # 全是實數
print("非對稱矩陣特徵值:")
w = np.linalg.eigvals(B)
print(w) # 帶 ± 虛部(複數)!
print("非對稱矩陣的特徵向量正交嗎?")
w, V = np.linalg.eig(B)
V = V.real
print(np.abs(V.T @ V - np.eye(5)).max()) # 通常遠離 0
對照結果非常清楚:非對稱矩陣的特徵值常帶虛部,特徵向量也不正交; 對稱矩陣兩者都乖——這正是譜定理承諾的。
實驗二:二次型 \(\mathbf{x}^T A\mathbf{x}\) 與正定的初步直覺#
把矩陣夾在一個向量的兩側: \(f(\mathbf{x}) = \mathbf{x}^T A\mathbf{x}\) ,這是二次型。 例如 \(A = \begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix}\) 時:
它是「向量 \(\mathbf{x}\) 在 \(A\) 這把尺下的能量」。在特徵座標下超級簡單:
所有特徵值 \(> 0\) (正定)時,這個值對任何 \(\mathbf{x} \neq \mathbf{0}\) 都 \(> 0\) —— 碗狀的能量面,唯一的最小值在原點。這就是二次函數有唯一最小值、 高斯消去不會翻車的代數保證(也呼應 6.3: \(A^T A\) 永遠半正定)。
import numpy as np
import matplotlib.pyplot as plt
A = np.array([[2., 1.],
[1., 3.]])
print(np.linalg.eigvalsh(A)) # 都 > 0 → 正定
# 畫 z = x^T A x 的能量面:正定 → 碗狀
g = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(g, g)
Z = 2*X**2 + 2*X*Y + 3*Y**2
plt.contourf(X, Y, Z, levels=30, cmap='viridis')
plt.colorbar(label='x^T A x')
plt.title("正定矩陣的二次型:橢圓等高線的碗")
plt.gca().set_aspect('equal')
plt.show()
# 反例:有一個負特徵值 → 馬鞍面
B = np.array([[1., 0.],
[0., -1.]])
Z2 = X**2 - Y**2
plt.contourf(X, Y, Z2, levels=30, cmap='coolwarm')
plt.title("有負特徵值:馬鞍,某些方向是「下坡」")
plt.gca().set_aspect('equal')
plt.show()
讀圖要點:等高線是橢圓還是雙曲線,完全由特徵值的正負號決定; 橢圓的長短軸方向,正是特徵向量的方向。特徵值不只是數字,是能量面的形狀密碼。
小結與練習#
本節重點 1. 對稱矩陣 \(A = A^T\) 隨處可見:協方差、鄰接矩陣、 \(A^T A\) 、二次型。 2. 譜定理:對稱矩陣必有實特徵值與正交特徵基, \(A = Q\Lambda Q^T\) ,反矩陣免費。 3. 對稱矩陣沿特徵方向純伸縮不旋轉;幾何動作 = 轉入特徵座標 → 伸縮 → 轉回。 4. 用 eigh 而非 eig:更快、更穩、特徵值自動排序。 5. 特徵值的正負決定二次型 \(\mathbf{x}^T A\mathbf{x}\) 是碗還是馬鞍——「正定」的初步直覺。
練習 1. 對 \(A = \begin{bmatrix} 4 & 2 \\ 2 & 1 \end{bmatrix}\) 用 eigh 分解,並驗證 \(A = Q\Lambda Q^T\) 與 \(Q^TQ = I\) 。 2. 把實驗二的 \(A\) 換成 \(\begin{bmatrix} 1 & 2 \\ 2 & 1 \end{bmatrix}\) ,先判斷正定性,再畫圖驗證你的判斷。 3. 挑戰:對非對稱矩陣 \(B\) ,計算 \(S = \frac{B + B^T}{2}\) 的 eigh 分解,思考——對稱部分捕捉了 \(B\) 的哪些行為?(提示:反對稱部分只負責旋轉,第 8 章見分曉。)