一、简介
SVD 全称:Singular Value Decomposition。SVD 是一种提取信息的强大工具,它提供了一种非常便捷的矩阵分解方式,能够发现数据中十分有意思的潜在模式。
主要应用领域包括:
- 隐性语义分析 (Latent Semantic Analysis, LSA) 或隐性语义索引 (Latent Semantic Indexing, LSI);
- 推荐系统 (Recommender system),可以说是最有价值的应用点;
- 矩阵形式数据(主要是图像数据)的压缩。
二、推导
详情请看文章。
三、结论介绍
矩阵(正交矩阵)的列向量分别是
;
是一个对角矩阵,形如:
;
矩阵的列向量分别是
。
关于 SVD 的一些重要的结论性总结:
- 任意的矩阵
是可以分解成三个矩阵;
表示了原始域的标准正交基;
表示经过
变换后的新标准正交基;
表示了
中的向量与
中相对应向量之间的比例(伸缩)关系;
中的每个
会按从大到小排好顺序,值越大代表该维度重要性越高;
- 在利用 SVD 做数据信息提取或压缩时,往往依据一些启发式策略,如直接设定只提取
中的前
项,或者另一种较常用的做法是保留矩阵中一定百分比的能量信息,一般可设定为 90%,能量信息比例的计算可先求得所有奇异值平方总和,然后将奇异值的平方依次累加到总值的 90% 为止,形如:
.
上图即为原始域的标准正交基到新标准正交基的转换。
四、python实现
# -*- coding: utf-8 -*-
import numpy as np
import numpy.linalg as la
import matplotlib.pyplot as plt
from sklearn import datasets
from skimage import io
def getImgAsMat(index):
ds = datasets.fetch_olivetti_faces()
return np.mat(ds.images[index])
def getImgAsMatFromFile(filename):
img = io.imread(filename, as_grey=True)
return np.mat(img)
def plotImg(imgMat):
plt.imshow(imgMat, cmap=plt.cm.gray)
plt.show()
def recoverBySVD(imgMat, k):
# singular value decomposition
U, s, V = la.svd(imgMat)
# choose top k important singular values (or eigens)
Uk = U[:, 0:k]
Sk = np.diag(s[0:k])
Vk = V[0:k, :]
# recover the image
imgMat_new = Uk * Sk * Vk
return imgMat_new
# -------------------- main --------------------- #
A = getImgAsMatFromFile('D:/pic.jpg')
plotImg(A)
A_new = recoverBySVD(A, 30)
plotImg(A_new)
这里用小黄人的大头照做个例子看看:
原图:
设置 k = 10,得到的压缩图:
k = 20:
k = 30:
继续增加 k 值,将会得到越来越接近原始图的压缩图。
五、应用举例
实例一
经过这个矩阵变换后的效果如下图所示:
在这个例子中,第二个奇异值为 0,因此经过变换后只有一个方向上有表达。
M = u1σ1 v1T.
换句话说,如果某些奇异值非常小的话,其相对应的几项就可以不同出现在矩阵 M 的分解式中。因此,我们可以看到矩阵 M 的秩的大小等于非零奇异值的个数。
实例二
我们来看一个奇异值分解在数据表达上的应用。假设我们有如下的一张 15 x 25 的图像数据。
如图所示,该图像主要由下面三部分构成。
我们将图像表示成 15 x 25 的矩阵,矩阵的元素对应着图像的不同像素,如果像素是白色的话,就取 1,黑色的就取 0. 我们得到了一个具有375个元素的矩阵,如下图所示
如果我们对矩阵M进行奇异值分解以后,得到奇异值分别是
σ1 = 14.72
σ2 = 5.22
σ3 = 3.31
矩阵M就可以表示成
M=u1σ1 v1T + u2σ2 v2T + u3σ3 v3T
vi具有15个元素,ui 具有25个元素,σi 对应不同的奇异值。如上图所示,我们就可以用123个元素来表示具有375个元素的图像数据了。
实例三
减噪(noise reduction)
前面的例子的奇异值都不为零,或者都还算比较大,下面我们来探索一下拥有零或者非常小的奇异值的情况。通常来讲,大的奇异值对应的部分会包含更多的信息。比如,我们有一张扫描的,带有噪声的图像,如下图所示
我们采用跟实例二相同的处理方式处理该扫描图像。得到图像矩阵的奇异值:
σ1 = 14.15
σ2 = 4.67
σ3 = 3.00
σ4 = 0.21
σ5 = 0.19
...
σ15 = 0.05
很明显,前面三个奇异值远远比后面的奇异值要大,这样矩阵 M 的分解方式就可以如下:
M u1σ1 v1T + u2σ2 v2T + u3σ3 v3T
经过奇异值分解后,我们得到了一张降噪后的图像。
实例四
数据分析(data analysis)
我们搜集的数据中总是存在噪声:无论采用的设备多精密,方法有多好,总是会存在一些误差的。如果你们还记得上文提到的,大的奇异值对应了矩阵中的主要信息的话,运用SVD进行数据分析,提取其中的主要部分的话,还是相当合理的。
作为例子,假如我们搜集的数据如下所示:
我们将数据用矩阵的形式表示:
经过奇异值分解后,得到
σ1 = 6.04
σ2 = 0.22
由于第一个奇异值远比第二个要大,数据中有包含一些噪声,第二个奇异值在原始矩阵分解相对应的部分可以忽略。经过SVD分解后,保留了主要样本点如图所示
就保留主要样本数据来看,该过程跟PCA( principal component analysis)技术有一些联系,PCA也使用了SVD去检测数据间依赖和冗余信息.