news 2026/11/2 20:37:06

A^T A 正定吗?列满秩条件与数值判定

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
A^T A 正定吗?列满秩条件与数值判定

矩阵 A 的转置乘 A 是否一定正定?这大概是线性代数课上被问得最多、也被答错得最多的问题之一。我在实际项目里见过不止一次有人很有把握地说,A^T A 当然是正定的,因为 x^T A^T A x 就等于 Ax 的范数平方,肯定大于 0,然后转头在最小二乘程序里收到一条LinAlgError: Matrix is not positive definite。问题就出在那个“肯定”上:||Ax||^2 ≥ 0这个不等式只能给出半正定,要升级成正定,必须再补一个条件,而且这个条件不是关于 G = A^T A 自身的,是关于 A 的。矩阵 A 的转置乘 A 是正定矩阵的充分必要条件,一句话版本就是:A 的列向量线性无关,即 A 列满秩(rank(A) = n,其中 A 是 m×n 的实矩阵)。这句话往下拆,可以牵出零空间、秩-零化度定理、奇异值、条件数平方、Cholesky 分解,以及一堆看起来无懈可击其实有致命漏洞的伪证明。下面我按自己的理解顺序,从为什么、怎么证、怎么算、怎么判、怎么用这条线把它捋一遍,数学方向的学生、写数值代码的工程师、需要判断协方差矩阵性质的数据分析者,应该都能从中拿到自己那一份。

1. 先把半正定这件事钉死

1.1 无条件成立的那个版本

设 A 是 m×n 实矩阵,定义 G = A^T A。G 是 n×n 的,并且 G^T = (A^T A)^T = A^T A = G,所以 G 一定是实对称矩阵。这一步跟 A 长什么样完全没关系,A 是零矩阵也是对称的,零矩阵当然对称。

接下来对任意 x ∈ R^n:

x^T G x = x^T A^T A x = (Ax)^T (Ax) = ||Ax||^2 ≥ 0

范数平方非负,所以 G 是半正定的。这三行没有任何前提条件,不需要 A 满秩,不需要 A 是方阵,也不需要 m 和 n 的大小关系。顺手还能拿到两个副产品:第一,G 的对角元 G_ii 等于 A 第 i 列向量的范数平方,所以只要 A 有一列是全零,G 就有一个对角元为 0,而正定矩阵的对角元必须全为正,直接判死;第二,tr(G) 等于 A 所有元素平方和,也就是 A 的 Frobenius 范数平方,这个恒等式在调试时很好用,如果它算出来是 0,说明 A 就是零矩阵,根本不用往下判。

复数域里的版本完全平行:把转置换成共轭转置,G = A^H A 一定是 Hermitian 半正定的,x^H G x = ||Ax||² 依旧成立。后面为了叙述方便,全部按实矩阵写,结论一字不改就能搬过去。

1.2 从“非负”到“严格正”差的那一步

半正定和正定的区别只有一个字:二次型取零的那些点。定义上,G 正定要求对所有非零 x 都有 x^T G x > 0;半正定只要求 ≥ 0,允许存在某些非零 x 使二次型恰好等于 0。

代进我们的表达式,x^T G x = 0 等价于 ||Ax||² = 0,也就等价于 Ax = 0。所以:

  • 如果存在非零 x 满足 Ax = 0,也就是 A 的零空间 N(A) 里除了零向量还有别的东西,那么在这个 x 上二次型取到 0,G 只是半正定,不是正定;
  • 如果 Ax = 0 只有零解,那么任何 x ≠ 0 都给出 Ax ≠ 0,从而 ||Ax||² > 0,G 就是正定的。

问题到这里已经被完整翻译成了“齐次方程 Ax = 0 有没有非零解”,而这正是列向量线性无关性的定义。整个证明其实已经结束了,剩下的全是换个说法。

有一条恒等式值得单独记下来:N(A^T A) = N(A)。包含关系 N(A) ⊆ N(A^T A) 是显然的(Ax = 0 当然推出 A^T Ax = 0);反过来若 x ∈ N(A^T A),则 x^T A^T A x = 0,即 ||Ax||² = 0,于是 Ax = 0。两边一夹,零空间完全相同。这条恒等式是后面所有秩等式的基础。

