【矩阵论】Chapter 6— 矩阵分解知识点总结复习(附 Python 实现)

矩阵分解

1 满秩分解(Full-Rank Factorization)

  • 满秩分解定理

    m×nm\times n 矩阵 AA 的秩为 r>0r>0,则存在 m×rm\times r 矩阵 BB(列满秩矩阵)和 r×nr\times n 矩阵 CC(行满秩矩阵)使得 image-20240728220206575 并且 rank(B)=rank(C)=rrank(B)=rank(C)=r

    满秩分解不唯一

    定理:设 AA m×nm\times n 矩阵,且 rank(A)=rrank(A)=r,存在 mm 阶可逆矩阵 PP nn 阶可逆矩阵 QQ,使得img

    证明满秩分解定理:

    Latex公式渲染之后的图片

    img

    则令img,可得到 A=BCA=BC

    \because P,CP,C 是可逆矩阵,BB rr 个列是 PP 的前 rr 列;CC rr 个行是 QQ 的前 rr

    \therefore rank(B)=rank(C)=rrank(B)=rank(C)=r

  • 满秩分解步骤

    1. AA m×nm\times n 矩阵,首先求 rank(A)rank(A)
    2. AA j1,j2,jrj_1,j_2,…j_r列构成 Bm×rB_{m\times r}
    3. AAHermite 标准型(即行最简行矩阵)HH 的前 rr 行构成矩阵 Cr×nC_{r\times n}
    4. A=BCA=BC 就是矩阵 AA 的一个满秩分解
  • Python 求解满秩分解

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    import numpy as np
    from sympy import Matrix
    
    '''
    Full-Rank Factorization
    @params: A Matrix
    @return: F, G Matrix
    '''
    def full_rank(A):
        r = A.rank()
        A_arr1 = np.array(A.tolist())
        # 求解A的最简行阶梯矩阵,要转换成list,再转换成array
        A_rref = np.array(A.rref()[0].tolist())
        k = [] # 存储被选中的列向量的下标
        # 遍历A_rref的行
        for i in range(A_rref.shape[0]):
            # 遍历A_rref的列
            for j in range(A_rref.shape[1]):
                # 遇到1就说明找到了A矩阵的列向量的下标
                # 这些下标的列向量组成F矩阵,然后再找下一行
                if A_rref[i][j] == 1:
                    k.append(j)
                    break
        # 通过选中的列下标,构建F矩阵       
        B = Matrix(A_arr1[:,k])
        # G就是取行最简行矩阵A的前r行构成的矩阵
        C = Matrix(A_rref[:r])
    
        return B, C
    
    if __name__ == "__main__":
        # 表示矩阵A
        A = np.array([[1, 1, 0], [0, 1, 1], [-1, 0, 0], [1, 1, 1]])
        A = Matrix(A)
        B, C = full_rank(A)
        print("B:", B)
        print("C:", C)

