我正在尝试编写一个函数,该函数接受方阵或非方阵作为输入并返回行的子集,以便返回的矩阵是满秩的。我还需要跟踪删除了哪些线性相关行。尽管我的示例很简单,但矩阵并不总是二进制值。
关于这个主题似乎有很多线程(例如如何从矩阵中找到线性独立的行),这促使我尝试 QR 分解方法:
def reduce_to_full_rank(A):
Q, R = np.linalg.qr(A)
to_keep = (np.abs(np.diag(R)) > 1e-10)
return A[to_keep]
我不明白的是为什么这种方法似乎取决于 A 中行的顺序。
例如,给定输入:
A = np.array(
[
[1,1,0],
[1,1,0],
[1,1,1],
]
)
以下代码打印等级 2,这是有道理的,因为 [1,1,0] 和 [1,1,1] 是独立的。
Q, R = np.linalg.qr(A)
rank = (np.abs(np.diag(R)) > 1e-10).sum()
print(rank)
但是,如果我只是将 A 的顺序更改为:
A = np.array(
[
[1,1,1],
[1,1,0],
[1,1,0],
]
)
完全相同的代码打印排名为 1,因为 R 只有一个非零对角元素。
请谁能帮助我理解:
谢谢!
确实,这可能取决于硬件。
所以,就我而言
Qme,Rme=np.linalg.qr([[1,1,1],[1,1,0],[1,1,0]])
Qme=
array([[-0.57735027, -0.57735027, -0.57735027],
[-0.57735027, 0.78867513, -0.21132487],
[-0.57735027, -0.21132487, 0.78867513]])
Rme=
array([[-1.73205081, -1.73205081, -0.57735027],
[ 0. , 0. , -0.57735027],
[ 0. , 0. , -0.57735027]])
这是正确的 Q/R 分解,因为 Q 是正交的
[email protected]
array([[ 1.00000000e+00, 7.91376881e-18, -1.76949056e-17],
[ 7.91376881e-18, 1.00000000e+00, 2.98200950e-18],
[-1.76949056e-17, 2.98200950e-18, 1.00000000e+00]])
基本上是身份。所以 Q 确实是正交的。
R 是三角形。
还有
Qme@Rme =
array([[ 1.00000000e+00, 1.00000000e+00, 1.00000000e+00],
[ 1.00000000e+00, 1.00000000e+00, 7.91376881e-18],
[ 1.00000000e+00, 1.00000000e+00, -1.76949056e-17]])
基本上是原始矩阵。
但是你的Q/R也是正确的(有更大的错误,但这可能是因为numpy输出的复制和粘贴,被截断了)
Qyou =
array([[-5.77350269e-01, 8.16496581e-01, -2.21595527e-16],
[-5.77350269e-01, -4.08248290e-01, -7.07106781e-01],
[-5.77350269e-01, -4.08248290e-01, 7.07106781e-01]])
Ryou =
array([[-1.73205081e+00, -1.73205081e+00, -5.77350269e-01],
[ 0.00000000e+00, -3.13297402e-17, 8.16496581e-01],
[ 0.00000000e+00, 0.00000000e+00, -1.69038416e-16]])
同样
[email protected] =
array([[ 1.00000000e+00, 1.30276010e-10, 1.30275697e-10],
[ 1.30276010e-10, 9.99999999e-01, -3.33885539e-10],
[ 1.30275697e-10, -3.33885539e-10, 9.99999999e-01]])
接近身份(再次,1e-10而不是1e-17是因为在论坛中复制和粘贴)
所以你的 Q 也是正交的
你的 R 也是三角形的。还有
Qyou@Ryou =
array([[1.00000000e+00, 1.00000000e+00, 1.00000000e+00],
[1.00000000e+00, 1.00000000e+00, 1.30275973e-10],
[1.00000000e+00, 1.00000000e+00, 1.30275734e-10]])
所以两者都是同一矩阵的正确 QR 分解。 毫无疑问。那是数学,而不是 numpy (尽管我用 numpy 验证了这一点,但至少,它是相同的 numpy 说两者都可以。另外,我确信任何其他线性代数,甚至只是纸和笔也会这么说)
因此,如果同一矩阵的两个正确的 QR 分解在对角线上没有相同数量的 0 元素,则意味着我一开始忽略了该假设(并且在没有考虑太多的情况下假设是正确的,因为它来自math.stackexchange...)是错误的。 这不是一个麻木的问题。只是,如果同秩矩阵(甚至相同矩阵)的2个正确的QR分解在对角线上的0元素数量不同,则证明对角线上的0元素数量不是标准。
如果你仔细想想,这是非常合乎逻辑的。
您知道 Q 由独立的行和列组成(至少在方形情况下)。而R列就是如何组合Q列来创建A=QR列。
因此,就我而言,A 的第一列只是(对于乘法因子)Q 的第一列。QR 分解也是如此。
A 的第二列是相同的,因为 Q 的第二列与第一列相同。对于我们的分解。对角线元素中的 0 确实证明我们不会使用“新”向量来创建 A 的第二列;仅是我们第一次使用过的向量。因此,排名下降-1。 在我们的两个例子中。
场景不同的地方(以及考虑解释变得很重要的地方)是第三列。
在我的例子中,R 的第三列有 3 个非零值(因此对角线元素上有一个非 0,但这并不重要)。 所以,这意味着我将用于 A“新”向量的第三列,我还没有用于第 2 列。因为这是我第一次在第二行和第三行中有非零。所以第一次我将结合 Q 的第二列和第三列。所以,这是一个新的维度。排名不会下降。
在您的情况下,R 的第三列只有 2 个非零值。对角线元素为0。不过没关系。重要的是,第二行第一次不为零。您正在使用创建 A 的第三列和 Q 的第二列,这是第一次。您还没有对前两列执行此操作。所以,这也是一个新的维度。因此,尽管对角线上的值为 0,但排名并没有降低。
所以,重要的不是对角线值非0。这是一个非 0 的新行。之前所有列中都为 0 的行都为非 0。
在满秩情况下,确实是在对角线值上。但在非满秩情况下,“新的非 0”可能位于对角线上,或者可能更高。
因此,对角线相关的唯一情况是证明矩阵是否满秩。如果R的对角线上有0,则矩阵不是满秩的。否则就是这样。
所以,简短的回答:R 对角线中非零元素的数量不是秩。