18.06 第 13 讲:第一次测验复习
- 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 翻出几份旧测验,一道一道读题,现场做。我把他做的每道题都交给 NumPy 重算了一遍,发现这些题几乎都靠同一个动作解决:先数形状和秩,再用 、、 把四个子空间的维数写出来。比如那个 10 × 6 的矩阵 ,秩是 6, 的零空间维数就是 ,全程不需要消元。
视频:Lecture 13: Quiz 1 review(OCW 页面与字幕) 教材:《Introduction to Linear Algebra》第 6 版 第 1 到 3 章 前置:第 12 讲:图、网络与关联矩阵 一句话:测验题的套路是“先看形状和秩,再用四个子空间的维数公式回答”,能不做乘法就不做乘法。
- 这一讲是纯做题,本篇按他的出题顺序重算,每一题都有代码。想自己先想一遍,就先暂停视频,想完再对答案。
- 他做 那道题时,“左乘可逆矩阵不改变零空间”这句话值得认真听,后面很多地方会用到。
- 最后几道判断题(交换两行、 为什么不能同时是一行和零空间里的向量)很短,但它们直接通向下一讲,别倍速。
- 字幕是自动转写的,题目里的矩阵在黑板上,转写里经常缺数字。下面凡是我根据字幕上下文还原的矩阵,我都会说明。
三个向量张成几维
第一题:、、 是 里的非零向量,它们张成的子空间可能是几维?
答案是 1、2 或 3。不会是 0,因为向量非零(全是零向量才会得到零维子空间);不会超过 3,因为只有三个向量。三种维数各举一个例子:三个都是 的倍数得 1 维, 得 2 维,三个随机向量得 3 维。这个检验放在下一节的代码块开头。
5 × 3 的阶梯形与它的两个拼接
第二题是整场复习的主菜。 是 5 × 3 的阶梯形矩阵,有三个主元()。他连着问了几个小问题:
- 的零空间是什么?三列无关,所以只有零向量。
- 是 10 × 3,它的阶梯形是什么,秩是多少?
- 是 10 × 6,秩是多少?
- 的零空间维数是多少?
对 ,他的想法是把消元看成块操作:第一块乘 加到第二块,得到 ,所以秩还是 3。对 ,第一行块减去第二行块得到 ,整理成 的样子,每一块有 3 个主元,一共 6 个,秩是 6。最后一问: 是 6 × 10,零空间在 里,维数是 。
字幕里没有 的具体数字,我自己选了一个上三角的例子,下面的脚本同时验证了第一题的三种维数,以及这一题的每一问:
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) rng = np.random.default_rng(1806)
# R^7 里三个非零向量张成的子空间,维数只能是 1、2、3 u = rng.standard_normal(7) v = rng.standard_normal(7) cases = { "三个都是 u 的倍数": np.column_stack([u, 2 * u, -3 * u]), "w = u + v": np.column_stack([u, v, u + v]), "三个随机向量": rng.standard_normal((7, 3)), } for name, M in cases.items(): print(f"{name}:维数 = {np.linalg.matrix_rank(M)}")
# 5 x 3 的阶梯形 U,三个主元 U = np.array( [ [1.0, 2.0, 3.0], [0.0, 4.0, 5.0], [0.0, 0.0, 6.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], ] ) print("U 的秩:", np.linalg.matrix_rank(U)) # 零空间只有零向量:U @ x = 0 的最小二乘解就是 0,且 U 的最小奇异值 > 0 print("U 的奇异值:", np.linalg.svd(U, compute_uv=False))
# B = [U; 2U]:把第一块乘 -2 加到第二块,消元一步就得到 [U; 0] B = np.vstack([U, 2 * U]) E = np.block([[np.eye(5), np.zeros((5, 5))], [-2 * np.eye(5), np.eye(5)]]) print("B 的秩:", np.linalg.matrix_rank(B)) print("E @ B 等于 [U; 0]:", np.allclose(E @ B, np.vstack([U, 0 * U])))
# C = [[U, U], [U, 0]],10 x 6 C = np.block([[U, U], [U, np.zeros((5, 3))]]) r = np.linalg.matrix_rank(C) print("C 的形状:", C.shape, ",秩:", r) print("N(C^T) 的维数 = m - r =", C.shape[0] - r)
# 用奇异值分解直接取出 N(C^T) 的一组基并验证 left, s, _ = np.linalg.svd(C) Y = left[:, r:] print( "N(C^T) 基的列数:", Y.shape[1], ",C^T @ Y = 0:", np.allclose(C.T @ Y, 0), )
if __name__ == "__main__": main()三个都是 u 的倍数:维数 = 1w = u + v:维数 = 2三个随机向量:维数 = 3U 的秩: 3U 的奇异值: [9.0125 2.9975 0.8884]B 的秩: 3E @ B 等于 [U; 0]: TrueC 的形状: (10, 6) ,秩: 6N(C^T) 的维数 = m - r = 4N(C^T) 基的列数: 4 ,C^T @ Y = 0: True的秩没有因为多了一块 而增加:,多出来的五行全被消成了零。 的秩却从 3 涨到 6:消元之后左右两块各自带来三个新的主元,没有谁重复谁。最后用 SVD 取出 的四个基向量, 确实是零。(换成任何有三个主元的 ,这些答案都不变,它们只依赖形状和秩。)
只给完全解,倒推矩阵
这类题的出法有点反着来: 不给矩阵,只给 的完全解,让你回答行空间的维数、矩阵本身、有解的条件。据我对字幕上下文的还原,完全解是
字幕里这几个向量的数字没有完整转写出来,我是靠他后面的推理反推的:他说第一列是 ,第二列是 ,最后一列全零。这三句话和上面的向量是自洽的。
推理很直接。完全解里有两个无关的零空间向量,所以零空间是 2 维,,秩 。矩阵怎么找: 而 只有第一个分量非零,所以第一列是 ; 在零空间里,说明第三列是零; 在零空间里,说明第二列是第一列的相反数。结果
列空间就是 的所有倍数,所以 有解,当且仅当 是 的倍数(他回答“能不能对每个 都有解”时说的是“不能”)。
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True) rng = np.random.default_rng(1806)
# 题目只给了完全解 x = x_p + c1 * n1 + c2 * n2,右端项是 b,没给矩阵 b = np.array([2.0, 4.0, 2.0]) x_p = np.array([2.0, 0.0, 0.0]) n1 = np.array([1.0, 1.0, 0.0]) n2 = np.array([0.0, 0.0, 1.0])
# A @ x_p = b:x_p 只取第一列,所以第一列 = b / 2 col1 = b / x_p[0] # A @ n2 = 0:最后一列是零;A @ n1 = 0:第二列 = -第一列 A = np.column_stack([col1, -col1, np.zeros(3)]) print("A =") print(A)
print("A @ x_p = b:", np.allclose(A @ x_p, b)) print("A @ n1 = 0:", np.allclose(A @ n1, 0)) print("A @ n2 = 0:", np.allclose(A @ n2, 0))
r = np.linalg.matrix_rank(A) print("行空间维数 = 秩 =", r, ",零空间维数 =", 3 - r)
# 任意 c1、c2 都给出解 c1, c2 = rng.standard_normal(2) x = x_p + c1 * n1 + c2 * n2 print("随机取 c1、c2,A @ x = b:", np.allclose(A @ x, b))
# 什么样的 b 有解:b 必须在列空间里,也就是 (1, 2, 1) 的倍数 for rhs in (np.array([3.0, 6.0, 3.0]), np.array([1.0, 0.0, 0.0])): solvable = np.linalg.matrix_rank(np.column_stack([A, rhs])) == r print(f"b = {rhs},有解:", solvable)
if __name__ == "__main__": main()A =[[ 1. -1. 0.] [ 2. -2. 0.] [ 1. -1. 0.]]A @ x_p = b: TrueA @ n1 = 0: TrueA @ n2 = 0: True行空间维数 = 秩 = 1 ,零空间维数 = 2随机取 c1、c2,A @ x = b: Trueb = [3. 6. 3.],有解: Trueb = [1. 0. 0.],有解: False行空间维数是 1,零空间维数是 2,加起来是 。 有解, 没有。他在这里提醒了一句:别忘了秩等于 或等于 的那些好情形,上一章讲过,这道题只是“秩很小、零空间很大”的那一头。
四道判断题
判断题没有一道需要计算,但每一道都值得举反例。 他说真正的测验里不会有判断题,这几道只是拿来快速复习。
- 若方阵的零空间只有零向量,则 的零空间也只有零向量。对:已知 ,而 ,所以 。他强调这是个非常重要的事实。
- 5 × 5 矩阵构成一个 25 维的向量空间,其中可逆的矩阵构成子空间吗?不:零矩阵不在里面,而且两个可逆矩阵的和可能奇异( 加 就是零矩阵)。奇异矩阵也不行,因为两个奇异矩阵的和可能可逆。
- 若 ,则 ?错,经典反例是 。他管它叫“危险的矩阵”,说后面会反复出现,我猜是讲到特征值和 Jordan 形的时候。
- 的矩阵,列线性无关,则每个右端项都有解?对:秩是 ,矩阵可逆,什么都不会出错。他在这里拿观众投票开玩笑,结果五五开(第十三讲了,台下还有一半人举手说不一定,我替他们捏一把汗)。
import numpy as np
def nullity(M: np.ndarray) -> int: return M.shape[1] - np.linalg.matrix_rank(M)
def main() -> None: np.set_printoptions(precision=4, suppress=True) rng = np.random.default_rng(1806)
# 1. 方阵 A 的零空间只有零向量,A^T 的零空间也只有零向量 A = rng.standard_normal((5, 5)) print("dim N(A) =", nullity(A), ",dim N(A^T) =", nullity(A.T))
# 2. 5 x 5 的可逆矩阵不构成子空间:没有零矩阵,和也可能奇异 P = np.eye(5) Q = -np.eye(5) print("det(P) =", np.linalg.det(P), ",det(Q) =", np.linalg.det(Q)) print("P + Q 的秩:", np.linalg.matrix_rank(P + Q), "(零矩阵,不可逆)")
# 3. B^2 = 0 推不出 B = 0 B = np.array([[0.0, 1.0], [0.0, 0.0]]) print("B @ B =") print(B @ B)
# 4. m x m 且列无关,则对每个右端项 Ax = b 有解 M = rng.standard_normal((6, 6)) worst = 0.0 for _ in range(1000): b = rng.standard_normal(6) x = np.linalg.solve(M, b) worst = max(worst, np.linalg.norm(M @ x - b)) rk = np.linalg.matrix_rank(M) print("秩 =", rk, ",1000 个随机 b 的最大残差 =", f"{worst:.1e}")
if __name__ == "__main__": main()dim N(A) = 0 ,dim N(A^T) = 0det(P) = 1.0 ,det(Q) = -1.0P + Q 的秩: 0 (零矩阵,不可逆)B @ B =[[0. 0.] [0. 0.]]秩 = 6 ,1000 个随机 b 的最大残差 = 1.3e-14第一题对一个随机 5 × 5 矩阵,两个零空间的维数都是 0。第二题的 秩是 0。第四题我对 1000 个随机右端项求解,最大残差 1.3e-14,是舍入误差的量级,而不是“有时有解”。
分解乘积 B = CD:左乘可逆矩阵不改变零空间
下一题给的是一个以乘积形式出现的矩阵,: 是 3 × 3 的, 是 3 × 4 的阶梯形。我根据字幕还原出的两个因子是
字幕里数字是连着念出来的,我是按行断开的。我用来核对的是:他说 的第一列是 ,我还原出的 和 相乘确实给出这一列;他读出的特解里的 、、 也都对得上。
这一题的关键是: 可逆,所以 和 有相同的零空间。若 则 ;反过来 时左乘 就得到 。因此 的零空间不用乘出来看,直接读 :主元在前两列,自由变量是第 3、4 个,特解是 的两列,其中 是 右上角的 2 × 2 块。
他接着解 。 的第一列恰好就是右端项,所以特解取 ,完全解是特解加上两个特解的任意组合。有学生问“特解是不是唯一的”,他的回答是不唯一,挑最方便的那个。
import numpy as np
def main() -> None: np.set_printoptions(precision=4, suppress=True)
# B = C @ D:C 是 3 x 3,D 是 3 x 4 的阶梯形 C = np.array([[1.0, 1.0, 0.0], [0.0, 1.0, 0.0], [1.0, 0.0, 1.0]]) D = np.array( [ [1.0, 0.0, -1.0, 2.0], [0.0, 1.0, 1.0, -1.0], [0.0, 0.0, 0.0, 0.0], ] ) B = C @ D print("B =") print(B) print( "det(C) =", round(np.linalg.det(C), 6), ",秩(B) =", np.linalg.matrix_rank(B), )
# 零空间:D 的自由变量是第 3、4 个,特解 = [-F; I] F = D[:2, 2:] N = np.vstack([-F, np.eye(2)]) print("特解矩阵 N(每列一个特解):") print(N) print("D @ N = 0:", np.allclose(D @ N, 0)) print("B @ N = 0:", np.allclose(B @ N, 0))
# 解 B x = (1, 0, 1):B 的第一列恰好是它 b = np.array([1.0, 0.0, 1.0]) x_p = np.array([1.0, 0.0, 0.0, 0.0]) print("B 的第一列 =", B[:, 0], ",B @ x_p = b:", np.allclose(B @ x_p, b)) rng = np.random.default_rng(1806) c = rng.standard_normal(2) x = x_p + N @ c print("x_p + N @ c 仍是解:", np.allclose(B @ x, b))
if __name__ == "__main__": main()B =[[ 1. 1. 0. 1.] [ 0. 1. 1. -1.] [ 1. 0. -1. 2.]]det(C) = 1.0 ,秩(B) = 2特解矩阵 N(每列一个特解):[[ 1. -2.] [-1. 1.] [ 1. 0.] [ 0. 1.]]D @ N = 0: TrueB @ N = 0: TrueB 的第一列 = [1. 0. 1.] ,B @ x_p = b: Truex_p + N @ c 仍是解: True 的秩是 2,4 列减 2 个主元,零空间是 2 维,和 的两列一致。B @ N 和 D @ N 都是零,验证了“左乘可逆的 不改变零空间”。他还说,“特解加零空间”这个模式不只限于有限矩阵,它在整个线性系统的数学里都在用。
四个子空间的几道判断题
最后一批题,都是在问“哪个子空间变了,哪个没变”。
- 方阵的行空间等于列空间吗?不一定。 的行空间是 的倍数,列空间是 的倍数,完全不同。对称矩阵能保证两者相等。
- 和 有相同的四个子空间吗?有。
- 两个矩阵有相同的四个子空间,一个就是另一个的倍数吗?错。反例:任意两个可逆的 6 × 6 矩阵,四个子空间都是 或 。他顺便说,它们至少有相同的秩,但真正能说的更多,他没有展开。
- 交换 的两行,哪些子空间不变?行空间和零空间不变,列空间会变。
import numpy as np
def rank(M: np.ndarray) -> int: return int(np.linalg.matrix_rank(M))
def main() -> None: np.set_printoptions(precision=4, suppress=True) rng = np.random.default_rng(1806)
# 1. 方阵的行空间不一定等于列空间 N = np.array([[0.0, 1.0], [0.0, 0.0]]) row_vec = np.array([[0.0, 1.0]]) col_vec = np.array([[1.0], [0.0]]) print("(0, 1) 在行空间里:", rank(np.vstack([N, row_vec])) == rank(N)) print("(1, 0) 在行空间里:", rank(np.vstack([N, col_vec.T])) == rank(N)) print("(1, 0) 在列空间里:", rank(np.hstack([N, col_vec])) == rank(N))
# 2. A 和 -A 的四个子空间相同 A = rng.standard_normal((4, 3)) @ rng.standard_normal((3, 5)) print("A 的秩:", rank(A), ",A 是 4 x 5") print("列空间相同:", rank(np.hstack([A, -A])) == rank(A)) print("行空间相同:", rank(np.vstack([A, -A])) == rank(A))
# 3. 四个子空间相同,不代表差一个倍数:两个可逆的 6 x 6 X = rng.standard_normal((6, 6)) Y = rng.standard_normal((6, 6)) print("秩:", rank(X), rank(Y), ",X / Y 的比值:") print((X / Y)[0, :3])
# 4. 交换两行:行空间、零空间不变,列空间变 S = np.array([[1.0, 0.0, 1.0], [0.0, 0.0, 0.0], [0.0, 1.0, 1.0]]) T = S[[1, 0, 2]] n = np.array([1.0, 1.0, -1.0]) print( "S @ n = 0,T @ n = 0:", np.allclose(S @ n, 0), np.allclose(T @ n, 0) ) print("行空间不变:", rank(np.vstack([S, T])) == rank(S)) print("列空间不变:", rank(np.hstack([S, T])) == rank(S))
# 5. (1, 2, 3) 不能既是某一行,又在零空间里 v = np.array([1.0, 2.0, 3.0]) M = np.vstack([v, rng.standard_normal((2, 3))]) print("M 的第一行乘 v =", (M @ v)[0], ",v 点乘 v =", v @ v)
if __name__ == "__main__": main()(0, 1) 在行空间里: True(1, 0) 在行空间里: False(1, 0) 在列空间里: TrueA 的秩: 3 ,A 是 4 x 5列空间相同: True行空间相同: True秩: 6 6 ,X / Y 的比值:[-1.5896 2.3334 -0.5318]S @ n = 0,T @ n = 0: True True行空间不变: True列空间不变: FalseM 的第一行乘 v = 14.0 ,v 点乘 v = 14.0四个小题各对一类: 的 在行空间里, 不在; 在列空间里。两个随机的可逆矩阵逐元素相除,比值是 、、,不是常数,所以谁也不是谁的倍数。交换两行后, 仍然在零空间里,行空间不变,列空间变了。
最后一题:为什么 (1, 2, 3) 不能同时是一行和零空间里的向量
他用这道题收尾,说它引向下一章。如果 的第一行是 , 又在零空间里,那 的第一个分量就是
不是零,矛盾。代码块最后一行用随机矩阵确认了这个 14:不管另外两行是什么,第一个分量都是 。
这说明行空间和零空间同在 里,却只共享零向量。更准确的说法是:零空间垂直于行空间。他说这是下一讲的内容,并祝大家考试顺利。
我读完这份复习有一个感受:每一道题我都是先看形状,再数秩,最后才碰数字。这像编程里先看函数签名再读函数体,能省下大把时间。(反过来说,我花在“还原字幕里被吞掉的数字”上的时间,大概是真正做题的三倍。)
下一讲是考试之后的第一讲,主题正是上面最后一题留下的:正交。见 18.06 第 14 讲:正交向量与正交子空间。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!