2 三角分解(Triangular Factorization)

  • LULU 分解定义

    如果有一个矩阵 AA,我们能表示下三角矩阵 LL 和上三角矩阵 UU 的乘积,称为 AA 的三角分解或 LULU 分解。

    img

    更进一步,我们希望下三角矩阵的对角元素都为 11

    img

  • LULU 分解定理

    AA nn 阶非奇异矩阵,则存在唯一的单位下三角矩阵 LL 和上三角矩阵 UU 使得 A=LUA=LU 的充分必要条件是 AA 的所有顺序主子式均非零(这一条件保证了对角线元素非零),即 Δk0(k=1,,n1)\Delta_k\neq 0(k=1,…,n-1)

  • LULU 分解步骤

    AA n×nn\times n 矩阵

    1. 进行初等行变换(注意:不涉及行交换的初等变换),从第 11 行开始,到第 nn 行结束。将第 ii 行第 ii 列以下的元素全部消为 00
    2. 这样操作后得到的矩阵即为 UU
    3. 构造对角线元素全为 11 的单位下三角矩阵 LLLL 的剩余元素通过构建方程组的形式来求解。
  • Python 求解 LULU 分解

  • LULU 分解的实际意义

    • 解线性方程组

      假设我们有一个线性方程组 Ax=bAx=b,其中 AA 是一个非奇异矩阵,而 bb 是一个列向量。通过 LULU 分解,我们可以将方程组转化为两个简化的方程组 Ly=bLy=b Ux=yUx=y,其中 LL 是下三角矩阵,UU 是上三角矩阵。这两个方程组分别易于求解。

      具体:

      首先,通过前代法(forward substitution)解 Ly=bLy=b,然后通过回代法(backward substitution)解 Ux=yUx=y。这样,我们就得到了方程组的解。

  • LDULDU 分解定理

    AA nn 阶非奇异矩阵,则存在唯一的单位下三角矩阵 LL,对角矩阵 D=diag(d1,d2,,dn)D=diag(d_1,d_2,…,d_n) 和上三角矩阵 UU 使得 A=LDUA=LDU 的充分必要条件是 AA 的所有顺序主子式均非零(这一条件保证了对角线元素非零),即 Δk0(k=1,,n1)\Delta_k\neq 0(k=1,…,n-1) 并且 d1=a11,dk=ΔkΔk+1,k=2,,nd_1=a_{11},d_k=\frac{\Delta_k}{\Delta_{k+1}},k=2,…,n

  • LDULDU 分解步骤

    AA n×nn\times n 矩阵

    1. 先求 LULU 分解
    2. UU 的对角线元素提出来构成对角矩阵 DD
    3. UU 中的元素 uiju_{ij}除以 did_i,其中 did_i表示第 ii 个对角元素。这样操作得到变换后的 UU
  • Python 求解 LDULDU 分解

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    
    import numpy as np
    from sympy import Matrix
    import pprint
    
    EPSILON = 1e-8
    
    def is_zero(x):
        return abs(x) < EPSILON
    
    def LU(A):
        # 断言A必须是非奇异方阵A
        assert A.rows == A.cols, "Matrix A must be a square matrix"
        assert A.det() != 0, "Matrix A must be a nonsingular matrix"
    
        n = A.rows
    
        U = A
        # 构建出U矩阵
        # 将U转换成list,再转换成array
        U = np.array(U.tolist())
    
        # 遍历U的每一行利用高斯消元法
        for i in range(n):
            # 判断U[i][i]是否为0
            assert not is_zero(U[i][i]), "主元为0,无法进行LU分解"
            # 对i+1行到n行进行消元
            for j in range(i + 1, n):
                # 计算消元因子
                factor = U[j][i] / U[i][i]
                # 对第j行进行消元
                for k in range(i, n):
                    U[j][k] -= factor * U[i][k]
        # 消元后的矩阵U则是最终U矩阵
        U = Matrix(U)
        # 根据LU = A,得到L矩阵
        L = A * U.inv()
        return L, U
    
    def LDU(A):
        L, U = LU(A)
        D = Matrix(np.diag(np.diag(U)))
        U = D.inv() * U
        return L, D, U
    
    if __name__ == '__main__':
        A = np.array([[2, 3, 4], [1, 1, 9], [1, 2, -6]])
        A = Matrix(A)
        '''
        # test LU分解
        L, U = LU(A)
        pprint.pprint("L:")
        pprint.pprint(L)
        pprint.pprint("U:")
        pprint.pprint(U)
        '''
        # test LDU分解
        L, D, U = LDU(A)
        pprint.pprint("L:")
        pprint.pprint(L)
        pprint.pprint("D:")
        pprint.pprint(D)
        pprint.pprint("U:")
        pprint.pprint(U)
  • PLUPLU 分解

    PLU 分解是将矩阵 AA 分解成一个置换矩阵 PP、单位下三角矩阵 LL 和上三角矩阵 UU 的乘积,即 image-20240728220231616 之前 LULU 分解中限制了行交换,如果不可避免的必须进行行互换,我们就需要进行 PLUPLU 分解。

    实际上只需要把 A=LUA = LU 变成 P1A=P1PLUP^{-1}A = P^{-1}PLU 就可以了,实际上所有的 A=LUA = LU 都可以写成 P1A=LUP^{-1}A = LU 的形式,由于左乘置换矩阵 P1P^{-1} 是在交换行的顺序,所以由 P1A=P1PLUP^{-1}A = P^{-1}PLU 推得适当的交换 AA 的行的顺序,即可将 AALULU 分解。当 AA 没有行互换时,PP 就是单位矩阵。

    事实上,所有的方阵都可以写成 PLUPLU 分解的形式,事实上,PLUPLU 分解有很高的数值稳定性,因此实用上是很好用的工具。

    有时为了计算上的方便,会同时间换行与列的顺序,此时会将 AA 分解成 image-20240728220240133 其中 PPLLUU 同上,QQ 是一个置换矩阵。