1.3 为什么这里最容易翻车

翻车点通常有两个。第一个是把“非负”当“正”,这是纯粹的逻辑跳跃,属于纸面上的粗心。第二个更隐蔽:把退化情况当成思维里的特例直接跳过,觉得“实际数据不会这么巧”。

可我的经验恰恰相反,退化在真实数据里出现的概率远比想象中高。做回归时,如果同时放了“总价”和“总价的万元表示”两个特征,A 立刻列不满秩,G 立刻奇异,正规方程直接崩;做时间序列时,如果两个传感器的读数只差一个固定比例,同一件事。这不是什么人为构造的病态例子,这就是数据预处理里最常见的失误。所以半正定和正定这一字之差,在工程上就是“程序跑得通”和“程序抛异常”的差别。

把这句话刻在脑子里:A^T A 的正定性,从来不是 A^T A 自己的性质,而是 A 的列向量组的性质。判断对象搞错了,后面全是白费。

2. 充分必要条件:把“A 列满秩”翻译成六种说法

2.1 定理的完整陈述

设 A 是 m×n 实矩阵。下列命题两两等价:

  1. G = A^T A 是正定矩阵;
  2. rank(A) = n;
  3. A 的 n 个列向量线性无关;
  4. 齐次方程 Ax = 0 只有零解,即 N(A) = {0};
  5. A^T A 可逆(非奇异);
  6. A 的所有奇异值严格大于 0;
  7. A 作为线性映射 R^n → R^m 是单射。

此外,若 A 还是方阵(m = n),以上全部等价于 det(A) ≠ 0,也就是 A 本身可逆。

这张清单的实用价值在于,做实际问题时你几乎不会真的去构造 G 再算它的特征值,而是直接看 A 的秩、看列向量是否相关、看最小奇异值离 0 有多远。从计算成本和数值稳定性两个角度讲,后者永远是更优的选择,原因后面第 4 节会细说。

顺带说一句,条件 7 的几何含义值得体会:列满秩意味着 A 把 R^n 单射进 R^m 的一个 n 维子空间里,不折叠、不塌陷。A^T A 的正定性,本质上是在说“这个映射在每个方向上都有真实的伸缩”,没有任何方向被压成 0。

2.2 两条证明路线,我推荐第一条

路线一:零空间路线。

正定定义要求对任意 x ≠ 0,x^T G x > 0。

x^T G x = ||Ax||²,所以 x^T G x = 0 ⟺ Ax = 0 ⟺ x ∈ N(A)。

于是 G 正定 ⟺ N(A) = {0}。再用秩-零化度定理 rank(A) + dim N(A) = n(n 是列数,也就是未知量个数),立刻得到 rank(A) = n。

这条路线三行写完,不依赖任何高级工具,我推荐给所有刚接触这个问题的人。它还有个好处:把“正定性”这个二次型语言的概念,翻译成了“线性方程组解的唯一性”这个更朴素的语言,直觉上更容易接受。

路线二:特征值路线。

G 实对称,所以存在正交矩阵 Q 使 Q^T G Q = diag(λ_1, ..., λ_n),所有 λ_i 都是实数。半正定意味着所有 λ_i ≥ 0,正定则要求所有 λ_i > 0。

而 λ_i 是 A^T A 的特征值,√λ_i 正好是 A 的奇异值 σ_i。于是“G 正定” ⟺ “A 的奇异值全为正” ⟺ “A 列满秩”。这条路线顺便送来一个定量关系:cond₂(A^T A) = cond₂(A)²,它是第 4 节数值陷阱那部分的主角。

路线三:顺序主子式,不推荐。

Sylvester 判据说,对称矩阵正定 ⟺ 所有顺序主子式(左上角 k×k 子式,k 从 1 到 n)都大于 0。用它来证 A^T A 正定是绕远路,而且很容易踩坑。坑在于:顺序主子式判据只对对称或 Hermitian 矩阵成立,随手拿一个非对称矩阵套用会得出荒谬结论。做证明时我见过有人对一个普通方阵算顺序主子式全正就宣称正定,那是根本性错误。

