6.11 奇异值分解

定义

  拖了很久没写这篇奇异值分解文章,今天把它给写了。因为奇异值分解太重要了。任意矩阵都有奇异值分解,它是将矩阵分解为三部分相乘:
A m × n = U m × m ( Σ r × r 0 0 0 ) m × n V n × n H A_{m \times n}=U_{m \times m}\begin{pmatrix} \Sigma_{r \times r} & \bold 0 \\ \bold 0 & \bold 0\end{pmatrix}_{m \times n}V^H_{n \times n} Am×n=Um×m(Σr×r000)m×nVn×nH
  其中 U U U是m阶酉矩阵, V V V是n阶酉矩阵, Σ \Sigma Σ是所有奇异值从大到小排列组成的对角阵。从这个定义来看,奇异值分解是非常难的。但是前人已经总结出了一套算法了。奇异值分解为什么这么重要?因为这个分解提供了太多信息了。

  1. V V V的前 r r r个向量组成了矩阵行空间的一组正交基;
  2. V V V的后几个向量组成了矩阵零空间的一组正交基。
  3. U U U的前 r r r( r r r是矩阵的秩)个列向量组成了矩阵列空间的一组正交基;
  4. U U U的后几个向量组成了矩阵左零空间( N u l l ( A H ) Null(A^H) Null(AH))的一组正交基。
  5. V V V的前 r r r列由 A H A A^HA AHA的单位正交特征向量组成;
  6. U U U的前 r r r列由 A A H AA^H AAH的单位正交特征向量组成;

  这么难吗?哈哈。其实,步骤主要分以下几步:

  1. A A H AA^H AAH矩阵和 A H A A^HA AHA矩阵;
  2. A A H AA^H AAH的所有非零特征值,开根号得到奇异值,再排序得到 Σ \Sigma Σ
  3. A A H AA^H AAH的所有非零特征值的单位正交特征向量组成 U U U的前 r r r列;
  4. A H A^H AH的零空间所有单位正交向量组成 U U U的后 m − r m-r mr列;
  5. A A H AA^H AAH的所有单位正交特征向量组成 V V V的前 r r r列;
  6. A A A的零空间所有单位正交向量组成 V V V的后 n − r n-r nr列;
  7. 返回 U , V , Σ U,V,\Sigma U,V,Σ

举例

  求这个矩阵的奇异值分解:
( 0 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 ) \begin{pmatrix} 0 & 1 & 0 & 0\\ 0 & 0 & 2 & 0\\ 0 & 0 & 0 & 3\\ 0 & 0 & 0 & 0 \end{pmatrix} 0000100002000030
 一步一步来,首先求 A A H AA^H AAH矩阵和 A H A A^HA AHA矩阵:
A A H = ( 0 0 0 0 0 1 0 0 0 0 4 0 0 0 0 9 ) A H A = ( 0 0 0 0 0 1 0 0 0 0 4 0 0 0 0 9 ) AA^H=\begin{pmatrix}0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 4 & 0\\ 0 & 0 & 0 & 9\\ \end{pmatrix}\\ A^HA=\begin{pmatrix}0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 4 & 0\\ 0 & 0 & 0 & 9\\ \end{pmatrix} AAH= 0000010000400009 AHA= 0000010000400009
  再求 求 A A H AA^H AAH的所有非零特征值,得到三个奇异值:
3 , 2 , 1 3,2,1 3,2,1
  再求 A A H AA^H AAH非零特征值的的特征空间:
s p a n { ( 0 0 1 0 ) , ( 0 1 0 0 ) , ( 1 0 0 0 ) } span\{ \begin{pmatrix}0\\ 0\\ 1\\ 0\\ \end{pmatrix},\begin{pmatrix}0\\ 1\\ 0\\ 0\\ \end{pmatrix}, \begin{pmatrix}1\\ 0\\ 0\\ 0\\ \end{pmatrix} \} span{ 0010 , 0100 , 1000 }
  求 A H A^H AH的零空间为:
s p a n { ( 0 0 0 1 ) } span\{\begin{pmatrix}0\\ 0\\ 0\\ 1\\ \end{pmatrix}\} span{ 0001 }
  所以 U U U为:
( 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 ) \begin{pmatrix}0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 1\\ \end{pmatrix} 0010010010000001
  为了节省篇幅,求 V V V的顺序我就不细说了,最后求得 V V V为:
( 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 ) \begin{pmatrix}0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 1 & 0 & 0 & 1\\ \end{pmatrix} 0001001001000001
  所以最后的奇异值分解为:
( 0 1 0 0 0 0 2 0 0 0 0 3 0 0 0 0 ) = ( 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 ) ( 3 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 ) ( 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 ) \begin{pmatrix}0 & 1 & 0 & 0\\ 0 & 0 & 2 & 0\\ 0 & 0 & 0 & 3\\ 0 & 0 & 0 & 0\\ \end{pmatrix}=\begin{pmatrix}0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 1\\ \end{pmatrix} \begin{pmatrix}3 & 0 & 0 & 0\\ 0 & 2 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0\\ \end{pmatrix} \begin{pmatrix}0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 1 & 0 & 0 & 0\\ \end{pmatrix} 0000100002000030 = 0010010010000001 3000020000100000 0001001001001000

Python实现

  我没有用numpy等包,直接把以前自己写的求齐次方程组的解、QR分解等代码利用起来,代码如下:

    # 奇异值分解
    def svd(self):
        m = len(self.__vectors[0])
        n = len(self.__vectors)
        # 先计算两个矩阵
        ah = self.hermitian_transpose()
        a_ah = self * ah
        ah_a = ah * self

        # 求奇异值
        from com.youngthing.mathalgorithm.linearalgebra.hessenberg import Matrix as M
        eigen_values = M(ah_a.__vectors).eigen_values()
        eigen_values.sort(reverse=True)
        sigma = Matrix([[0 for _ in range(m)] for _ in range(n)])
        for i, e in enumerate(eigen_values):
            sigma.__vectors[i][i] = math.sqrt(e)

        # 求aah的所有单位正交特征向量
        u = []
        for i, e in enumerate(eigen_values):
            if matrix_utils.is_zero(e):
                continue
            eigen_vectors = a_ah.eigen_vector(e)
            q, _ = Matrix(eigen_vectors).qr_equations()
            u += q.__vectors
        # 求ah的零空间
        vectors = ah.homogeneous_solution()
        q, _ = Matrix(vectors).qr_equations()
        u += q.__vectors

        # 求aha的所有单位正交特征向量
        v = []
        for i, e in enumerate(eigen_values):
            if matrix_utils.is_zero(e):
                continue
            eigen_vectors = ah_a.eigen_vector(e)
            q, _ = Matrix(eigen_vectors).qr_equations()
            v += q.__vectors
        # 求a的零空间
        vectors = self.homogeneous_solution()
        q, _ = Matrix(vectors).qr_equations()
        v += q.__vectors

        return Matrix(u),sigma,Matrix(v)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值