奇异值分解
矩阵的奇异值分解是指将 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≥⋯≥σp≥0
任意给定一个实矩阵,其奇异值分解一定存在,但并不唯一
奇异值分解包括紧奇异值分解和截断奇异值分解
紧奇异值分解是与原始矩阵等秩的奇异值分解,截断奇异值分解是比原始矩阵低秩的奇异值分解
奇异值分解有明确的几何解释
奇异值分解对应三个连续的线性变换:一个旋转变换,一个缩放变换和另一个旋转变换第一个和第三个旋转变换分别基于空间的标准正交基进行
设矩阵 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. \begin{array} { l } { A ^ { T } A = V ( \Sigma ^ { T } \Sigma ) V ^ { T } } \\\\ { A A ^ { T } = U ( \Sigma \Sigma ^ { T } ) U ^ { T } } \end{array} \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 } } ∥A∥F=(i=1∑mj=1∑n(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,A∈Rm×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