特征分解的缺点
特征分解的推导与意义与opencv代码在上一篇博客中介绍了特征分解的原理和推导,特征分解在一定的情况下可以很好的分解(实对称矩阵),但是也有很大的局限性
1. 只能对可对角化的方阵使用
2. 在可以对角化的情况下,特征向量之间也不一定相互正交
为了克服这些缺点,我们便在寻找对一个任意的M*N的矩阵都能找到一个类似特征分解的公式(以下的是我的理解,如果有错欢迎指出):
1.特征分解所干的事情:将在以I为基底的情况下,转换到以特征向量为基底的表示方法,并且将之在特征向量的方向上进行特征值倍的拉伸,最终再转换回以I为基底的表示方法。换一个说法就是一个可以对角化的矩阵A的作用便是:对一个基底进行拉伸,即 。
2.我们在寻找的对任意矩阵都适用的类似的方法:由于不是所有矩阵都可以找到一个基底,并且对这个基底进行拉伸一定倍数便等于A的效果,例如,P不存在逆的情况。此时我们的目标变成将在以I为正交基底的情况下,转换到另一个正交基底,再拉伸一定倍数再旋转一定的角度(在特征分解里映射到原来的基底I可以看成是旋转一个比较特殊的角度),所产生的效果和与矩阵A直接相乘的效果是一样的。换一个说法就是将一个单位正交基底经过A的映射到另一个正交基底,将拉伸的倍数提取出来,使新基底仍然是单位基底。
- PS:第一种说法是我根据特征分解的思路去理解svd分解每个矩阵代表的意义,第二种说法是根据另一篇博客的证明思路去理解的。我不知道两种思路是否都正确,欢迎指出错误。
- 第一种思路 :从右到左,第一个矩阵代表将从基底I转换到基底V,第二个矩阵代表在V基底下的一定的拉伸,U是一个单位正交矩阵(因为旋转矩阵一定是单位正交矩阵,但是单位旋转矩阵是否是正交矩阵我不确定,假设是吧),那么U的作用便是一个旋转。
- 第二种思路 :等式左边是一个正交基底,经过A的转换到另一个正交基底,同时把拉伸倍数提取出来,则成为了 。从这个角度来说,应该是任何一个矩阵的作用都是对某个基底旋转加拉伸,而可对角化的矩阵的作用刚好是旋转的角度为0,而对角矩阵的基底刚刚好是I,所以作用只是对各个轴上进行拉伸。
其实svd正是在做这么一件事情,以下的推导用第二种思路(毕竟是看别人博客的)。
奇异值分解(SVD)
将奇异分解所做的事情写成数学表达式,即为
V是一个正交基底,U也是一个正交基底,
是一个对角阵,对角线上的值为U里的每个列向量的拉伸倍数。我们的目标就是找到
这个三个矩阵。
接下来寻找一下这三个矩阵
1. 具体怎么选取正交基底V我也不太清楚,不过前人已经帮我们找到了,就是 的单位特征向量
( ),并且各个列向量都是正交的(因为 是一个实对称阵),即
2. 则A矩阵会将这组基底映射成 ,映射后的各个列向量依然是正交的,即
3.到此,我们已经证明了AV的基底也是正交的,即U的每一列都是正交的,即 接下来是将U给单位化,因为我们的目的是得到单位正交基底。
已知
又
可以得到
则令 (由于 的模长与 相等,则 一定为与 同方向的单位向量),可以解得
将上面的内容整理一下便得到了svd分解的公式
其中V为
的特征向量所组成的矩阵,
是一个对角阵,且对角线上的值为
,
如果A是一个m×n的矩阵,那么V是n×n的正交矩阵,U是m×m的正交矩阵,
是m×n的对角阵,多余的位置用0去补充。
SVD用到图片上
对角阵 的值代表的是每个方向上分量的值,明显值越大代表的影响就越大,以下是opencv+c++代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char const* argv[])
{
if (argc != 2) {
cout << "error" << endl
<< "./matrixFeature pic" << endl;
return -1;
}
Mat pic = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
pic.convertTo(pic, CV_64FC1, 1 / 255.0);
Mat w, U, Vt;
SVD::compute(pic, w, U, Vt);
Mat W(w.rows, w.rows, w.type(), cv::Scalar(0));
for (int i = 0; i < w.rows; i++) {
W.at<double>(i, i) = w.at<double>(i);
Mat svd_pic = U * W * Vt;
imshow("svd", svd_pic);
cout << i * 1.0 / w.rows * 100 << "%" << endl;
waitKey(30);
waitKey(0);
}
}
原图
一个奇异值的时候的效果
10%奇异值的效果
20%奇异值效果,可以看到20%效果已经挺不错了,就是噪点比较多
50%的奇异值已经是只有很细微的噪点了
参考:奇异值分解(SVD)原理