18.06 第 32 讲:第三次测验复习
- 118.06 第 1 讲:方程组的行图与列图
- 218.06 第 2 讲:用矩阵做消元
- 318.06 第 3 讲:矩阵乘法的四种看法与逆矩阵
- 418.06 第 4 讲:分解成 A = LU
- 518.06 第 5 讲:转置、置换与向量空间
- 618.06 第 6 讲:列空间与零空间
- 718.06 第 7 讲:解 Ax = 0,主变量与特解
- 818.06 第 8 讲:解 Ax = b,行最简形 R
- 918.06 第 9 讲:线性无关、基与维数
- 1018.06 第 10 讲:四个基本子空间
- 1118.06 第 11 讲:矩阵空间、秩 1 矩阵与小世界图
- 1218.06 第 12 讲:图、网络与关联矩阵
- 1318.06 第 13 讲:第一次测验复习
- 1418.06 第 14 讲:正交向量与正交子空间
- 1518.06 第 15 讲:投影到子空间
- 1618.06 第 16 讲:投影矩阵与最小二乘
- 1718.06 第 17 讲:正交矩阵与 Gram-Schmidt
- 1818.06 第 18 讲:行列式的性质
- 1918.06 第 19 讲:行列式公式与代数余子式
- 2018.06 第 20 讲:Cramer 法则、逆矩阵与体积
- 2118.06 第 21 讲:特征值与特征向量
- 2218.06 第 22 讲:对角化与矩阵的幂
- 2318.06 第 23 讲:微分方程与 exp(At)
- 2418.06 第 24 讲:Markov 矩阵与 Fourier 级数
- 2518.06 第 24b 讲:第二次测验复习
- 2618.06 第 25 讲:对称矩阵与正定性
- 2718.06 第 26 讲:复矩阵与快速 Fourier 变换
- 2818.06 第 27 讲:正定矩阵与极小值
- 2918.06 第 28 讲:相似矩阵与 Jordan 标准形
- 3018.06 第 29 讲:奇异值分解
- 3118.06 第 30 讲:线性变换及其矩阵
- 3218.06 第 31 讲:基变换与图像压缩
- 3318.06 第 32 讲:第三次测验复习本文
- 3418.06 第 33 讲:左逆、右逆与伪逆
- 3518.06 第 34 讲:期末复习
这一讲没有新定理,Strang 拿几道旧考题把第六章的东西串了一遍:特征值、对称与正定、相似矩阵、SVD。我的做法是把每道题都交给 NumPy 验证。其中最有意思的一个数字出在 SVD:从 和 分别求出特征向量来拼 ,列的符号有 4 种选法,只有 1 种能还原 ,另外 3 种的误差分别是 8.4853、11.3137 和 14.1421。
视频:Lecture 32: Quiz 3 review(OCW 页面与字幕) 教材:《Introduction to Linear Algebra》第 6 版第 6 到 8 章(录像里的测验只到特征值那一章,线性变换留给期末,所以这一讲实际用到的是第 6 章与第 7 章的 SVD) 前置:第 31 讲:基变换与图像压缩 一句话:做特征值的题先看矩阵属于哪个家族,对称、反对称、正交这三类都满足 ,特征向量正交,剩下的全看特征值。
- 开头他列了本章要记住的几条:对称矩阵的实特征值与 、正定、相似矩阵特征值相同、SVD。这一段很短,值得完整听一遍当清单用。
- 第一道微分方程题(反对称矩阵)和后面那道“ 取哪些值”的题,我在下面都算过了,可以倍速。其中“ 是特征向量正交的精确条件”这句他讲得很快,建议回放。
- SVD 那一段他承认自己在上一次讲课时符号选错了。这是全篇最值得认真听的地方,本篇第三节用代码复现了这个错误。
- 最后的“对称又正交”真假题短而密,每一句都是一个结论,暂停着听比较稳。
反对称矩阵:特征值在虚轴上
第一道题是一个 3 × 3 的微分方程 ,矩阵对角线是 0,上面是 ,下面是 :
没有给初值,所以要的是通解 。他先问这个矩阵奇不奇异:第一行和第三行只差一个符号,所以奇异,。再看 ,反对称矩阵的特征值是纯虚数,特征多项式 给出 。
结论有三个。解既不衰减也不爆炸,因为 的模永远是 1。解是周期的,周期 满足 ,即 。特征向量两两正交。下面用 NumPy 一次验证:
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) # 黑板上的反对称矩阵:对角线为 0,上面是 -1,下面是 +1 A = np.array([[0.0, -1.0, 0.0], [1.0, 0.0, -1.0], [0.0, 1.0, 0.0]]) print("A.T == -A:", np.array_equal(A.T, -A))
lam, S = np.linalg.eig(A) print("特征值的虚部:", np.sort(lam.imag)) print("特征值实部的最大绝对值:", np.abs(lam.real).max()) print("sqrt(2) =", np.sqrt(2.0)) # 特征向量两两正交(复向量用共轭转置) print("S^H S 是单位矩阵:", np.allclose(S.conj().T @ S, np.eye(3))) # 反对称矩阵满足 A A^T = A^T A print("A A^T == A^T A:", np.allclose(A @ A.T, A.T @ A))
# e^{At} = S diag(e^{lambda t}) S^{-1} def expm(t: float) -> np.ndarray: return (S @ np.diag(np.exp(lam * t)) @ np.linalg.inv(S)).real
period = np.pi * np.sqrt(2.0) print("周期 T = pi * sqrt(2) =", period) for t in [0.5 * period, period]: err = np.linalg.norm(expm(t) - np.eye(3)) print(f"t = {t:.4f}:||e^(At) - I|| = {err:.2e}")
# 解既不增长也不衰减:每个时刻的长度都一样 u0 = np.array([1.0, 2.0, 3.0]) ts = np.linspace(0.0, period, 7) print("||u(t)||:", np.array([np.linalg.norm(expm(t) @ u0) for t in ts]))
if __name__ == "__main__": main()A.T == -A: True特征值的虚部: [-1.4142 0. 1.4142]特征值实部的最大绝对值: 5.4814816543375465e-17sqrt(2) = 1.4142135623730951S^H S 是单位矩阵: TrueA A^T == A^T A: True周期 T = pi * sqrt(2) = 4.442882938158366t = 2.2214:||e^(At) - I|| = 2.83e+00t = 4.4429:||e^(At) - I|| = 8.45e-15||u(t)||: [3.7417 3.7417 3.7417 3.7417 3.7417 3.7417 3.7417]这个脚本有三处值得看。特征值的实部最大是 ,也就是 0;虚部是 。 在半个周期处离 有 2.83,到整个周期 处只剩 ,所以周期确实是 。而 在七个等间隔的时刻都是 3.7417(也就是 , 的长度),解一直在一个球面上绕。
他顺带补了一句我觉得值得抄下来的话:特征向量正交的精确条件是 。对称矩阵(两边都是 )、反对称矩阵(两边都是 )、正交矩阵(两边都是 )都满足,这就是第六章里三个最重要的家族。输出里的 A A^T == A^T A: True 是反对称这一项。(用复向量就要用共轭转置,所以脚本里写的是 S.conj().T。)
最后他提到 :矩阵可对角化时它是 ,脚本里的 expm 就是这么写的,没有调用任何现成的矩阵指数函数。
只知道特征值和特征向量,能说什么
第二道题给了一个 3 × 3 矩阵的三个特征向量(两两正交)和特征值(一个是 0,另一个是 2,还有一个未知的 ),然后连续问:对哪些 可对角化、对称、正定、是 Markov 矩阵、 是投影矩阵。字幕没有念出黑板上的向量,所以下面的向量是我自己选的一组正交基,不是原题的数字,结论只依赖“正交”这一点。
他的回答顺序是:可对角化只看特征向量够不够,三个正交向量一定无关,所以任何 都行;特征向量正交加上特征值为实数就是对称,所以所有实数 ;正定不可能,因为有特征值 0, 时是半正定(“安慰奖”);Markov 不可能,因为特征值不能超过 1,而这里有 2; 是投影矩阵要求特征值只能是 0 或 1,所以 或 。
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) # 字幕没有念出板上的向量,我自己选了一组两两正交的特征向量 S = np.array([[1.0, 1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 0.0, -2.0]]) Q = S / np.linalg.norm(S, axis=0) print("三个特征向量两两正交:", np.allclose(Q.T @ Q, np.eye(3)))
for c in [-1.0, 0.0, 1.0, 2.0]: # 特征值 0、2、c,特征向量是 Q 的三列:A = Q diag(0, 2, c) Q^T A = Q @ np.diag([0.0, 2.0, c]) @ Q.T lam = np.linalg.eigvalsh(A) P = A / 2.0 print(f"c = {c:4.1f},特征值 {np.round(lam, 10) + 0.0}") print(" 对称:", np.allclose(A, A.T)) print(" 半正定:", bool(lam.min() > -1e-12)) print(" 正定:", bool(lam.min() > 1e-12)) print(" 有特征值大于 1(Markov 不允许):", bool(lam.max() > 1.0)) print( " A / 2 是投影矩阵:", np.allclose(P @ P, P) and np.allclose(P, P.T), )
if __name__ == "__main__": main()三个特征向量两两正交: Truec = -1.0,特征值 [-1. 0. 2.] 对称: True 半正定: False 正定: False 有特征值大于 1(Markov 不允许): True A / 2 是投影矩阵: Falsec = 0.0,特征值 [0. 0. 2.] 对称: True 半正定: True 正定: False 有特征值大于 1(Markov 不允许): True A / 2 是投影矩阵: Truec = 1.0,特征值 [0. 1. 2.] 对称: True 半正定: True 正定: False 有特征值大于 1(Markov 不允许): True A / 2 是投影矩阵: Falsec = 2.0,特征值 [0. 2. 2.] 对称: True 半正定: True 正定: False 有特征值大于 1(Markov 不允许): True A / 2 是投影矩阵: True四个 值的结果和他的口头回答一一对应: 连半正定都不是, 是半正定但没有一个正定,所有行的“有特征值大于 1”都是 True,只有 和 让 通过了 与 。我只试了四个点,并不能证明“只有这两个”,但 推出 ,证明是他那一句话里的。
SVD:符号是唯一会出错的地方
第三个话题是 SVD。 对任何矩阵成立,关键是 :中间是对角,两边是同一个正交矩阵,所以 是 的特征向量矩阵, 是它的特征值。同样 给出 。
然后是他承认的那个错误。上次上课他用 的特征向量当 ,符号撞上了错的那一半:特征向量乘以 还是特征向量,光凭 决定不了符号。正确的做法是定了 之后,用 反推 ,这样符号被 绑定。他说自己有 50% 的概率选对,结果没选对。
我用 复现(这是我挑的矩阵,不是黑板上的)。把 的两列符号四种组合全试一遍:
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) A = np.array([[4.0, 4.0], [-3.0, 3.0]])
# 第一步:A^T A 的特征向量给出 V,特征值开方给出 sigma w, V = np.linalg.eigh(A.T @ A) order = np.argsort(w)[::-1] w, V = w[order], V[:, order] sigma = np.sqrt(w) print("sigma =", sigma)
# 第二步(对的):由 A v = sigma u 得到 u,符号随 V 定下来 U_good = (A @ V) / sigma print( "A v = sigma u 得到的 U 满足 A = U Sigma V^T:", np.allclose(U_good @ np.diag(sigma) @ V.T, A), )
# 第二步(Strang 当年出错的做法):独立求 A A^T 的特征向量, # 但每一列的符号是任意的,一共 2 * 2 = 4 种选法 w2, U_eig = np.linalg.eigh(A @ A.T) U_eig = U_eig[:, np.argsort(w2)[::-1]] good = 0 for s1 in [1.0, -1.0]: for s2 in [1.0, -1.0]: U_try = U_eig * np.array([s1, s2]) err = np.linalg.norm(U_try @ np.diag(sigma) @ V.T - A) good += int(err < 1e-10) print(f"符号 ({s1:4.1f}, {s2:4.1f}):误差 {err:.4f}") print("4 种符号里能还原 A 的有", good, "种")
# 和 NumPy 对照 U, s, Vt = np.linalg.svd(A) print("np.linalg.svd 的奇异值:", s)
if __name__ == "__main__": main()sigma = [5.6569 4.2426]A v = sigma u 得到的 U 满足 A = U Sigma V^T: True符号 ( 1.0, 1.0):误差 0.0000符号 ( 1.0, -1.0):误差 8.4853符号 (-1.0, 1.0):误差 11.3137符号 (-1.0, -1.0):误差 14.14214 种符号里能还原 A 的有 1 种np.linalg.svd 的奇异值: [5.6569 4.2426]第一行的“对的”做法用 ,通过了。独立求 的特征向量后,4 种符号只有 这一种能还原 (这次 eigh 恰好吐出了对的符号,但没有任何东西保证它会这样),另外三种的误差是 8.4853、11.3137 和 14.1421。表里是 4 选 1,也就是 25%;Strang 当时只有一个符号没定,所以他说 50% 的运气。最后一行用 np.linalg.svd 对照,两个奇异值 5.6569 与 4.2426 和手算的 、 一致。
他接着出了几个问 SVD 的“读图”题。 是 2 × 2 的可逆矩阵;把 2 换成 就不是 SVD 了,因为奇异值不能为负; 的话秩为 1,零空间维数为 1, 在零空间里, 在 的零空间里。他说得很直白:SVD 多花一点时间,但把所有基本子空间一次摆了出来。
对称又正交的矩阵
最后一道是真假题。 既对称又正交,问:
- 特征值是什么?实数(对称)且模为 1(正交:),所以只能是 或 。
- 一定正定吗?不,可以有 。
- 没有重复特征值吗?假,只要够大, 里总有一个重复。
- 可对角化吗?可以,而且能用正交的 。
- 非奇异吗?是,正交矩阵都可逆。
最后一步:证明 是投影矩阵。对称是显然的;平方得 ,而 对称正交意味着 ,所以 ,结果是 自己。换个角度:特征值是 ,加 后是 和 ,除以 2 就是 和 。
“对称又正交”的最典型例子是 Householder 反射 。我用它验证上面的每一条,并且顺手验证他开头说的“相似矩阵特征值相同,幂也只差一个 和 ”:
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) rng = np.random.default_rng(1806)
# Sigma = diag(3, 2) 与 diag(3, 0):U、V 用随机正交矩阵 U, _ = np.linalg.qr(rng.standard_normal((2, 2))) V, _ = np.linalg.qr(rng.standard_normal((2, 2))) for s in [(3.0, 2.0), (3.0, 0.0)]: A = U @ np.diag(s) @ V.T print( f"Sigma = diag{s}:秩 {np.linalg.matrix_rank(A)},", f"det = {np.linalg.det(A):.4f}", ) # 第二个奇异值为 0 时,v2 在零空间里,u2 在 A^T 的零空间里 print("A v2 =", np.round(A @ V[:, 1], 10) + 0.0) print("A^T u2 =", np.round(A.T @ U[:, 1], 10) + 0.0)
# 对称又正交的矩阵:Householder 反射 A = I - 2 u u^T n = 5 u = rng.standard_normal((n, 1)) u /= np.linalg.norm(u) H = np.eye(n) - 2.0 * u @ u.T print( "H 对称且正交:", np.allclose(H, H.T), np.allclose(H @ H.T, np.eye(n)) ) print("特征值:", np.linalg.eigvalsh(H)) print("H @ H == I:", np.allclose(H @ H, np.eye(n))) P = 0.5 * (H + np.eye(n)) print( "(H + I) / 2 是投影矩阵:", np.allclose(P @ P, P) and np.allclose(P, P.T), ) print("P 的特征值:", np.round(np.linalg.eigvalsh(P), 10) + 0.0) print("trace(P) =", np.trace(P))
# 相似矩阵:B = M^{-1} A M 与 A 的特征值相同,B^k = M^{-1} A^k M M = rng.standard_normal((n, n)) B = np.linalg.inv(M) @ H @ M print( "相似矩阵特征值相同:", np.allclose(np.sort(np.linalg.eigvals(B).real), np.linalg.eigvalsh(H)), ) k = 7 lhs = np.linalg.matrix_power(B, k) rhs = np.linalg.inv(M) @ np.linalg.matrix_power(H, k) @ M print(f"B^{k} == M^-1 H^{k} M:", np.allclose(lhs, rhs))
if __name__ == "__main__": main()Sigma = diag(3.0, 2.0):秩 2, det = 6.0000Sigma = diag(3.0, 0.0):秩 1, det = 0.0000A v2 = [0. 0.]A^T u2 = [0. 0.]H 对称且正交: True True特征值: [-1. 1. 1. 1. 1.]H @ H == I: True(H + I) / 2 是投影矩阵: TrueP 的特征值: [0. 1. 1. 1. 1.]trace(P) = 4.0相似矩阵特征值相同: TrueB^7 == M^-1 H^7 M: True 的特征值是一个 加四个 ( 方向被翻转,其余方向不动), 通过了, 的特征值是一个 0 加四个 1,迹为 4,正是投影到 4 维子空间。随机的 5 × 5 矩阵 做出来的相似矩阵 与 的特征值一致, 也成立。再强调一遍他的原话: 改变特征向量,但不改变特征值。(另外两行关于秩 1 的输出,A v2 与 A^T u2 都是零向量,是上一节“读图”题的验证。)
下一讲回到一个我觉得更有趣的话题(我对“有趣”的标准很低:只要某个误差能从 0 跳到 14):矩阵不可逆、方程组无解或有无穷多解的时候,到底该用什么“逆”。Strang 管这个叫左逆、右逆与伪逆,而它恰好是 SVD 的又一个应用。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!