不过这个判据在 A^T A 上有个漂亮的解释:G 的第 k 个顺序主子式,恰好是 A 的前 k 列构成的子矩阵 A_k 的 Gram 行列式 det(A_k^T A_k),它非零意味着前 k 列线性无关。所以顺序主子式全正,其实是在逐列地检查“每一列都不能被前面的列线性表示”,跟列满秩是同一件事的不同切法。

2.3 形状决定命运:三种局面速查

关于 A 的形状,有个非常实用的对照:

A 的形状A^T A 的阶数可能正定吗原因
m > n(高瘦)n×n可能列满秩时正定,这是最常见的“数据够用”情形
m = n(方阵)n×n可能只要 A 可逆就正定
m < n(矮胖)n×n不可能rank(A) ≤ m < n,必然奇异,必有零特征值

第三种情况最容易被忽略。一个 2×3 的矩阵 A,秩最多是 2,而 A^T A 是 3×3 的,秩最多 2,也就意味着至少有一个零特征值。所以矮胖矩阵的 A^T A 永远只是半正定,永远不正定,无论你怎么挑元素、怎么调数值。这个结论对做欠定方程、压缩感知、或者不小心把数据表行列转置了的人特别有用——你不用试,一试就是错的。

顺着这个思路还能得到一个小推论:如果 A 的列数大于行数,你根本不需要计算,直接就能下结论“不正定”。我在 review 代码时见过有人对 30×100 的矩阵算了半天特征值,其实一句话就能否掉。

3. 三个手算例子,把直觉焊死在脑子里

3.1 正例:高瘦且列满秩

取 A = [[1,0], [0,1], [1,1]],3×2 的矩阵。

先算 G = A^T A:

第一行第一列 = 1² + 0² + 1² = 2 第一行第二列 = 1·0 + 0·1 + 1·1 = 1 第二行第二列 = 0² + 1² + 1² = 2

所以 G = [[2,1],[1,2]]。行列式 2·2 − 1·1 = 3 > 0,迹 4 > 0,特征值 (4 ± √(16−12))/2 = (4 ± 2)/2,得到 3 和 1,两个都正,正定。

用定义直接验算更直观。令 x = (x₁, x₂):

x^T G x = 2x₁² + 2x₁x₂ + 2x₂² = x₁² + x₂² + (x₁ + x₂)²

三个平方项相加,只有 x₁ = x₂ = 0 时才可能为 0,这跟“列线性无关”完全对应。这里能配成平方和不是巧合,任何 x^T A^T A x 都能写成 ||Ax||²,也就是若干个线性组合的平方和,配方只是把这个事实显式展开。

3.2 反例一:列成比例

取 B = [[1,1], [2,2], [3,3]],3×2,第二列正好是第一列的两倍。

G = B^T B = [[14,14],[14,14]],秩 1,特征值 28 和 0。半正定,但绝对不正定。取 x = (1, −1) 直接得到 0,连算都不用算。

这个例子值得多看一眼:B 不是零矩阵,m > n 形状看起来“应该没问题”,元素也是普通的正整数,可它就是不正定。这就是为什么不能只看形状,还得看列相关性——而列相关性在真实数据里,往往就是以“两个特征只差一个倍数”这种平淡无奇的形式出现的。

3.3 反例二:矮胖

取 C = [[1,0,0], [0,1,0]],2×3。

G = C^T C = diag(1, 1, 0),特征值 1、1、0。取 x = (0,0,1) 时二次型为 0。这里甚至不需要 C 的列有什么关联,单纯是维度不够,第三列在二维空间里无论如何都活不成独立方向。

3.4 反例三:方阵但奇异

取 D = [[1,2],[2,4]],方阵,det = 4 − 4 = 0。

G = D^T D = [[5,10],[10,20]],一样是秩 1,特征值 25 和 0。很多人的思维定式是“方阵嘛,只要不是零矩阵大概就能求逆”,这个例子就是专门打这种定式的。方阵可逆与否则看行列式,转置乘自己并不会凭空创造出可逆性。