3 正交三角分解(QR Factorization)

  • QRQR 分解定理

    AA m×nm\times n 实(复)矩阵,mnm\ge n 且其 nn 个列向量线性无关,则存在 mm 阶正交(酉)矩阵 QQ n n 阶非奇异实(复)上三角矩阵 RR 使得 image-20240728220319602

  • QRQR 分解步骤

    AA 3×33\times 3 矩阵,即 A=(α1,α2,α3)A=(\alpha_1, \alpha_2,\alpha_3)。则:

    1. 正交化:β1=α1\beta_1=\alpha_1β2=α2k21β1\beta_2=\alpha_2-k_{21}\beta_1β3=α3k31β1k32β2\beta_3=\alpha_3-k_{31}\beta_1-k_{32}\beta_2,其中 k21=<α2,β1><β1,β1>k_{21}=\frac{<\alpha_2,\beta_1>}{<\beta_1,\beta_1>}k31=<α3,β1><β1,β1>k_{31}=\frac{<\alpha_3,\beta_1>}{<\beta_1,\beta_1>}k31=<α3,β2><β2,β2>k_{31}=\frac{<\alpha_3,\beta_2>}{<\beta_2,\beta_2>}

    2. 单位化得到矩阵 QQQ=(β1β1,β2β2,β3β3)Q=(\frac{\beta_1}{||\beta_1||},\frac{\beta_2}{||\beta_2||},\frac{\beta_3}{||\beta_3||})

    3. 计算得到矩阵 RRimage-20240728220329407

    4. 这样,A=QRA=QR

  • Python 求解 QRQR 分解

    常规计算:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    
    import numpy as np
    import sympy
    from sympy import Matrix
    from sympy import *
    import pprint
    
    
    #正交三角分解(QR)
    a = [[1, 1, -1],
         [-1, 1, 1],
         [1, 1, -1],
         [1, 1, 1]]
    
    # a = [[1,1,-1],
    #                   [1,0,0],
    #                   [0,1,0],
    #                   [0,0,1]]
    A_mat = Matrix(a)#α向量组成的矩阵A
    # A_gs= GramSchmidt(A_mat)
    A_arr = np.array(A_mat)
    L = []
    for i in range(A_mat.shape[1]):
        L.append(A_mat[:,i])
    #求Q
    A_gs = GramSchmidt(L)#α的施密特正交化得到β
    A_gs_norm = GramSchmidt(L,True)#β的单位化得到v
    
    A = []
    
    for i in range(A_mat.shape[1]):
        for j in range(A_mat.shape[0]):
            A.append(A_gs_norm[i][j])#把数排成一行
    
    A_arr = np.array(A)
    A_arr = A_arr.reshape((A_mat.shape[0],A_mat.shape[1]),order = 'F')#用reshape重新排列(‘F’为竖着写)
    #得到最后的Q
    Q = Matrix(A_arr)
    
    #求R
    
    C = []
    for i in range(A_mat.shape[1]):
        for j in range(A_mat.shape[1]):
            if i > j:
                C.append(0)
            elif i == j:
                t = np.array(A_gs[i])
                m = np.dot(t.T,t)
                C.append(sympy.sqrt(m[0][0]))
            else:
                t = np.array(A_mat[:,j])
                x = np.array(A_gs_norm[i])
                n = np.dot(t.T,x)
    #             print(n)
                C.append(n[0][0])
    # C_final为R          
    C_arr = np.array(C)
    # print(C_arr)
    C_arr = C_arr.reshape((A_mat.shape[1],A_mat.shape[1]))
    R = Matrix(C_arr)
    
    pprint.pprint("Q:")
    pprint.pprint(Q)
    pprint.pprint("R:")
    pprint.pprint(R)

    调用库函数

    1
    2
    3
    4
    5
    6
    7
    8
    
    # 求矩阵A的QR分解,保留根号
    Q_, R_ = A_mat.QRdecomposition()
    pprint.pprint("Q_:")
    pprint.pprint(Q_)
    pprint.pprint("R_:")
    pprint.pprint(R_)
    assert Q_ == Q, "Q_ != Q"
    assert R_ == R, "R_ != R"

