如何在Python中检测非方阵的所有行是否正交

7 投票
4 回答
8796 浏览
提问于 2025-04-18 05:35

我可以用 np.linalg.matrix_rank(A) 来测试一个矩阵的秩。但是,怎么高效地检查矩阵 A 的所有行是否是正交的呢?

我可以把所有行两两配对,计算它们之间的内积,但有没有更好的方法呢?

我的矩阵行数比列数少,而且这些行不是单位向量。

4 个回答

1
(U.T @ U == np.eye(U.shape[0])).all()

这段代码会检查矩阵'U'是否是正交的,如果是的话就返回'True',否则返回'False'。这里用到了'all()'这个函数,它的作用是把我们在'U.T @ U == np.eye(U.shape[0])'这个操作后得到的布尔值矩阵(也就是True和False的组合)转换成一个单一的布尔值。

如果你想检查矩阵是否近似正交(也就是说,经过'U.T @ U'这个操作后得到的矩阵几乎等于一个单位矩阵),那么可以使用'np.allclose()',用法如下:

np.allclose(U.T @ U, np.eye(U.shape[0]))

注意:'@'符号是用来进行矩阵乘法的。

3

方法 #3:计算 AT 的 QR 分解

一般来说,要找到某个矩阵 X 的范围空间的正交基,可以计算这个矩阵的 QR 分解(可以使用 Givens 旋转或 Householder 反射)。Q 是一个正交矩阵,而 R 是上三角矩阵。Q 中与 R 的非零对角线元素对应的列,形成了范围空间的一个正交归一基。

如果 X 的列是 AT,也就是说 A 的行已经是正交的,那么 QR 分解中的 R 矩阵的对角线元素会是对角线上的数值,正好是 X 的列(也就是 A 的行)的长度的正负值。

大家普遍认为,这种方法在数值计算上比计算 A*AT=RT*R 更好。这种差别在处理较大的矩阵时可能更明显。不过,这个计算并不像矩阵乘法那样直接,但操作的数量是差不多的。

6

这个回答基本上总结了问题和评论中提到的方法,并对它们进行了比较和分析。


方法一 - 检查所有行对

正如你所建议的,你可以遍历所有的行对,并计算它们的内积。如果A.shape==(N,M),也就是说你有N行,每行有M个元素,那么这个方法的复杂度是O(M*N^2)。

方法二 - 矩阵乘法

正如评论中@JoeKington提到的,你可以计算乘法A.dot(A.T),然后检查所有非对角线的元素。根据用于矩阵乘法的算法,这个方法可能会比简单的O(M*N^2)算法要快一些,但只是在理论上更好。如果你的矩阵不大,这个方法反而会更慢。


方法一的优点:

  • 你可以“短路” - 一旦找到第一个非正交的行对,就可以停止检查。
  • 需要的内存更少。在方法二中,你会创建一个临时的NxN矩阵。

方法二的优点:

  • 乘法运算很快,因为它是在高度优化的线性代数库(ATLAS的BLAS)中实现的。我相信这些库会根据输入的大小选择合适的算法(也就是说,它们不会在小矩阵上使用复杂的算法,因为对于小矩阵来说,这些算法反而会更慢。O-表示法背后隐藏着一个很大的常数)。
  • 需要写的代码更少。

我认为对于小矩阵来说,方法二可能会更快,因为线性代数库经过了高度优化,尽管它们会计算整个乘法,即使在处理第一个非正交的行对之后也是如此。

5

看起来这样做就可以了

product = np.dot(A,A.T)
np.fill_diagonal(product,0)
if (product.any() == 0):

撰写回答