3.5 一个必须单独说的坑:特征值别乱猜

不少人脑子里有个模糊印象:“A^T A 的特征值就是 A 的特征值的平方”。这话在 A 对称时成立,一般情况下是错的。

反例:A = [[1,1],[0,1]],特征值 1、1,看起来挺“正”。但 A^T A = [[1,1],[1,2]],特征值是 (3 ± √5)/2,约 2.618 和 0.382,跟 1、1 差得远。

正确说法是:A^T A 的特征值是 A 的奇异值的平方。奇异值和特征值只有在 A 正规(包含对称、正交、反对称这几种)时才通过绝对值对上关系 σ_i = |λ_i|。对于矩形矩阵,“A 的特征值”这个说法本身就不成立,根本无法比较。

这个误区在判断正定性上的实际危害是:你会因为 A 看起来特征值都非负,就错误地推断 A^T A 一定正定。而矩阵是否正定,完全由它自己的特征值符号决定,跟 A 的特征值没有直接对应关系。

4. 代码里怎么判:五种判据的边界与实测

4.1 判据对比

判据数学形式计算成本数值稳健性适用场景
定义法验证二次型恒正极高差证明用,不用于计算
顺序主子式所有 det(G_k) > 0O(n⁴)很差n 极小的教学演示
特征值λ_min > 0O(n³)一般需要知道最小特征值有多小
Cholesky 分解G = LL^T 成功O(n³)/3较好算法内部首选
秩判据rank(A) = nO(mn²)最好判断 A^T A 正定的首选

我的习惯很固定:判断 A^T A 是否正定,几乎永远走最后一行,直接看 A 的秩,用 SVD 做,带相对容差。理由很直接——A^T A 的条件数是 A 的条件数的平方,你在 G 上做判断,等于把精度损失了一倍,本来能分辨的东西变分辨不了了。

Cholesky 是第二选择,适合那些“我就是要分解出来用”的场景。它有个好处:数据结构上不需要额外的容差,成功就是成功,抛异常就是不正定,判定干脆。坏处是对于“几乎奇异”的矩阵,它会因为一个微小的负值而失败,而你其实很想把它当成正定来处理——这时候就需要正则化介入,第 5 节会讲。

4.2 Python 实操:三行核心逻辑

import numpy as np def check_ata(A, tol=1e-10): A = np.asarray(A, dtype=float) m, n = A.shape G = A.T @ A s = np.linalg.svd(A, compute_uv=False) # 奇异值,降序排列 if s.size == 0: return G, False, s rank = int((s > tol * s[0]).sum()) # 相对容差判秩 return G, rank == n, s A = np.array([[1., 0.], [0., 1.], [1., 1.]]) G, is_pd, s = check_ata(A) print(G) print("特征值:", np.linalg.eigvalsh(G)) print("奇异值:", s, "正定?", is_pd)

跑出来 G 是[[2. 1.] [1. 2.]],特征值[1. 3.],奇异值[1.73205081 1.],正定判定为 True。注意奇异值是特征值的算术平方根,1.732 是 √3,1 是 √1,跟手算完全一致。

换成坏例子:

B = np.array([[1., 1.], [2., 2.], [3., 3.]]) G2, is_pd2, s2 = check_ata(B) print(G2) print("特征值:", np.linalg.eigvalsh(G2)) print("奇异值:", s2, "正定?", is_pd2)

G2 是[[14. 14.] [14. 14.]],特征值[0. 28.],奇异值[6.324 0.],判定 False。注意最小奇异值直接是 0,不是 1e-17 之类的噪声,因为这个例子是精确的秩亏,浮点也很难算出非零。

Cholesky 版本:

def is_pd_cholesky(G): try: np.linalg.cholesky(G) return True except np.linalg.LinAlgError: return False print(is_pd_cholesky(A.T @ A)) # True print(is_pd_cholesky(B.T @ B)) # False

条件数对比实验,用范德蒙德矩阵最直观:

