一、前言
这篇博客,主要使用最通俗的语言来讲解SVD奇异值分解,通过该篇博客,将知道 SVD 的来龙去脉,底层原理。同时知道如何利用他去做图片压缩,PCA,求解矩阵(如 Fundamental 矩阵,Homography 矩阵)等。我会详细的讲解 SVD 的每一个细节。由浅到深,由窄到广。那么我们现在就开始吧。


二、简单原理介绍
在推导数学公式,以及几何意义之前,我们先来看看其物理层面的应用。这样有助于后面更深层次的理解。首先这里有个基本的概念简单说一下, 一个nm×n 维的矩阵,我们可以分解成km×k 以及k×n 的矩阵相乘,如下图所示:






对于m行 n列的矩阵A, 通过SVD分解之后,拆分成了3个子矩阵,其中 U矩阵为 m行 m列的方阵,V为 n行 n列的方阵,Σ为只有对角线有值的矩阵,其中的值称之为奇异值。看一个例子,原始矩阵如下:



奇异值分解的结果如下



在奇异值分解中,Σ 矩阵的奇异值是按照从大到小的顺序排列的,而且减少的特别快,经常前 10% 的奇异值就占据了全部奇异值 99% 以上的比例。基于这个性质,我们可以只提取前几个奇异值及其对应的矩阵来近似的描述原来的矩阵。
那么我们现在就来做个实验,我们只获取矩阵得如下部分来复原矩A:



也就是





也就是





上图主要表示了如下公式(k与n越接近说明图像还原度越高,当然压缩效果也没有那么明显):



三、图像压缩
那么我们如何使用 SVD 来做图像压缩呢? 通过上面的介绍,我们就可以完成图像压缩了。这里我们把一张图像的像素看作前面的矩阵Am ×n,然后编写代码如下:

import cv2
import numpy as np
# 调整该值重复运行代码保存图像
k = 200
img = cv2.imdecode(np.fromfile('./1.png', dtype=np.uint8), 0)
u, w, v = np.linalg.svd(img)
u = u[:, :k]
w = np.diag(w)
w = w[:k, :k]
v = v[:k, :]
img = u.dot(w).dot(v)
cv2.imencode('.jpg', img)[1].tofile('k={}.jpg'.format(k))

调整代码中的 k值,重复保存图像。注意,根据前面的介绍我们可以得知0‹k‹h, k值越大,图像的还原度越高。原图如下:



本人调整k=100,k=50,k=20值保存结果如下:



我们输入一张图像,通过SVD奇异值分解分解之后,得到 u, w, v 三个矩阵,根据自己的需求,对这三个矩阵进行适当的剪切,代码中的剪切大小通过变量 k控制。我们只需要保存剪切之后的矩阵,就可以复原图像了。注意这里的 w 为对角矩阵,只需要保存对角线的元素即可。

那么我们来计算一下,这张图像压缩多少空间。因为上图中我们可以看到k=100 的时候,图像基本是没有太大损失的。所以我们按k=100 来计算。原始图像像素为200x200=40000。压缩之后为 200x100+100+100x100=20000+100+10000=30100。可以看到其压缩了1/4左右的大小,并且基本没有像素损失。

四、特征值分解→EVD
两个矩阵 A AAB BB 相乘, 其为A AA 的行与 B BB 的列,对应相乘相加,所以出现如下公式:



    1、矩阵乘法对应了一个变换,是把任意一个向量变成另一个方向或长度都大多不同的新向量。

    2、如果矩阵对某一个向量或某些向量只发生伸缩变换,不对这些向量产生旋转的效果,
    那么这些向量就称为这个矩阵的特征向量,伸缩的比例就是特征值。


一个 m阶的方阵,那么则有:


这里我们令:



则我们可以得到
AU=UA
进一步推导(由于这里的特征向量两两正交,所以U为正交阵,正交阵的逆矩阵等于其转置-有兴趣的同学可以百度一下正交矩阵):



到这里为止,对于方阵的特征分解可以说是完成了。但是这里出现了一个问题,上面的结论是基于方阵推导出来的,那么如果 A并非一个方阵,而是一个任意的矩阵呢? 比如前面提到的Am×n或者张长方形的图像。那么就无法 EVD 特征分解了。这个时候就轮到 SVD 奇异值分解登场了。

五、特征值分解→SVD
通过前面的介绍,我们知道知道一个方阵是可以进行 EVD 特征分解的,经过推导得到公式(13)





U 和 V我们都求出来了,现在就剩下奇异值矩阵 Σ没有求出了。由于 Σ除了对角线上是奇异值其他位置都是0,那我们只需要求出每个奇异值 σ就可以了(后面有举例如何求解)。我们注意到





七、SVD 计算举例
这里我们用一个简单的例子来说明矩阵是如何进行奇异值分解的。我们的矩阵A定义为:







六、结语
通过该篇博客,我们知道了如何对一个矩阵进行 SVD 奇异值分解,并且列举了一个图像压缩的例子。但是这仅仅其中的一部分应用,我们还可以用来求解超定方程 A x = 0 Ax = 0Ax=0(最优解)。 当然,该博客的篇幅已经很长了,所以令起一篇博客继续为大家介绍如何求解超定方程,为什么最小奇异值对应的特征值,为超定方程的解。