第 12 章 特征值与特征向量
学习目标
- 从几何直觉理解「特征方向」与「拉伸倍数」
- 掌握特征值与特征向量的定义
- 推导特征方程
- 会手算二阶矩阵的特征值与特征向量
- 理解对角化 与它的用途
- 会用 PyTorch 计算特征值,并用幂法从零实现
12.1 直觉:有些方向,变换后方向不变
拿一个矩阵
它把向量 变成 :水平方向拉长 2 倍,竖直方向拉长 3 倍。观察几个向量:
- :方向没变,长度变 2 倍;
- :方向没变,长度变 3 倍;
- :方向变了!

绝大多数向量被矩阵作用后,方向都改变了;只有少数特殊方向,变换后仍然在原来的直线上,只是被拉伸或压缩了若干倍。这些特殊方向叫特征方向,拉伸倍数叫特征值。它们是理解矩阵变换最本质的钥匙:一个矩阵再怎么复杂,它沿特征方向做的事情只是「乘一个数」。
import matplotlib.pyplot as plt
from matplotlib import font_manager
for f in font_manager.findSystemFonts():
if any(k in f for k in ("NotoSansCJK", "NotoSansSC", "wqy", "SimHei", "msyh", "PingFang")):
font_manager.fontManager.addfont(f)
plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "WenQuanYi Zen Hei", "SimHei", "Microsoft YaHei", "PingFang SC"]
plt.rcParams["axes.unicode_minus"] = False
import numpy as np
A = np.array([[2.0, 0.0],
[0.0, 3.0]])
fig, ax = plt.subplots(figsize=(6, 6))
ax.axhline(0, color="black", linewidth=1)
ax.axvline(0, color="black", linewidth=1)
ax.grid(True, linestyle=":", alpha=0.5)
ax.set_xlim(-0.5, 3.5)
ax.set_ylim(-0.5, 4)
ax.set_aspect("equal")
vectors = [np.array([1.0, 0.0]), np.array([0.0, 1.0]), np.array([1.0, 1.0])]
colors = ["tab:red", "tab:blue", "tab:orange"]
labels = ["特征向量 (1,0)→2(1,0)", "特征向量 (0,1)→3(0,1)", "普通向量 (1,1)→(2,3) 方向变了"]
for v, c, label in zip(vectors, colors, labels):
Av = A @ v
ax.quiver(0, 0, v[0], v[1], angles="xy", scale_units="xy", scale=1,
color=c, width=0.018, alpha=0.45)
ax.quiver(0, 0, Av[0], Av[1], angles="xy", scale_units="xy", scale=1,
color=c, width=0.018)
ax.annotate("", Av, xytext=v, arrowprops=dict(arrowstyle="->", color=c, lw=0.8))
ax.annotate(label, Av, textcoords="offset points", xytext=(8, 6), color=c, fontsize=9)
ax.set_title("A = diag(2, 3):特征方向只拉伸,不转向")
fig.savefig("book/public/figs/fig12-eigen.png", dpi=120, bbox_inches="tight")
plt.close(fig)12.2 定义
特征向量与特征值:对 阶方阵 ,若存在非零向量 与数 ,使得
则 叫 的特征值, 叫属于 的特征向量。 必须非零——零向量乘以任何数都成立,没有信息。
例:对角矩阵 的特征值是 2 和 3,对应特征向量 与 。对角矩阵的特征值就是对角线上的数,特征向量是标准基。
12.3 特征方程:从定义到行列式
把定义变形。 等价于
右边第二项用单位矩阵帮忙改写成矩阵乘矩阵:
这是一个齐次方程组(右端为零)。它要有非零解,由第 9 章的等价链,系数矩阵必须不可逆,即
为什么?回顾第 9.5: 时方程组只有唯一解,而齐次方程组的唯一解就是零解 ——那不是特征向量。所以非零解存在,当且仅当行列式为 0。
展开后是关于 的 次多项式,叫特征多项式。求特征值 = 求这个多项式的根。 阶矩阵恰有 个特征值(计重数,可能含复数)。
12.4 手算一个 2×2 例子
第 1 步:写特征方程。
展开:
特征值:、。
第 2 步:对每个特征值解 ,求特征向量。
:
得到 ,即 。取 ,特征向量 。
验证:
:
得到 ,取 ,特征向量 。
用库验证:
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 2.0]])
print("np.linalg.eig:\n", np.linalg.eig(A))运行输出:
np.linalg.eig:
EigResult(eigenvalues=array([3.+0.j, 1.+0.j]), eigenvectors=array([[ 0.70710678+0.j, -0.70710678+0.j],
[ 0.70710678+0.j, 0.70710678+0.j]]))特征值 与手算一致;特征向量是归一化后的 与 ——方向相同,长度归一化到 1。库返回的单位化特征向量,与手算的特征向量只差一个常数倍,而特征向量的倍数仍是特征向量:
PyTorch 对对称矩阵用 torch.linalg.eigh(保证实特征值、正交特征向量):
import torch
A = torch.tensor([[2.0, 1.0],
[1.0, 2.0]])
vals, vecs = torch.linalg.eigh(A)
print("特征值:", vals)
print("特征向量(按列):\n", vecs)
print("验证 A v = λ v:", torch.allclose(A @ vecs[:, 0], vals[0] * vecs[:, 0]))运行输出:
特征值: tensor([1., 3.])
特征向量(按列):
tensor([[-0.7071, 0.7071],
[ 0.7071, 0.7071]])
验证 A v = λ v: True12.5 对角化:把矩阵「拆开看」
如果 有 个线性无关的特征向量 ,把它们按列拼成矩阵 ,把特征值放在对角线拼成 :
验证 :左边 乘第 列得 ;右边 的第 列是 乘 的第 列,即 。两边的每一列都相等,所以
这叫道对角化。它把「复杂的 」分解成「好算的 、、」。威力体现在幂运算:因为中间的 会抵消,
而 只是每个对角线元素取 次方。手算 从「连乘 100 次矩阵」变成「算两个数的高次幂」。
import numpy as np
A = np.array([[2.0, 1.0],
[1.0, 2.0]])
vals, vecs = np.linalg.eig(A)
# 用对角化算 A^10
P = vecs
D = np.diag(vals)
P_inv = np.linalg.inv(P)
A10_diag = P @ (D ** 10) @ P_inv
# 直接算 A^10 对比
A10_direct = np.linalg.matrix_power(A, 10)
print("对角化算 A^10:\n", A10_diag.real)
print("直接算 A^10:\n", A10_direct)
print("一致?", np.allclose(A10_diag.real, A10_direct))运行输出:
对角化算 A^10:
[[29525. 29524.]
[29524. 29525.]]
直接算 A^10:
[[29525. 29524.]
[29524. 29525.]]
一致? True12.6 幂法:不展开多项式也能求最大特征值
如果矩阵很大,展开特征多项式不现实。幂法只用一个迭代就能抓出绝对值最大的特征值:
- 随机选一个非零向量 ;
- 反复做 ;
- 收敛到最大特征值对应的特征向量。
为什么收敛?把 按特征向量展开:
迭代 次后(忽略归一化),
如果 最大,第一项增长得最快, 足够大时其他项可以忽略,——方向指向 。
特征值用瑞利商恢复:
(把 两边点乘 ,移项即得。)
import numpy as np
def power_iteration(A, steps=100):
"""幂法:求绝对值最大的特征值及其特征向量"""
v = np.array([1.0, 2.0])
for _ in range(steps):
Av = A @ v
v = Av / np.linalg.norm(Av)
lam = (v @ A @ v) / (v @ v) # 瑞利商
return lam, v
A = np.array([[2.0, 1.0],
[1.0, 2.0]])
lam, v = power_iteration(A)
print("幂法特征值:", lam)
print("幂法特征向量:", v)
print("库结果:", np.linalg.eigvals(A))运行输出:
幂法特征值: 3.0
幂法特征向量: [0.70710678 0.70710678]
库结果: [3.+0.j 1.+0.j]幂法抓到了最大特征值 3 和特征向量 的方向——它是 Google PageRank 等算法的基本思想之一。
12.7 AI 视角:为什么处处是特征值
特征值/特征向量在 AI 里无处不在:
- 主成分分析(PCA):协方差矩阵的特征向量就是数据的主要方向,特征值衡量该方向上的方差大小;
- 马尔可夫链:平稳分布是转移矩阵特征值 1 的特征向量;
- PageRank:网页排序是转移矩阵主特征向量;
- 深度学习:损失函数在极值点附近的曲率由 Hessian 矩阵的特征值决定,训练稳定性与特征值(谱)密切相关;
- SVD(第 14 章):奇异值来自 的特征值。
学会了特征值,你就拿到了分析「矩阵作为变换」的通用语言。
动手实践
- 对 写出特征值与特征向量,并验证 。
- 手算 的特征值(提示:特征多项式是 ),再用
np.linalg.eig验证。 - 用 12.6 的幂法求 的最大特征值,说明它为什么接近 1。
- 验证对角化:任选一个 2×2 矩阵,检查 。
- 用
torch.linalg.eigh求一个 3×3 对称矩阵的特征值,检查是否全为实数。
常见错误
| 错误写法/理解 | 原因 |
|---|---|
| 特征向量取零向量 | 零向量任何 都满足,不含信息;定义要求非零 |
| 特征方程写成 | 矩阵减标量无定义,必须减 |
| 认为特征向量唯一 | 特征向量可以乘任意非零常数,仍是特征向量 |
| 认为每个矩阵都能对角化 | 只有 个线性无关特征向量的矩阵可对角化;否则只能做 Jordan 形或 SVD |
| 特征值顺序与特征向量列错位 | 库返回的每个特征向量对应同列的特征值,一一对应 |
章末练习
基础
- 对 ,写出特征值与特征向量。
- 验证 是 的特征向量,并求出它对应的特征值。
- 用
torch.linalg.eigh求 的特征值。
提高
- 手算 的特征多项式、特征值与特征向量,写出对角化 中的 与 。
- 利用对角化计算 : 和 (后者特征值是 1 和 -1)。
挑战
- 用幂法思想证明:若 ,则 收敛到 的特征向量(写出 的展开式,说明其余项趋于 0)。
- 马尔可夫矩阵(每列元素相加为 1,元素非负)一定以 1 为特征值吗?构造一个 例子验证,并解释它对应的平稳分布。
章末自测
- 特征向量 满足?
- A.
- B.
- C.
- D.
- 特征方程是?
- A.
- B.
- C.
- D.
- 的特征值是?
- A.
- B.
- C.
- D.
- 是 的特征向量,对应的特征值是?
- A.
- B.
- C.
- D.
- 特征向量可以?
- A. 乘任意非零常数仍成立
- B. 取零向量
- C. 任意向量都是
- D. 只有一个
- 对角化要求 有?
- A. 至少一个特征向量
- B. 个线性无关的特征向量
- C. 行列式为 0
- D. 对称性
- (A 可对角化)
- A.
- B.
- C.
- D.
- 幂法收敛到?
- A. 最小特征值
- B. 绝对值最大的特征值
- C. 特征值的平均值
- D. 行列式
- 瑞利商 在 是特征向量时等于?
- A.
- B. 特征值
- C. 秩
- D. 迹
- 对称矩阵的特征值?
- A. 一定是实数
- B. 一定是复数
- C. 一定是整数
- D. 一定是正数