t = np.linspace(0.0, 1.0, 21) V = np.vander(t, 8, increasing=True) print("cond(V) =", np.linalg.cond(V)) # 量级约 1e6 print("cond(V^T V) =", np.linalg.cond(V.T @ V)) # 量级约 1e12

两个数相差正好是平方关系。这就是为什么“列满秩但接近共线”的数据,用正规方程解出来的系数会离谱到没法看——你在一个条件数 1e12 的系统上做消元,双精度的 16 位有效数字基本被吃干净。

4.3 秩判定到底怎么设容差

np.linalg.matrix_rank的默认容差是 max(m, n) · eps · σ_max,其中 eps 是机器精度,双精度下约 2.22e-16。这个默认值在大多数场景下合理,但如果 A 是病态构造的(范德蒙德、指数衰减基函数、近似共线的特征),就得自己动手。

我自己踩过的坑:用一组极其接近共线的特征做回归,数学上传入的 A 列确实线性无关,理论上正定;但浮点计算之后 σ_min/σ_max 掉到 1e-17 量级,比机器精度还小,SVD 给出的 σ_min 干脆就是 0 或者 1e-18 的纯噪声。这时候你判“不正定”,程序拒绝求解,其实是物理上正确的——输入数据本身的数据质量不足以支撑这个精度的结论。工程上的正确处理不是提高精度,而是要么删特征,要么上正则化,接受一个有偏但稳定的解。

提示:判断 A^T A 是否正定,不要在 G 上看“特征值是否大于某个小数”。G 的最小特征值是 σ_min²,平方一次就把 1e-8 的差别压成 1e-16,直接掉进浮点噪声里。要看就看 A 的 σ_min,保留原始精度。

还有一个容易忽视的点:如果 A 的各列量纲差异巨大(一列是百万级的销量,一列是零到一之间的比例),G 的对角元会相差好几个数量级,条件数被人为放大。这时候先做列标准化(每列除以其范数),再判断秩,结果会诚实得多。我现在的习惯是:任何涉及 A^T A 的判断,前面都先做一次列归一化。

5. 这个结论在工程里到底值多少钱

5.1 最小二乘与正规方程

解 min ||Ax − b||²,对 x 求导令其为零,得到正规方程 A^T A x = A^T b。

解的唯一性完全由 A^T A 的正定性决定:

  • A 列满秩 → A^T A 正定 → 唯一解 x = (A^T A)⁻¹ A^T b;
  • A 列不满秩 → A^T A 奇异 → 无穷多解,必须额外加约束(比如取最小范数解,用伪逆)。

这就是为什么“用 30 个样本拟合 100 个特征”的回归解不出来,而“用 1000 个样本拟合 10 个特征”很轻松。不是算法的问题,是矩阵结构在源头上就不允许。

还要提一句“理论正确但工程错误”的经典案例:即使 A 列满秩,直接算 (A^T A)⁻¹A^T b 也是下策,因为 cond(A^T A) = cond(A)²。列满秩但接近共线时,正规方程解出的系数可能跟真值差着好几个数量级。工程上的标准做法是改用 QR 分解(对 A 直接做,条件数是 cond(A) 而不是它的平方)或 SVD。数学上两条路等价,数值上差得很远。

5.2 协方差矩阵、Gram 矩阵与核矩阵

同样的结构在不同领域反复出现,只是换了名字:

  • 协方差矩阵:中心化数据矩阵 X(n 个样本 × p 个特征),协方差 C = X^T X/(n−1)。C 正定 ⟺ X 列满秩 ⟺ p 个特征线性无关且 n ≥ p。做 PCA 时如果 p > n,协方差必然奇异,这就是为什么高维小样本数据做 PCA 前必须降维或者用对偶形式。
  • 线性核的 Gram 矩阵:K = X X^T,这是 A A^T 的形式,正定条件是 X 行满秩。
  • 核方法的核矩阵:有限个点上构造的核矩阵,正定核的定义本身就要求它对任意有限点集半正定,这个要求比“某一个核矩阵半正定”强得多。

