矩阵论课后习题答案这类资源,用过的人大概都有一段不太愉快的回忆:题目看着眼熟,翻到答案发现只给了一个最终结果,中间跳过的步骤恰好是自己卡住的那三行推导。我前后整理过几轮这类答案,也帮身边同学逐题核对过,慢慢摸出一套相对靠谱的用法。这篇就围绕矩阵论课后习题答案这份资源,讲清它到底包含哪些内容、按什么逻辑组织、哪些题值得逐行推、哪些题可以直接跳过、以及如何用几行脚本把答案验一遍。适合正在啃矩阵论的学生、准备考研复试或期末突击的人,也适合已经工作、想把线性代数那套东西真正用起来、回头补课的技术从业者。不要求你数学基础多扎实,只要会基本的矩阵乘法,剩下的都能跟着走。
1. 这份答案资源到底解决什么问题
1.1 从“对答案”到“验证思路”的定位转变
绝大多数人对课后答案的期待是“我做完题,翻过去看看数字对不对”。这个用法不能说错,但价值被压得很低。矩阵论这门课和微积分不一样,它的题目往往不是算出一个数就结束,而是让你证明某个空间是同构的、某个矩阵可以相似对角化、某个分解存在且唯一。这类题的标准答案通常给的是“构造—验证”两段式结构,你真正需要从答案里抄走的是那个构造是怎么想到的,而不是最后的结论。
我把这类资源的定位重新摆了一下:它更像一份参考实现,而不是标准答案。就像写代码时看别人的开源实现,你不会把代码复制过来就完事,而是看人家在哪个地方做了封装、哪个边界条件提前处理了。矩阵论课后习题答案的价值也一样——它告诉你这道题的最小完整论证链长什么样,哪些条件是必须用上的,哪些是可以绕过的。
这个定位一旦立住,使用方式就跟着变了。做题时先自己写一版,哪怕写得很粗糙、逻辑有跳跃,也先落笔;然后再对照答案,重点看两处:一是你的出发点对不对,二是你的论证有没有漏掉某个关键的中间步骤。多数人卡住的不是不会算,而是没想到从哪个角度切入。答案最有价值的部分恰恰是那个切入点,而它通常只占答案的前两行。
所以我在整理和使用这份资源时,会刻意把“结果”和“路径”分开看。结果用来判断对错,路径用来学习方法。只盯着结果看,做完一百道题还是不会做第一百零一道;盯着路径看,做完二十道题就能摸出这门课的出题套路。
1.2 矩阵论这门课的难点分布与答案的对应关系
先把这门课的骨架摆出来,才知道答案资源该在哪些地方重点看。矩阵论的内容大致分几块:线性空间与线性变换、内积空间、矩阵的标准形(含Jordan标准形、有理标准形)、矩阵分解、矩阵分析(范数、矩阵级数、矩阵函数、矩阵微分)、广义逆与矩阵方程、非负矩阵与特殊矩阵。
这几块的难度分布很不均匀。线性空间与线性变换是地基,概念多、符号杂,但计算量小,难点在于“把抽象定义翻译成具体矩阵运算”;Jordan标准形是分水岭,会的人觉得就是算不变因子,不会的人连初等因子怎么取都搞不清;矩阵分解相对友好,方法固定,套流程就能出结果;矩阵分析里矩阵函数和矩阵微分是最容易翻车的,因为它把微积分的直觉搬到了矩阵上,而矩阵乘法不交换,稍不注意就写错顺序;广义逆的难点在于存在性证明和唯一性证明,计算反而次要。
对应到答案资源上,我的建议是分层次使用:
| 内容模块 | 建议使用方式 | 投入时间占比 |
|---|---|---|
| 线性空间与线性变换 | 逐题精读,重点看构造思路 | 25% |
| 标准形(Jordan、有理标准形) | 对照算例复现全过程 | 25% |
| 矩阵分解 | 看方法模板,独立重做 | 15% |
| 矩阵分析(范数、级数、函数、微分) | 逐行推,验证每一步合法性 | 25% |
| 广义逆与矩阵方程 | 重点看存在性与唯一性证明 | 10% |
这个比例不是拍脑袋定的。前两块加起来占一半,因为它们是后面所有内容的前提,Jordan标准形算不明白,矩阵函数就无从谈起;矩阵分析占四分之一,是因为它最容易在细节上出错,而细节恰恰是答案能补的;矩阵分解只占15%,是因为它套路性强,看两遍就能自己写,没必要在答案上耗太久。
注意:不要按章节顺序从第一页刷到最后一页。矩阵论教材的章节编排往往是“先抽象后具体”,但人的接受顺序是“先具体后抽象”。我的做法是先跳到矩阵分解和矩阵分析这两块,把计算类题目做熟,建立手感,再回头啃线性空间和标准形的证明题,这时候抽象概念有了具体例子垫底,理解速度会快很多。
1.3 不同基础的人该怎么切入
零基础或者线代基础不牢的人,别急着看答案的证明部分。先做一件事:把教材每章开头的定义和定理抄一遍,抄的时候在旁边写一个二阶或三阶的具体矩阵做例子。比如看到“线性变换的核”,就写一个从二维到二维的投影变换,手算出它的核是哪个子空间。这个动作做上两章,再去看答案里的抽象论证,你会发现那些符号突然变得可读了。
有一定基础、只是想在考试里拿分的人,重点看答案的“格式”。矩阵论的证明题对写法有要求,比如证明一个矩阵可对角化,标准流程是先求特征多项式、再求每个特征值的几何重数、再判断是否等于代数重数。答案里这套流程的书写顺序就是阅卷时想看到的顺序。把这个格式背下来,比多做十道题有用。
已经工作、想补课的人,直接跳过纯证明题,主攻矩阵分解、矩阵函数、广义逆这三块。这三块在实际工作里出现频率最高,而且都能用代码验证,学起来反馈快,不容易半途而废。
2. 答案资源的组织方式与内容边界拆解
2.1 按章节映射的目录结构
一份能用的矩阵论课后习题答案,第一眼要看的是它的目录能不能和教材对上。教材版本不同,章节编号差异很大,有的把“矩阵的范数”放在矩阵分析章的第一节,有的单独成章;有的把“矩阵的 Kronecker 积”放到最后一章讲应用,有的塞进矩阵运算那一章。所以拿到资源后,先做一次章节对照,拿教材目录和答案目录并排放,逐条标出对应关系。
我一般会建一张对照表,三列:教材章节号、答案章节号、该章题目数量。这个表看着简陋,但能解决两个实际问题。第一是快速定位,做到第三章某道题卡住了,不用从头翻。第二是发现缺漏,比如教材这一章有28题,答案里只收了20题,那8道要么是证明题被略过,要么是资源本身不全,得提前知道,免得到了考前一天才发现。
对照表还有个隐藏用途:估算工作量。把每章题目数量和自己的可用时间放在一起,就能判断哪些章必须精做、哪些章可以只挑典型题。比如矩阵分解那一章30题,但方法就那几种,挑8道覆盖LU、QR、SVD、满秩分解各两道就够了,剩下22道重复度很高。
提示:对照表做好后存成电子表格,每做完一道题就在后面打个标记,写上“独立完成”“看过答案”“仍需重做”三种状态。临考前只看“仍需重做”那一列,效率比翻书高得多。
2.2 一份合格答案应该包含的四层信息
我把理想的课后答案拆成四层,从下往上依次是:最终结果、关键中间步骤、所用定理的出处、思路的可迁移性。市面上流传的答案质量参差,主要差在上面几层的完整度。
最底层是最终结果,这一层几乎所有资源都有,但也最容易出错。矩阵论的计算题结果往往是矩阵、多项式或者一组基,抄错一个符号整道题就废了。所以第一层信息只能用来快速对自己算出来的东西,不能当依据。
第二层是关键中间步骤。一道证明题如果只给结论,那它跟没给一样;好的答案会写出“由XX定理可知……”“取基为……”“构造矩阵P=……”,这几句才是精华。看答案时我会把这类句子单独摘出来,攒成一个“套路本”。攒到二十来条,你会发现矩阵论的证明翻来覆去就用那么几个手法:构造基、取商空间、用维数公式、用不变子空间、用归纳法。
第三层是定理出处。矩阵论的定理名字多,同一个结论在不同教材里叫法不一样。答案里如果标了“由哈密顿-凯莱定理”,你就知道要去翻那一节;如果只写“显然”,那多半是作者默认你记得。遇到“显然”我就格外警惕,因为这往往是我卡住的地方。
第四层是思路可迁移性,这一层几乎没人写,但最值钱。比如一道题用了“把矩阵看成线性变换在一组基下的表示”这个视角,那这个视角能不能用到下一章的矩阵函数题上?能。这种跨章节的迁移,答案不会主动告诉你,得自己总结。
2.3 现有答案常见的三类缺陷
用多了会发现,这类资源的问题集中在三个地方。
第一类是符号体系不一致。教材里用 $\lambda$ 表示特征值,答案里可能用 $t$;教材里过渡矩阵写成 $P$,答案里写成 $C$;更常见的是矩阵转置的记号,有的用 $A^T$,有的用 $A'$。这不是大问题,但会让你在对照时反复确认“这个 C 到底是不是那个 P”,平白消耗注意力。解决办法是在对照表里加一列“符号映射”,把差异提前记下来。
第二类是跳步严重。典型表现是“经计算可得”后面直接跟一个三阶矩阵,中间的特征值求解、特征向量正交化、单位化全被吞掉。遇到这种,我的处理方式是不硬看,直接自己算一遍,算完再和答案对。跳步的题往往不难,只是繁琐,自己算反而更快。
第三类是错解。这个不用避讳,流传的答案有错是常态,尤其是证明题里“充分性”和“必要性”写反、矩阵分解里正交矩阵没单位化、广义逆里把 $A^+$ 和 $A^-$ 混为一谈。所以我在第4节专门讲怎么用代码把答案验一遍。数学题的答案不像代码可以跑测试,但矩阵论的计算题完全可以,这一步能挡掉大部分低级错误。
3. 核心章节的解题要点与验算方法
3.1 线性空间与线性变换:基、维数、过渡矩阵
这一块的题目类型高度集中,无非是判断子空间、求基与维数、求过渡矩阵、求线性变换在指定基下的矩阵。看起来简单,但初学者最容易在“过渡矩阵的方向”上翻车。
举个典型场景:给两组基 $\alpha_1,\alpha_2,\alpha_3$ 和 $\beta_1,\beta_2,\beta_3$,求从 $\alpha$ 到 $\beta$ 的过渡矩阵 $P$,使得 $(\beta_1,\beta_2,\beta_3)=(\alpha_1,\alpha_2,\alpha_3)P$。答案里通常直接给出一个矩阵,但你要清楚这个 $P$ 是把 $\beta$ 用 $\alpha$ 表示出来的系数矩阵。方向搞反,后面求坐标变换就全错。
我的验算习惯是:求出 $P$ 之后,随手取一个向量,用两组基分别表示,看坐标变换公式 $x_\alpha = P x_\beta$ 是否成立。这一步只要三十秒,但能挡住方向性错误。
求子空间的交与和也是高频题。答案里常用维数公式 $\dim(U+V)=\dim U+\dim V-\dim(U\cap V)$,但公式只给维数,不给具体的基。如果题目要求写出交空间的基,就得老老实实解方程组。这类题我的做法是先把两个子空间都写成齐次线性方程组的解空间,联立求解,解出来的基础解系就是交空间的基。答案如果只给了维数,那这道题等于没做完。
还有一个常被忽略的点:线性变换的核与像。求核就是解 $Ax=0$,求像就是求 $A$ 的列空间。这两件事在线代里就学过,但矩阵论里会要求你用“不变子空间”的语言重述一遍。看答案时注意它是怎么把“解方程组”翻译成“求核空间”的,这个翻译过程就是这门课想训练的东西。
3.2 特征值与Jordan标准形:不变因子与初等因子
Jordan标准形是整门课的分水岭,也是答案资源里最容易看不明白的地方。原因在于它的计算链条很长:特征矩阵 $\lambda I-A$ → 行列式因子 → 不变因子 → 初等因子 → Jordan块。任何一环断了,后面就接不上。
我的建议是把这条链拆成两步走。第一步只算不变因子,方法是把 $\lambda I-A$ 化成 Smith 标准形,对角线上那些多项式就是不变因子。这一步纯机械,做五六道题就能形成肌肉记忆。第二步才从不变因子拆初等因子,规则很简单:把每个不变因子分解成互不相同的线性因子的幂,每个幂对应一个 Jordan 块,幂次就是块的阶数。
这里有个坑要提前说:不变因子的顺序是有讲究的,必须满足 $d_1(\lambda) \mid d_2(\lambda) \mid \cdots \mid d_r(\lambda)$,也就是前一个整除后一个。有些答案直接给一组多项式,不检查整除关系,你照着用就会得到错误的 Jordan 形。我验算时一定会回头检查这个整除链,只要有一处不整除,说明中间某步算错了。
另一个高频错误是几何重数和代数重数搞混。代数重数是特征值在特征多项式里的重数,几何重数是 $\lambda I-A$ 的零空间维数,也就是 $n-\text{rank}(\lambda I-A)$。Jordan 块的个数等于几何重数,块的最大阶数等于该特征值对应初等因子的最高次幂。把这两个数算清楚,Jordan 形就唯一确定了。
用代码验算 Jordan 形非常方便,sympy 直接有现成函数。下面这段我常用来核对:
import sympy as sp lam = sp.symbols('lambda') A = sp.Matrix([[3, 1, -1], [0, 1, 1], [0, 0, 2]]) # 特征多项式 char_poly = A.charpoly(lam).as_expr() print("特征多项式:", sp.factor(char_poly)) # 最小多项式 print("最小多项式:", sp.factor(A.minimal_polynomial(lam).as_expr())) # Jordan 标准形与变换矩阵 J, P = A.jordan_form() print("Jordan 形:\n", J) print("变换矩阵 P:\n", P) print("验证 P^-1 A P == J:", sp.simplify(P.inv() * A * P) == J)这段代码最后一行是关键。很多人只看 $J$ 长什么样,不看 $P^{-1}AP$ 是否真的等于 $J$。手工算的时候,$P$ 的列向量顺序、每个块对应的广义特征向量,只要错一个,结果就不对。代码验证能一次性把这个问题暴露出来。
还要提醒一句:sympy 的jordan_form对含符号参数的矩阵可能算得很慢甚至算不出来,遇到带参数的题还是得手算,代码只用来验证数值情形。
3.3 矩阵分解:LU、QR、SVD、满秩分解
矩阵分解这一块的答案最好用,因为方法高度标准化,答案基本不会跳步。但要注意几种分解的适用条件,抄答案时别把条件漏了。
| 分解类型 | 存在条件 | 唯一性 | 常见坑 |
|---|---|---|---|
| LU 分解 | 各阶顺序主子式非零 | 下三角单位对角时唯一 | 需要选主元时答案可能略过置换矩阵 |
| QR 分解 | 列满秩 | 对角元取正时唯一 | 忘记对列向量单位化 |
| 满秩分解 | 任意非零矩阵 | 不唯一 | 答案给的 $F,G$ 和你算的不同但都对 |
| 奇异值分解 | 任意矩阵 | 奇异值唯一,向量不唯一 | 特征向量符号可取反 |
| 谱分解 | 正规矩阵 | 投影矩阵唯一 | 需先验证正规性 |
这张表里最值得说的是满秩分解和 SVD 的“不唯一”。很多人对完答案发现自己的 $F$、$G$ 和答案不一样,就以为做错了。其实只要满足 $A=FG$、$F$ 列满秩、$G$ 行满秩,就是对的。SVD 同理,$U$ 和 $V$ 的对应列同时变号,乘积不变。判断对错的方式不是比矩阵,而是验算乘积。
满秩分解的标准做法是对 $A$ 做初等行变换化成行最简形,取主元所在的列构成 $F$,行最简形的非零行构成 $G$。这个流程答案里一般会写,但有时会跳过“化行最简形”的中间过程,直接给结果。这时自己补一遍更稳妥。
QR 分解要注意两种形式:完整版和精简版(经济型)。完整版 $Q$ 是方阵,精简版 $Q$ 和 $A$ 同形。答案用哪种取决于教材约定,对答案前先确认。另外 Gram-Schmidt 正交化过程中,如果某一步得到的向量范数为零,说明列向量线性相关,这时候 QR 分解的精简版仍然存在,但完整版需要补正交基,答案里经常在这里含糊过去。
数值验算这几种分解用 numpy 就够:
import numpy as np A = np.array([[1., 2., 3.], [4., 5., 6.], [7., 8., 10.]]) # LU 分解(scipy 提供) from scipy.linalg import lu P, L, U = lu(A) print("PA == LU:", np.allclose(P @ A, L @ U)) # QR 分解 Q, R = np.linalg.qr(A) print("A == QR:", np.allclose(A, Q @ R)) print("Q 正交:", np.allclose(Q.T @ Q, np.eye(Q.shape[1]))) # SVD U_, s, Vt = np.linalg.svd(A) S = np.diag(s) print("A == USV^T:", np.allclose(A, U_ @ S @ Vt))这几行的思路是:不比对分解出来的矩阵,只验证乘积关系。这个原则适用于所有分解类题目。手工算完,把结果敲进去跑一遍,True就过,False就回头查。我算 SVD 时尤其依赖这一步,因为手工求 $AA^T$ 的特征向量再单位化,中间任何一步的算术错误都会让最终结果面目全非,而验算只需要一行。
3.4 矩阵分析与矩阵函数:范数、级数、矩阵微分
这一块是答案最容易出错的地方,也是我建议逐行推的地方。
矩阵范数题目通常分两类:算具体范数、证明范数不等式。算具体范数不难,1-范数是列和最大,$\infty$-范数是行和最大,2-范数是最大奇异值,F-范数是元素平方和开根。答案给结果,你自己算一遍对上就行。麻烦的是证明范数等价性或者算子范数的具体表达式,这类题答案往往写得跳跃。
矩阵级数主要考 $\sum A^k$ 的收敛性。核心结论是:级数收敛当且仅当谱半径 $\rho(A)<1$,且此时和为 $(I-A)^{-1}$。答案里有时会漏掉“谱半径小于 1”这个条件,直接写求和公式,这是不严谨的。看答案时注意这个条件有没有出现,没出现就自己补上。
矩阵函数是重灾区。$e^{At}$、$\sin A$、$\sqrt{A}$ 的定义都依赖级数,计算上通常走两条路:一是 Jordan 标准形,$f(A)=P f(J) P^{-1}$,其中 $f(J)$ 按块计算,每块用泰勒展开;二是待定系数法,先用最小多项式降次,再解线性方程组。
两条路各有适用场景。最小多项式次数低的时候用待定系数法更快;最小多项式次数高、但 Jordan 块结构清晰的时候用 Jordan 形更直接。答案通常只用一种方法,如果你用另一种算出同样的结果,那说明答案可信;如果对不上,先检查自己是不是在某个块上把 $f^{(k)}(\lambda)/k!$ 的系数搞错了。
Jordan 块上算 $f(J)$ 的公式是:
$$f(J_k(\lambda)) = \begin{pmatrix} f(\lambda) & f'(\lambda) & \frac{f''(\lambda)}{2!} & \cdots \ 0 & f(\lambda) & f'(\lambda) & \cdots \ 0 & 0 & f(\lambda) & \cdots \ \vdots & & & \ddots \end{pmatrix}$$
这个上三角结构里,对角线全是 $f(\lambda)$,往右上依次是各阶导数除以阶乘。我见过最多的错误是把导数阶乘的位置搞反,或者忘了除以 $k!$。
矩阵微分部分,重点是 $\frac{\partial \operatorname{tr}(AX)}{\partial X}=A^T$ 这类公式,以及 $d(X^{-1})=-X^{-1}dX,X^{-1}$。后一个公式里 $dX$ 夹在两个 $X^{-1}$ 中间,顺序不能换。答案里如果写成 $-X^{-2}dX$,那是错的,因为矩阵乘法不交换。看这一节时,凡是涉及矩阵乘积求导的地方,我都逐个检查顺序。
验算矩阵函数最直接的办法是数值逼近。用 scipy 的expm算 $e^A$,和你手工用 Jordan 形算出来的结果比:
import numpy as np from scipy.linalg import expm A = np.array([[1., 1.], [0., 2.]]) # 数值解 E_num = expm(A) # 手工解:先做 Jordan 分解,再按块套公式 # A 的特征值为 1 和 2,可对角化 lam1, lam2 = 1.0, 2.0 P = np.array([[1., 1.], [0., 1.]]) D = np.diag([np.exp(lam1), np.exp(lam2)]) E_hand = P @ D @ np.linalg.inv(P) print("数值解:\n", E_num) print("手工解:\n", E_hand) print("误差:", np.max(np.abs(E_num - E_hand)))误差在 $10^{-10}$ 量级以内就说明手工推导没问题。这个方法对 $\sin A$、$\cos A$、$A^{1/2}$ 同样适用,只需把expm换成对应的矩阵函数,或者自己用级数展开近似。
注意:数值验算只能验证“数值上对不对”,不能验证“推导过程对不对”。如果一道题要求证明 $e^{A+B}=e^Ae^B$ 在 $A,B$ 可交换时成立,代码帮不上忙。这类题还是得逐行看答案的逻辑链,重点确认“可交换”这个条件在哪一步用上了,用不上就是证明有问题。
3.5 广义逆与矩阵方程
广义逆这块的题目分两类:计算 ${1}$-逆、${1,2}$-逆、Moore-Penrose 逆,以及解矩阵方程 $AXB=C$、$AX=B$。
计算类题目,${1}$-逆不唯一,答案给的只是一个特例,所以你算出来的和答案不一样很正常,判断标准是 $AGA=G$ 是否成立。${1,2}$-逆要求同时满足 $AGA=A$ 和 $GAG=G$。Moore-Penrose 逆 $A^+$ 唯一,四个条件全满足,计算上走 SVD 最稳:$A=U\Sigma V^T$,则 $A^+=V\Sigma^+U^T$,其中 $\Sigma^+$ 是把非零奇异值取倒数再转置。
用 SVD 算 $A^+$ 有个好处,无论 $A$ 是满秩、亏秩还是长方形,公式都成立,不用分情况讨论。手算时如果题目规模小,也可以直接用公式 $A^+=(A^TA)^{-1}A^T$(列满秩时)或 $A^T(AA^T)^{-1}$(行满秩时)。答案里经常只给其中一种情形,遇到亏秩矩阵就卡住了,这时候直接上 SVD。
解矩阵方程 $AXB=C$ 的标准做法是向量化:把 $X$ 按列拉直成 $\text{vec}(X)$,方程变成 $(B^T\otimes A)\text{vec}(X)=\text{vec}(C)$,然后判断系数矩阵是否可逆,可逆则唯一解,不可逆则用广义逆表示通解。这个转化过程答案里一般会写,但 Kronecker 积的性质容易记混,特别是 $(B^T\otimes A)^{-1}=B^{-T}\otimes A^{-1}$ 这个式子,只在 $A,B$ 都可逆时成立。
验算 $A^+$ 最省事的办法是用 numpy 的pinv,然后检查四个 Penrose 条件:
import numpy as np A = np.array([[1., 2., 3.], [4., 5., 6.]]) Ap = np.linalg.pinv(A) Ap_hand = np.array([[-17/18, 4/18], [ -2/18, 1/18], [ 13/18, -2/18]]) # 手工计算结果 print("A A+ A == A :", np.allclose(A @ Ap_hand @ A, A)) print("A+ A A+ == A+:", np.allclose(Ap_hand @ A @ Ap_hand, Ap_hand)) print("(A A+)^T == A A+:", np.allclose((A @ Ap_hand).T, A @ Ap_hand)) print("(A+ A)^T == A+ A:", np.allclose((Ap_hand @ A).T, Ap_hand @ A))四个条件全True,手工结果才可信。只有前两个成立的是 ${1,2}$-逆,不是 Moore-Penrose 逆,这个区别在答案里经常被模糊掉。
4. 用代码交叉验证答案的实操流程
4.1 环境与工具准备
验算环境不需要多复杂,Python 加上 numpy、scipy、sympy 三个包就够。numpy 负责数值计算,scipy 提供lu、expm、sqrtm、logm这些矩阵函数,sympy 负责符号推导,算特征多项式、最小多项式、Jordan 形、Smith 标准形都靠它。
装的时候建议用虚拟环境,避免和系统里的其他包冲突:
python -m venv matverify source matverify/bin/activate # Windows 用 matverify\Scripts\activate pip install numpy scipy sympy三个包的版本不用太新,numpy 1.24 以上、scipy 1.10 以上、sympy 1.11 以上就能覆盖矩阵论习题里的绝大多数需求。装完跑一句import numpy, scipy, sympy确认没报错。
提示:sympy 的符号计算在矩阵规模超过 5×5 时会明显变慢,尤其是求 Jordan 形和 Smith 标准形。遇到大规模题目,先把矩阵转成数值型用 numpy 验算结果,符号推导只在关键步骤上做。我一般只对 3×3 到 4×4 的矩阵做完整符号验算,再大就纯数值验证。
工具准备好之后,建一个目录放验算脚本,按章节分文件,比如ch3_jordan.py、ch5_decomp.py、ch6_matrixfun.py。每个文件只放该章几道典型题的验算,这样回头查的时候不用翻大文件。这个习惯看着琐碎,但一个学期下来能省下大量重复劳动。
4.2 符号计算验算 Jordan 形与最小多项式
Jordan 形的手工计算最容易出错的环节是初等因子的拆分,符号验算正好能盯住这一步。我的做法是:手工算出不变因子和初等因子,然后用 sympy 直接算jordan_form,看两边得到的 $J$ 结构是否一致。如果一致,再检查 $P^{-1}AP=J$ 是否成立;如果不一致,先看 sympy 的结果里每个块的阶数,和自己的初等因子对一下,通常问题出在某个因子的幂次上。
最小多项式的验算更简单,sympy 的minimal_polynomial直接给结果。但要注意它返回的是PurePoly对象,需要.as_expr()转成普通表达式才能和手工结果比对。最小多项式的重要用处是判断矩阵能否对角化:最小多项式无重根等价于可对角化。这个判据比“几何重数等于代数重数”更快,考试时也更好写。
还有一个技巧:算完 Jordan 形,可以顺手验证 Cayley-Hamilton 定理。把特征多项式代入矩阵,看结果是不是零矩阵。这一步能同时检查特征多项式和矩阵乘法有没有算错:
import sympy as sp A = sp.Matrix([[2, 0, 0], [1, 2, 0], [0, 1, 2]]) lam = sp.symbols('lambda') p = A.charpoly(lam).as_expr() print("特征多项式:", sp.factor(p)) # Cayley-Hamilton 验证 I = sp.eye(3) res = A**3 - 6*A**2 + 12*A - 8*I # 代入 p(lambda) 的系数 print("p(A) 是否为零矩阵:", res == sp.zeros(3, 3))这类验证的好处是结果只有对错两种,没有解释空间。手工算完一道题,跑一遍,True就放心往下走,False就回头查。比自己反复检查省事得多。
4.3 数值计算验证分解类题目
分解类题目的验证原则前面说过:不比矩阵,只比乘积。具体到每种分解,需要额外检查的性质不一样。
LU 分解要检查 $L$ 是不是单位下三角、$U$ 是不是上三角、$PA=LU$ 里的置换矩阵 $P$ 有没有漏。QR 分解要检查 $Q^TQ=I$、$R$ 是不是上三角。SVD 要检查 $U^TU=I$、$V^TV=I$、$\Sigma$ 的对角元非负且按降序排列。满秩分解要检查 $F$ 列满秩、$G$ 行满秩。
这里有个细节容易忽略:numpy 的linalg.qr默认返回精简版 QR,如果你要完整版,需要额外补正交基。教材上的 QR 分解大多指精简版,但也有的教材用完整版,对答案前先确认版本。
矩阵秩的验算也值得单独提一句。很多分解题的第一步是判断矩阵的秩,秩算错了后面全错。numpy 的matrix_rank用的是 SVD 方法,对数值误差有容忍度;sympy 的A.rank()是精确计算,对符号矩阵更可靠。手工算秩时如果遇到接近零的奇异值,最好两边都跑一下,看结果是否一致。
import numpy as np import sympy as sp A = np.array([[1., 2., 3.], [2., 4., 6.], [1., 1., 1.]]) print("numpy 秩:", np.linalg.matrix_rank(A)) print("sympy 秩:", sp.Matrix(A.tolist()).rank()) # 满秩分解手工结果验证 F = np.array([[1., 3.], [2., 6.], [1., 1.]]) G = np.array([[1., 1., 0.], [0., 1., 1.]]) print("A == FG:", np.allclose(A, F @ G)) print("F 列满秩:", np.linalg.matrix_rank(F) == F.shape[1]) print("G 行满秩:", np.linalg.matrix_rank(G) == G.shape[0])两个秩函数结果不一致的情况确实存在,通常是因为矩阵里有接近零但不为零的元素。这种时候以 sympy 的精确结果为准,numpy 的结果只作参考。
4.4 批量化核对答案的脚本骨架
题目做多了,逐题写验算脚本会变成负担。我的做法是把每道题的矩阵和预期结果整理成结构化的数据,写一个通用脚本批量跑。数据可以存成 CSV,三列:题号、输入矩阵、预期输出。脚本读进来,逐行解析,跑对应类型的验证,输出一份对错清单。
这个骨架不需要多复杂,核心就三步:解析数据、按题型分派验证函数、汇总结果。下面是个简化版:
import numpy as np import json def check_jordan(A_str, J_str): A = np.array(json.loads(A_str), dtype=float) J = np.array(json.loads(J_str), dtype=float) # 简化验证:比较特征值和 Jordan 结构不现实,这里只比可对角化性 ev_A = np.sort(np.linalg.eigvals(A)) ev_J = np.sort(np.diag(J)) return np.allclose(ev_A, ev_J) def check_decomp(A_str, F_str, G_str): A = np.array(json.loads(A_str), dtype=float) F = np.array(json.loads(F_str), dtype=float) G = np.array(json.loads(G_str), dtype=float) return np.allclose(A, F @ G) cases = [ {"id": "3-12", "type": "decomp", "data": ["[[1,2,3],[2,4,6],[1,1,1]]", "[[1,3],[2,6],[1,1]]", "[[1,1,0],[0,1,1]]"]}, {"id": "3-15", "type": "jordan", "data": ["[[2,0,0],[1,2,0],[0,1,2]]", "[[2,0,0],[0,2,0],[0,0,2]]"]}, ] for c in cases: if c["type"] == "decomp": ok = check_decomp(*c["data"]) elif c["type"] == "jordan": ok = check_jordan(*c["data"]) else: ok = None print(f'{c["id"]}: {"通过" if ok else "未通过"}')这个脚本的价值不在技术含量,在于把“验算”这件事从临时起意变成固定流程。做完一章题,把数据填进去跑一遍,几分钟就能摸清哪几道题的结果有问题。问题题目标记出来,第二天重新手算一遍,比反复看答案有效得多。
注意:脚本验证的是数值,不是逻辑。证明题的推理链没法用这种方式检查。我的做法是证明题单独建一个文档,把自己的证明和答案的证明并排放,逐条比对关键步骤,标注“这一步我没想到”“这一步答案没写清”“这一步我有疑问”。攒够一定数量,集中去找老师或者同学讨论,比一题一问效率高。
5. 使用答案资源的正确姿势与避坑清单
5.1 三轮使用法
我把答案的使用分成三轮,每轮目的不同。
第一轮在自己做完题之后,只看结果的最后一个数或最后一个矩阵,对上了就跳过,对不上才回头看过程。这一轮的目的是筛选,把需要深究的题目挑出来,不需要的快速放过。很多人失败在把这一轮做成了精读,每道题都从头看到尾,时间全耗在已经会的题上。
第二轮针对第一轮筛出来的错题,逐行比对中间步骤。重点看三个地方:切入角度、关键定理、收尾方式。切入角度是“第一句话写了什么”,关键定理是“哪一步引用了哪个结论”,收尾方式是“最后怎么把结论扣回题目要求”。这三样看懂了,这道题才算真的过了。
第三轮在考前,只看错题和标记为“仍需重做”的题。这时候不写完整过程,只看题目,在脑子里过一遍思路,卡住了再翻答案。这一轮的目的是保持手感,不是重新学。
三轮下来,同一道题最多看三遍,但每一遍的注意力都落在不同层面,比反复通读有效得多。我自己的经验是,第一轮筛完通常能划掉六成题目,剩下的四成里第二轮能解决三成,真正留到第三轮的不到一成。
5.2 常见错误与排查速查表
下面这张表是我踩过坑之后整理的,做题卡住时可以按症状查:
| 症状 | 可能原因 | 排查动作 |
|---|---|---|
| 求出的过渡矩阵代入后坐标变换不成立 | 过渡矩阵方向反了 | 用具体向量验证 $x_\alpha=P x_\beta$ |
| Jordan 形和答案不一致 | 初等因子幂次拆错 | 检查不变因子是否满足整除链 |
| 可对角化判断出错 | 混淆几何重数与代数重数 | 算 $n-\text{rank}(\lambda I-A)$ |
| 满秩分解结果和答案对不上 | 分解不唯一,正常现象 | 验算 $FG=A$ 和满秩条件 |
| SVD 的 $U$、$V$ 和答案符号相反 | 特征向量可取反,正常现象 | 验算 $USV^T=A$ |
| 矩阵函数结果差一个系数 | Jordan 块公式漏了 $k!$ | 检查 $f^{(k)}(\lambda)/k!$ |
| 矩阵微分求导顺序不对 | 矩阵乘法不交换 | 逐个检查 $dX$ 的位置 |
| 广义逆验算不满足四个条件 | 算的是 ${1,2}$-逆而非 $A^+$ | 补验后两个 Penrose 条件 |
| 矩阵方程通解形式对不上 | 广义逆选取不同,正常现象 | 把通解代回原方程验证 |
这张表里“正常现象”那几行值得单独说。满秩分解、SVD、广义逆这三类题,答案不唯一是数学性质决定的,不是错误。判断标准永远是验算原式,而不是比矩阵。我见过太多人在这上面浪费时间,反复改自己的结果去凑答案,最后把本来对的东西改错了。
5.3 答案与教材符号不一致的处理
符号不一致是常态,处理原则是:以教材为准,建立映射,写在纸上放在手边。
具体做法是拿一张 A4 纸,左边写教材符号,右边写答案符号,中间画箭头。常见的不一致有这些:特征值用 $\lambda$ 还是 $t$;过渡矩阵用 $P$ 还是 $C$;矩阵的共轭转置用 $A^H$ 还是 $A^*$;内积用 $(\alpha,\beta)$ 还是 $\langle\alpha,\beta\rangle$;Jordan 块的记号用 $J_k(\lambda)$ 还是 $J(\lambda,k)$。
这张纸的价值在于减少认知负荷。看答案时不用每次都在心里翻译一遍符号,直接扫一眼纸就知道对应关系。尤其是做综合题的时候,符号切换频繁,有这张纸和没有,效率差别很明显。
还有一类不一致更隐蔽:定理的名字。同一个结论,有的教材叫“哈密顿-凯莱定理”,有的叫“凯莱-哈密顿定理”;有的把“Schur 定理”限定在酉相似,有的泛指一般相似。遇到答案引用一个你没听过的定理名,先别慌,去教材的索引里查一下,多半是同一个东西的另一种叫法。
提示:符号映射纸建议用铅笔写,随时补充。做到后面章节时,前面记的映射可能不够用,随时加。考试前把这张纸上的内容过一遍,比自己重新翻教材快得多。
6. 从习题答案延伸到课程之外的迁移价值
矩阵论这门课有个特点:学的时候觉得抽象得没边,用的时候发现到处都是。课后答案如果只用来应付考试,多少有点浪费。我在带人补课和自己复盘的过程中,慢慢发现几块内容的迁移价值特别高。
矩阵分解那块,SVD 在主成分分析、推荐系统、图像压缩里都是核心工具。做数据相关的工作,SVD 的几何意义(把任意线性变换拆成旋转、拉伸、旋转)比公式本身更重要。理解了这一点,再看降维算法就不会觉得是黑箱。QR 分解在最小二乘里用得极多,解超定方程组时,正规方程法和 QR 法的数值稳定性差别很大,后者明显更稳,这个结论在教材的习题里往往有一道题专门让你比较。
矩阵函数那块,$e^{At}$ 是线性常微分方程组的解,也是控制理论里状态转移矩阵的核心。做信号处理或者控制系统的人,绕不开这个。教材里求 $e^{At}$ 的习题,本质上就是在练这门手艺。把 Jordan 形法和待定系数法都练熟,遇到不同结构的矩阵能快速选方法,这个能力在实际工作里直接能用。
广义逆那块,最小二乘解、病态问题的正则化、欠定系统的通解,背后都是 Moore-Penrose 逆。教材里的习题规模小,但方法是一样的。学会用 SVD 算 $A^+$ 之后,再去看机器学习里的伪逆实现,会发现代码就那几行,没什么神秘。
矩阵微分那块,在优化理论里用得最多。梯度下降、牛顿法、矩阵分解的优化目标求导,全靠这套公式。教材里的习题大多是纯公式推导,看着枯燥,但每一条都对应一个实际场景。比如 $\frac{\partial \operatorname{tr}(AXB)}{\partial X}=A^TB^T$ 这条,在推导线性回归的正规方程时就会用到。
我的建议是,做完一章习题之后,花十分钟想一想这一章的内容在哪个实际场景里出现过。想不出来也没关系,至少建立了“这东西有用”的印象,以后遇到相关问题时,会想起来回头翻。这个动作花的时间不多,但能让整门课从“应付考试”变成“攒工具”。
后续如果想把这块内容吃得更透,可以往两个方向扩展。一个是数值线性代数,看看实际计算中怎么处理浮点误差、怎么设计稳定的算法,这方面的内容和教材里的精确计算形成互补。另一个是矩阵分析在具体领域的应用,挑一个自己感兴趣的方向(信号、控制、优化、统计),把相关的矩阵工具挑出来重点练。两条路都不需要额外学太多新东西,主要是把已有的工具用起来。
最后分享一个我自己的习惯:每学完一章,挑一道最难的习题,不看答案,从头到尾独立写一遍完整过程,写完再对照。这道题的选择标准不是分值最高,而是“看一眼就觉得头大”的那道。能把这种题独立写出来,说明这一章是真的过了。这个习惯坚持下来,比刷十套题管用。踩过的坑也不少,最典型的一次是花了一晚上死磕一道 Jordan 形的题,最后发现是特征多项式算错了一个符号,从那以后我每算完特征多项式都会代一个特征值回去验一下。这种笨办法,往往最省时间。