• 《统计学习方法》 第十五章 奇异值分解


    奇异值分解

    矩阵的奇异值分解是指将 m × n m \times n m×n实矩阵 A A A表示为以下三个实矩阵乘积形式的运算

    A = U Σ V T A = U \Sigma V ^ { T } A=UΣVT

    其中 U U U m m m正交矩阵 V V V n n n阶正交矩阵, Σ \Sigma Σ m × n m \times n m×n矩形对角矩阵

    Σ = diag ⁡ ( σ 1 , σ 2 , ⋯   , σ p ) , p = min ⁡ { m , n } \Sigma = \operatorname { diag } ( \sigma _ { 1 } , \sigma _ { 2 } , \cdots , \sigma _ { p } ) , \quad p = \operatorname { min } \{ m , n \} Σ=diag(σ1,σ2,,σp),p=min{m,n}

    其对角线元素非负,且满足 σ 1 ≥ σ 2 ≥ ⋯ ≥ σ p ≥ 0 \sigma _ { 1 } \geq \sigma _ { 2 } \geq \cdots \geq \sigma _ { p } \geq 0 σ1σ2σp0

    任意给定一个实矩阵,其奇异值分解一定存在,但并不唯一

    奇异值分解包括紧奇异值分解和截断奇异值分解

    紧奇异值分解是与原始矩阵等秩的奇异值分解,截断奇异值分解是比原始矩阵低秩的奇异值分解


    奇异值分解有明确的几何解释

    奇异值分解对应三个连续的线性变换:一个旋转变换,一个缩放变换和另一个旋转变换第一个和第三个旋转变换分别基于空间的标准正交基进行


    设矩阵 A A A的奇异值分解为 A = U Σ V T A = U \Sigma V ^ { T } A=UΣVT

    则有 A T A = V ( Σ T Σ ) V T A A T = U ( Σ Σ T ) U T \left.

    ATA=V(ΣTΣ)VTAAT=U(ΣΣT)UT" role="presentation">ATA=V(ΣTΣ)VTAAT=U(ΣΣT)UT
    \right. ATA=V(ΣTΣ)VTAAT=U(ΣΣT)UT

    即对称矩阵 A T A A^TA ATA A A T AA^T AAT的特征分解可以由矩阵 A A A的奇异值分解矩阵表示


    矩阵 A A A的奇异值分解可以通过求矩阵 A T A A^TA ATA的特征值和特征向量得到

    A T A A^TA ATA的特征向量构成正交矩阵 V V V的列

    A T A A^TA ATA的特征值 λ j \lambda _ { j } λj的平方根得到奇异值 σ i \sigma _ { i } σi

    σ j = λ j , j = 1 , 2 , ⋯   , n \sigma _ { j } = \sqrt { \lambda _ { j } } , \quad j = 1,2 , \cdots , n σj=λj ,j=1,2,,n

    对其由大到小排列,作为对角线元素,构成对角矩阵 Σ \Sigma Σ

    求正奇异值对应的左奇异向量,再求扩充的 A T A^T AT的标准正交基,构成正交矩阵 U U U的列


    矩阵 A = [ a i j ] m × n A = [ a _ { i j } ] _ { m \times n } A=[aij]m×n的弗罗贝尼乌斯范数定义为

    ∥ A ∥ F = ( ∑ i = 1 m ∑ j = 1 n ( a i j ) 2 ) 1 2 \| A \| _ { F } = ( \sum _ { i = 1 } ^ { m } \sum _ { j = 1 } ^ { n } ( a _ { i j } ) ^ { 2 } ) ^ { \frac { 1 } { 2 } } AF=(i=1mj=1n(aij)2)21

    在秩不超过 k k k m × n m \times n m×n矩阵的集合中,存在矩阵 A A A的弗罗贝尼乌斯范数意义下的最优近似矩阵 X X X

    秩为 k k k的截断奇异值分解得到的矩阵 A k A_k Ak能够达到这个最优值

    奇异值分解是弗罗贝尼乌斯范数意义下,也就是平方损失意义下的矩阵最优近似


    任意一个实矩阵 A A A可以由其外积展开式表示 A = σ 1 u 1 v 1 T + σ 2 u 2 v 2 T + ⋯ + σ n u n v n T A = \sigma _ { 1 } u _ { 1 } v _ { 1 } ^ { T } + \sigma _ { 2 } u _ { 2 } v _ { 2 } ^ { T } + \cdots + \sigma _ { n } u _ { n } v _ { n } ^ { T } A=σ1u1v1T+σ2u2v2T++σnunvnT

    其中 u k v k T u _ { k } v _ { k } ^ { T } ukvkT m × n m \times n m×n矩阵

    是列向量 u k u _ { k } uk和行向量 v k T v _ { k } ^ { T } vkT的外积, σ k \sigma _ { k } σk为奇异值

    u k , v k T , σ k u _ { k } , v _ { k } ^ { T } , \sigma _ { k } uk,vkT,σk通过矩阵 A A A的奇异值分解得到


    任意一个 m m m x n n n 矩阵,都可以表示为三个矩阵的乘积(因子分解)形式

    分别是 m m m正交矩阵,由降序排列的非负的对角线元素组成的 m m m x n n n 矩形对角矩阵

    n n n正交矩阵,称为该矩阵的奇异值分解

    矩阵的奇异值分解一定存在,但不唯一

    奇异值分解可以看作是矩阵数据压缩的一种方法,即用因子分解的方式近似地表示原始矩阵,这种近似是在平方损失意义下的最优近似


    矩阵的奇异值分解是指,将一个非零的 m m m x n n n 实矩阵 A , A ∈ R m × n A, A\in R^{m\times n} A,ARm×n表示为一下三个实矩阵乘积形式的运算

    A = U Σ V T A = U\Sigma V^{T} A=UΣVT,

    其中 U U U m m m 阶正交矩阵, V V V n n n 阶正交矩阵, Σ \Sigma Σ 是由降序排列的非负的对角线元素组成的 m m m x n n n矩形对角矩阵

    称为 A A A 的奇异值分解

    U U U的列向量称为左奇异向量, V V V的列向量称为右奇异向量

    奇异值分解不要求矩阵 A A A 是方阵,事实上矩阵的奇异值分解可以看作方阵的对角化的推广


    紧奇奇异值分解

    紧奇奇异值分解是与原始矩阵等秩的奇异值分解


    截断奇异值分解

    截断奇异值分解是比原始矩阵低秩的奇异值分解


    代码实现

    import numpy as np
    
    
    #基于矩阵分解的结果,复原矩阵
    def rebuildMatrix(U, sigma, V):
        a = np.dot(U, sigma)
        a = np.dot(a, np.transpose(V))
        return a
    
    
    #基于特征值的大小,对特征值以及特征向量进行排序。倒序排列
    def sortByEigenValue(Eigenvalues, EigenVectors):
        index = np.argsort(-1 * Eigenvalues)
        Eigenvalues = Eigenvalues[index]
        EigenVectors = EigenVectors[:, index]
        return Eigenvalues, EigenVectors
    
    
    #对一个矩阵进行奇异值分解
    def SVD(matrixA, NumOfLeft=None):
        #NumOfLeft是要保留的奇异值的个数,也就是中间那个方阵的宽度
        #首先求transpose(A)*A
        matrixAT_matrixA = np.dot(np.transpose(matrixA), matrixA)
        #然后求右奇异向量
        lambda_V, X_V = np.linalg.eig(matrixAT_matrixA)
        lambda_V, X_V = sortByEigenValue(lambda_V, X_V)
        #求奇异值
        sigmas = lambda_V
        sigmas = list(map(lambda x: np.sqrt(x)
                          if x > 0 else 0, sigmas))  #python里很小的数有时候是负数
        sigmas = np.array(sigmas)
        sigmasMatrix = np.diag(sigmas)
        if NumOfLeft == None:
            rankOfSigmasMatrix = len(list(filter(lambda x: x > 0,
                                                 sigmas)))  #大于0的特征值的个数
        else:
            rankOfSigmasMatrix = NumOfLeft
        sigmasMatrix = sigmasMatrix[0:rankOfSigmasMatrix, :]  #特征值为0的奇异值就不要了
    
        #计算右奇异向量
        X_U = np.zeros(
            (matrixA.shape[0], rankOfSigmasMatrix))  #初始化一个右奇异向量矩阵,这里直接进行裁剪
        for i in range(rankOfSigmasMatrix):
            X_U[:, i] = np.transpose(np.dot(matrixA, X_V[:, i]) / sigmas[i])
    
        #对右奇异向量和奇异值矩阵进行裁剪
        X_V = X_V[:, 0:NumOfLeft]
        sigmasMatrix = sigmasMatrix[0:rankOfSigmasMatrix, 0:rankOfSigmasMatrix]
        #print(rebuildMatrix(X_U, sigmasMatrix, X_V))
    
        return X_U, sigmasMatrix, X_V
    
    • 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
  • 相关阅读:
    ArrayList
    【SUMO】初级 Public Transport - 1
    VMware Workstation Pro详解
    【Nginx38】Nginx学习:SSL模块(二)错误状态码、变量及宝塔配置分析
    【医学影像处理】基于MRIcron的dcm2nii批量dcm转nii格式
    QT快捷键
    秋招面试问题总结
    ASAN入门参考
    Git基本命令和使用
    APS高级排产在休闲食品行业的应用
  • 原文地址:https://blog.csdn.net/qq_38973721/article/details/128067423