奇异值分解的定义SVD(Singular Value Decomposition)可以理解为:将一个比较复杂的矩阵用更小更简单的3个子矩阵的相乘来表示,这3个小矩阵描述了大矩阵重要的特性。定义:矩阵的奇异值分解是指将一个秩为rrr的实矩阵Am×nA_{m \times n}Am×n分解为三个实矩阵乘积的形式:Am×n=Um×mΣm×nVn×nT≈Um×kΣk×kVk×nTA_{m\times n} = U_{m \times m} \Sigma_{m \times n} V ^ { T }_{n....
奇异值分解的定义
SVD(Singular Value Decomposition)可以理解为:将一个比较复杂的矩阵用更小更简单的3个子矩阵的相乘来表示,这3个小矩阵描述了大矩阵重要的特性。
定义:矩阵的奇异值分解是指将一个秩为r的实矩阵Am×n分解为三个实矩阵乘积的形式:
Am×n=Um×mΣm×nVn×nT≈Um×kΣk×kVk×nT
其中U是m阶正交矩阵(U的列向量称为左奇异向量),V是n阶正交矩阵( V的列向量称为右奇异向量),Σ是m×n矩形对角矩阵,称为奇异值矩阵,对角线上的元素称为奇异值。
Σ=[Dr×r000]m×n
D是一个r×r的对角阵,D的对角线元素是A的前r个奇异值σ1≥σ2≥⋯≥σr>0(非负,降序)。
知识点:任意一个实矩阵A可以由其外积展开式表示
A=σ1u1v1T+σ2u2v2T+⋯+σrurvrT
其中ukvkT为m×n矩阵,是列向量uk和行向量vkT的外积,σk为奇异值,uk,vkT,σk通过矩阵A的奇异值分解得到。
知识点:奇异值在矩阵中按照从大到小排列,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。我们可以用最大的k个奇异值的矩阵和UVT相乘来近似描述矩阵,从而实现了降维、减少数据存储、提升计算性能等效果。
奇异值分解的计算
设矩阵A的奇异值分解为A=UΣVT,则有
ATA=V(ΣTΣ)VTAAT=U(ΣΣT)UT
即对称矩阵ATA和AAT的特征分解可以由矩阵A的奇异值分解矩阵表示。
证明:ATA的特征值非负。
令A是m×n矩阵,那么ATA是对称矩阵且可以正交对角化,让{v1,…,vn}是Rn的单位正交基且构成ATA的特征向量,λ1,…,λn是ATA对应的特征值,那么对1≤i≤n,
∥Avi∥2=(Avi)T(Avi)=viTATAvi=viTλivi=λi
所以ATA的所有特征值都非负,如果必要,通过重新编号我们可以假设特征值的重新排列满足
λ1≥λ2≥⋯≥λn≥0
A的奇异值是ATA的特征值的平方根,记为σ1,σ2,…,σn,且它们递减顺序排列。
σj=∥Avj∥=λj,j=1,2,⋯,n
可见,对A进行奇异值分解需要求矩阵ATA的特征值及其对应的标准正交的特征向量来构成正交矩阵V的列,特征值λj的平方根得到奇异值$\sigma _ { i } 也即得到奇异值矩阵\Sigma$。
证明:假设{v1,v2,…,vn}是包含ATA特征向量的Rn上的标准正交基,重新整理使得对应ATA的特征值满足λ1≥λ2≥⋯≥λn。若A有r个非零奇异值,则{Av1,Av2,…,Avr}是ColA的一个正交基,且rankA=r。
当i不等于j时,viTvj=0。
(Avi)TAvj=viTATAvj=λjviTvj=0
所以,{Av1,Av2,…,Avn}是一个正交基。由于向量Av1,Av2,…,Avn的长度是A的奇异值,且因为有r个非零奇异值,Avi(r≥i≥1)为非零向量。所以Av1,Av2,…,Avr线性无关,且属于ColA。
对任意属于ColA的y,如y=Ax,我们可以写出x=c1v1+⋯+cnvn,且
y=Ax=c1Av1+⋯+crArvr
这样,y在Span{Av1,…,Avr}中,这说明{Av1,Av2,…,Avr}是ColA的一个正交基,因此rankA=dim(ColA)=r。
由于{Av1,Av2,…,Avr}是ColA的一个正交基,将每一个Avi单位化得到一个标准正交基{u1,u2…ur},此处
ui=∥Avi∥1Avi=σi1Avi(r≥i≥1)
将{u1,u2…ur}扩充为Rm的单位正交基{u1,u2…um}。
取
U=(u1,u2,…,um),V=(v1,v2,…,vn)
由构造可知,U和V是正交矩阵,
AV=(Av1,…,Avr,0,…,0)=(σ1u1,…,σrur,0…,0)=UΣ
即:A=UΣVT,从而得到U。
知识点:任意给定一个实矩阵,其奇异值分解一定存在,但并不唯一。
奇异值分解的实现
1. 手动实现
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):
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))
sigmas = np.array(sigmas)
sigmasMatrix = np.diag(sigmas)
if NumOfLeft is None:
rankOfSigmasMatrix = len(list(filter(lambda x: x > 0, sigmas)))
else:
rankOfSigmasMatrix = NumOfLeft
sigmasMatrix = sigmasMatrix[0:rankOfSigmasMatrix, :]
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:rankOfSigmasMatrix]
sigmasMatrix = sigmasMatrix[0:rankOfSigmasMatrix, 0:rankOfSigmasMatrix]
return X_U, sigmasMatrix, X_V
A = np.array([[4, 11, 14], [8, 7, -2]])
X_U, sigmasMatrix, X_V = SVD(A)
print(A)
print(X_U.shape)
print(sigmasMatrix.shape)
print(X_V.shape)
print(rebuildMatrix(X_U, sigmasMatrix, X_V))
2. 使用numpy.linalg.svd函数
import numpy as np
A = np.array([[4, 11, 14], [8, 7, -2]])
print(A)
u, s, vh = np.linalg.svd(A, full_matrices=False)
print(u.shape)
print(s.shape)
print(vh.shape)
a = np.dot(u, np.diag(s))
a = np.dot(a, vh)
print(a)
奇异值分解的应用
1. 数据压缩
奇异值分解可以有效地表示数据。例如,假设我们希望传输下面的图像,它由一个25×15个黑色或白色像素组成的数组。
由于此图像中只有三种类型的列,如下图所示,因此可以用更紧凑的形式表示数据。
我们将图像表示为一个25×15矩阵,矩阵的元素对应着图像的不同像素,如果像素是白色的话,就取 1,黑色的就取 0。 我们得到了一个具有375个元素的矩阵,如下图所示
如果对M进行奇异值分解,我们会发现只有三个非零奇异值σ1=14.72,σ2=5.22,σ3=3.31(非零奇异值的数目等于矩阵的秩,在这个例子中,我们看到矩阵中有三个线性无关的列,这意味着秩将是3)。
M=σ1u1v1T+σ2u2v2T+σ3u3v3T
vi具有15个元素,ui 具有25个元素,σi 对应不同的奇异值。我们就可以用123个元素来表示具有375个元素的图像数据了。通过这种方式,奇异值分解可以发现矩阵中的冗余,并提供消除冗余的格式。
2. 去噪
前面的例子展示了如何利用许多奇异值为零的情况。一般来说,大的奇异值对应的部分会包含更多的信息。假设我们使用扫描仪将此图像输入计算机。但是,我们的扫描仪会在图像中引入一些缺陷(通常称为“噪声”)。
我们可以用同样的方法进行:用一个25×15矩阵表示数据,并执行奇异值分解。我们发现以下奇异值:
σ1=14.15,σ2=4.67,σ3=3.00,σ4=0.21,…,σ15=0.05
显然,前三个奇异值是最重要的,所以我们假设其它的都是由于图像中的噪声造成的,并进行近似。
M≈σ1u1v1T+σ2u2v2T+σ3u3v3T
这导致下面的改进图像。
3. 数据分析
我们搜集的数据中总是存在噪声:无论采用的设备多精密,方法有多好,总是会存在一些误差的。如果你们还记得上文提到的,大的奇异值对应了矩阵中的主要信息的话,运用SVD进行数据分析,提取其中的主要部分的话,还是相当合理的。
假设我们收集了一些数据,如下所示:
我们可以将数据放入矩阵中:
[−1.03−2.230.741.61−0.02−0.020.510.88−1.31−2.390.992.020.691.62−0.12−0.35−0.72−1.671.112.46]
经过奇异值分解后,得到σ1=6.04,σ2=0.22。
由于第一个奇异值远比第二个要大,可以假设σ2的小值是由于数据中的噪声产生的,并且该奇异值理想情况下应为零。在这种情况下,矩阵的秩为1,意味着所有数据都位于ui定义的行上。
参考文献
- https://zhuanlan.zhihu.com/p/54693391
- http://www.ams.org/publicoutreach/feature-column/fcarc-svd
本文地址:https://blog.csdn.net/LSGO_MYP/article/details/107886273