顺手记一条容易混的:A A^T 和 A^T A 的非零特征值完全相同(这是 AB 与 BA 非零特征值相同的特例),但两个矩阵的正定性条件不同——A A^T 正定 ⟺ A 行满秩(rank = m),A^T A 正定 ⟺ A 列满秩(rank = n)。方阵时两者一致,矩形矩阵时千万别混。我见过有人在小样本高维场景下误判 A A^T 的性质,结论直接反了。

5.3 正则化:花一点偏差买一个正定

实际工程里,A^T A 不满秩的情况太常见——共线、样本不足、特征重复、编码时产生完全共线的哑变量,处理办法不是硬求,而是加一个“正定保险”:

A^T A + λI, λ > 0

这个矩阵对任意 A、任意 λ > 0 都严格正定。验证只用一行:

x^T (A^T A + λI) x = ||Ax||² + λ||x||² ≥ λ||x||² > 0 (x ≠ 0)

这就是岭回归,也就是 Tikhonov 正则化。λ 在这里的作用不只是“防止过拟合”这种笼统说法,它在数学上给出了一个特征值的硬下限:最小特征值至少是 λ。于是 Ch

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 20:37:05

IOCP高并发服务端:完成端口队列与SAEA复用避坑

简介&#xff1a;一套聚焦 C# 高性能并发服务端的实战示例&#xff0c;基于 SocketAsyncEventArgs 封装完成端口&#xff08;IOCP&#xff09;通讯模型&#xff0c;面向已掌握基础 Socket 编程、希望深入理解高并发网络架构的开发者。示例覆盖服务端日志查看、连接列表管理、文…

作者头像 李华
网站建设 2026/11/2 20:36:37

Java在工业物联网中的OPC UA实现与应用

1. 工业物联网与Java的融合背景工业物联网&#xff08;IIoT&#xff09;正在重塑传统制造业的运营模式&#xff0c;而Java凭借其跨平台特性和成熟的生态系统&#xff0c;成为实现IIoT系统的理想选择。在工业4.0时代&#xff0c;设备互联产生的数据量呈指数级增长&#xff0c;根…

作者头像 李华
网站建设 2026/11/2 20:36:28

嵌入式OSAL操作系统抽象层实战指南

1. 项目概述&#xff1a;这不是一份普通的学习笔记&#xff0c;而是一份嵌入式系统开发者的“操作系统抽象层”实战手记“OSAL-学习笔记”这六个字&#xff0c;乍看平平无奇&#xff0c;像是某位学生在课后随手记下的几行潦草心得。但如果你在嵌入式开发、无线通信协议栈移植、…

作者头像 李华
网站建设 2026/11/2 20:33:56

虚拟电厂在碳交易与需求响应中的协同优化策略

1. 虚拟电厂与碳交易的基本概念解析虚拟电厂&#xff08;Virtual Power Plant, VPP&#xff09;作为能源互联网时代的新型电力系统运营模式&#xff0c;其核心在于通过先进的信息通信技术和软件系统&#xff0c;将分布式发电、储能设备和可控负荷等分散资源聚合起来&#xff0c…

作者头像 李华
网站建设 2026/11/2 20:27:54

智表ZCELL的Canvas渲染与极速排序技术解析

1. 项目概述&#xff1a;智表ZCELL的排序性能突破去年在优化财务报表系统时&#xff0c;我遇到了一个棘手问题&#xff1a;当用户尝试对超过5万行的交易记录进行排序时&#xff0c;Excel开始明显卡顿&#xff0c;而专业数据库方案又过于笨重。直到测试了智表ZCELL&#xff0c;才…

作者头像 李华
网站建设 2026/11/2 20:25:45

动态规划解决网格路径计数问题

1. 问题背景与理解"不同路径"这个题目在编程领域通常指代一个经典的动态规划问题——网格路径计数问题。想象一个mn的网格&#xff0c;机器人位于左上角&#xff0c;每次只能向右或向下移动一步&#xff0c;问到达右下角有多少种不同的路径。这个问题看似简单&#x…

作者头像 李华