4 奇异值分解(SVD)

  • SVDSVD 定理

    AA m×nm\times n 矩阵,且 rank(A)=rrank(A)=r,则存在 mm 阶酉矩阵 UU nn 阶酉矩阵 VV 使得 image-20240728220417133 其中 Σ=diag(σ1,,σr)\Sigma=diag(\sigma_1,…,\sigma_r),且 σ1σr>0\sigma_1\geq …\geq \sigma_r>0

    σ\sigma AA 的奇异值,具体含义这里不在叙述,但需要记住的是 σ2\sigma^2 AHAA^HA 的特征值,也是 AAHAA^H 的特征值,且:

    1. AHAA^HA AAHAA^H 的特征值均为非负数
    2. AHAA^HA AAHAA^H 的非零特征值相同,并且非零特征值的个数(重特征值按重数计算)等于 rank(A)rank(A)

    所以我们求 Σ\Sigma 就转换成求这两个矩阵其中一个的特征值。

  • SVDSVD 分解步骤

    1. AHAA^HA nn 个特征值,即计算λIAHA=0|\lambda I-A^HA|=0。得到特征值:λ1,,λr,λr+1=0,,λn=0\lambda_1,…,\lambda_r,\lambda_{r+1}=0,…,\lambda_n=0,其中 r=rank(A)r=rank(A)

    2. rr 个奇异值(即非零特征值开根号)从大到小排列组成对角矩阵,再添加额外的 00 构成 Σm×n\Sigma_{m\times n}矩阵。 image-20240728220426625

    3. 求特征值:λ1,,λr,λr+1=0,,λn=0\lambda_1,…,\lambda_r,\lambda_{r+1}=0,…,\lambda_n=0 对应的特征向量 ξ1,,ξn\xi_1,…,\xi_n:当 λ=λ1\lambda=\lambda_1时,(λIAHA)×ξ1=0(\lambda I-A^HA)\times \xi_1=0,解得 ξ1\xi_1,同理,计算其余特征向量。

    4. 因为 ξ1,,ξn\xi_1,…,\xi_n相互正交,我们还需要进行单位化,得到 v1,,vnv_1,…,v_n,即 v1=ξ1ξ1,,vn=ξnξnv_1=\frac{\xi_1}{||\xi_1||},…,v_n=\frac{\xi_n}{||\xi_n||}。则 V=(v1,,vn)V=(v_1,…,v_n)

    5. 根据 A=Um×mΣm×nVn×nHA=U_{m\times m}\Sigma_{m\times n}V_{n\times n}^H,可得 U1=AVn×nΣr×n1U_1=AV_{n\times n}\Sigma_{r\times n}^{-1}(注意,σ\sigma 此时为 Σm×n\Sigma_{m\times n}的前 rr 行),易知 U1U_1 m×rm\times r 的矩阵,我们还需要扩充 U2U_2,其为 m×(mr)m\times (m-r) 矩阵。

    6. U1HU2=0U_1^HU_2=0,取 U2U_2,必须要单位化 U2U_2,这样 U=[U1:U2]U=[U_1:U_2]

    7. img

  • Python 求解奇异值分解

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    import numpy as np
    from sympy import Matrix
    import pprint
    
    A = np.array([[1,0],[0,1],[1,1]])
    # 求A的奇异值分解
    U, sigma, VT = np.linalg.svd(A)
    print ("U:", U)
    print ("sigma:", sigma)
    print ("VT:", VT)

相关内容

Buy me a coffee~
HeZephyr 支付宝支付宝
HeZephyr 微信微信
0%