【问题标题】:Obtaining an invertible square matrix from a non-square matrix of full rank in numpy or matlab从numpy或matlab中的满秩非方阵获取可逆方阵
【发布时间】:2010-08-21 21:19:09
【问题描述】:

假设您有一个满秩的NxM 矩阵A,其中M>N。如果我们用C_i 表示列(维度为Nx1),那么我们可以将矩阵写为

A = [C_1, C_2, ..., C_M]

如何获得原始矩阵A的第一个线性独立列,以便可以构造一个新的NxN矩阵B,它是一个具有非零行列式的可逆矩阵。

B = [C_i1, C_i2, ..., C_iN]

如何在 matlab 或 python numpy 中找到索引 {i1, i2, ..., iN}?这可以使用奇异值分解来完成吗?代码 sn-ps 将非常受欢迎。

编辑: 为了使这一点更具体,请考虑以下 python 代码

from numpy import *
from numpy.linalg.linalg import det

M = [[3, 0, 0, 0, 0],
     [0, 0, 1, 0, 0],
     [0, 0, 0, 0, 1], 
     [0, 2, 0, 0, 0]]
M = array(M)

I = [0,1,2,4]
assert(abs(det(M[:,I])) > 1e-8)

所以给定一个矩阵 M,我们需要找到一组 N 线性独立的列向量的索引。

【问题讨论】:

    标签: python matlab numpy linear-algebra svd


    【解决方案1】:

    在 MATLAB 中简单易用。使用 QR,特别是旋转的 QR。

    M = [3 0 0 0 0;
         0 0 1 0 0;
         0 0 0 0 1; 
         0 2 0 0 0]
    
    [Q,R,E] = qr(M)
    Q =
         1     0     0     0
         0     0     1     0
         0     0     0     1
         0     1     0     0
    
    R =
         3     0     0     0     0
         0     2     0     0     0
         0     0     1     0     0
         0     0     0     1     0
    
    E =
         1     0     0     0     0
         0     1     0     0     0
         0     0     1     0     0
         0     0     0     0     1
         0     0     0     1     0
    

    E 的前 4 列指定要使用的 M 的列,即列 [1,2,3,5]。如果你想要 M 的列,只需形成产品 M*E。

    M*E
    ans =
         3     0     0     0     0
         0     0     1     0     0
         0     0     0     1     0
         0     2     0     0     0
    

    顺便说一句,使用 det 来确定矩阵是否为奇异矩阵是绝对、肯定、绝对最糟糕的方法。

    改用排名。

    基本上,您几乎不应该在 MATLAB 中使用 det,除非您明白为什么这样做是一件糟糕的事情,并且尽管如此,您还是选择使用它。

    【讨论】:

    【解决方案2】:

    我的第一个想法是尝试 M 列中 N 列的每种可能组合。可以这样完成(在 Python 中):

    import itertools
    import numpy.linalg
    
    # 'singular' returns whether a matrix is singular.
    # You could use something more efficient than the determinant
    # (I'm not sure what options there are in NumPy)
    singular = lambda m: numpy.linalg.det(m) == 0
    
    def independent_square(A):
        N,M = A.shape
        for colset in itertools.combinations(xrange(M), N):
            B = A[:,colset]
            if not singular(B):
                return B
    

    如果您想要列索引而不是生成的方阵,只需将return B 替换为return colset。或者您可以通过return colset,B 获得两者。

    我不知道 SVD 有什么帮助。事实上,除了反复试验之外,我想不出任何可以将 A 转换为 B 的纯数学运算(甚至任何可以计算出 MxN 列选择矩阵 Q 使得 B=A.Q 的运算)。但是,如果您想知道是否存在,math.stackexchange.com 将是一个很好的询问地点。

    如果您只需要一种计算方式,上面的代码就足够了。

    【讨论】:

    • 谁投了反对票,请说明为什么你认为这个程序是错误的。
    • 我没有投反对票,但它真的很贵。 Determinate 计算起来很昂贵:如果 numpy 提供它,行减少会更好(我不知道)。更好的算法是归纳的:假设 n-1 列是线​​性独立的。然后继续尝试下一个未使用的列,直到找到一个也是线性独立的列。重复。请记住,即使您可能不必搜索所有这些,(除非您这样做,否则它们不会被创建)您愿意搜索 M!/(N!(M - N)!) 组合在那里。
    • 我不知道 Numpy 是否也提供行缩减功能...行列式只是我能想到的确定列的线性独立性的第一种方法,因为我找不到 @987654325 @ 函数(当然有一个,但它并没有按照你的想法做)。我想我应该编辑说任何查找列是否线性独立的过程都可以在那里工作。
    • 您想知道为什么这是一个糟糕的解决方案吗?这个解决方案的问题在于它可能非常低效,具体取决于 M 和 N 的值。例如,当 N = 100 和 M = 50 时,可能有超过 1e29 种列组合。对列进行蛮力搜索真是太疯狂了。鉴于在 QR 分解中有一个非常好的解决方案,使用像蛮力搜索这样的低效算法是愚蠢的。更糟糕的是,我相信您最初的回答提出了确定奇点的决定因素。 det 对任何矩阵都是一件可怕的事情。
    • 没有人说过它在数学上是错误的。我建议作为解决此问题的方法提供的建议很糟糕,并给出了一个很好的理由。如果 Python 中没有旋转二维码,那么还有其他选择。没有什么能阻止您提出 Gram-Schmidt 的变体,这与 QR 没有什么不同。所以写一个 GS 的旋转形式,它只是说你减去指向到目前为止找到的先前列的方向的分量,然后以剩余幅度最大的列为中心。 (这写起来很简单。)
    猜你喜欢
    • 1970-01-01
    • 2017-07-06
    • 2019-09-28
    • 2014-02-17
    • 1970-01-01
    • 2019-05-16
    • 2018-10-06
    • 1970-01-01
    • 2012-04-05
    相关资源
    最近更新 更多