一,SVD分解说明
在大部分情况下,当我们把矩阵ΣΣ里的奇异值按从大到小的顺序呢排列以后,很容易就会发现,奇异值σσ减小的速度特别快。在很多时候,前10%甚至前1%的奇异值的和就占了全部奇异值和的99%以上。
二,SVD分解的应用
1.降维
通过上面的式子很容易看出,原来矩阵AA的特征有nn维。而经过SVD分解之后,完全可以用前rr个非零奇异值对应的奇异向量表示矩阵AA的主要特征。这样,就天然起到了降维的作用。
2.压缩
还是看上面的式子,再结合第三部分的图,也很容易看出,经过SVD分解以后,要表示原来的大矩阵AA,我们只需要存U,Σ,V三个较小的矩阵的即可。而这三个较小矩阵的规模,加起来也远远小于原有矩阵AA。这样,就天然起到了压缩的作用。
三,QR分解的运算
它是将矩阵分解成一个正规正交矩阵Q与上三角形矩阵R,所以称为QR分解法。该算法对对称矩阵和非对称矩阵都适用。用施密特正交计算方法如下
四,QR分解的应用
QR 分解经常用来解线性最小二乘法问题。
QR分解的实际计算有很多方法,例如[ivens旋转,Householder变换以及Gram-Schmidt正交化等等。每一种方法都有其优点和不足。
五,opencv实践
用opencv按10%特征还原图片的c++代码如下:
include <opencv.hpp>
using namespace cv;
//参数分别为输入图像,输出图像,压缩比例
void SVDRESTRUCT(const cv::Mat &inputImg, cv::Mat &outputImg, double theratio)
{
cv::Mat tempt;
cv::Mat U, W, V;
inputImg.convertTo(tempt, CV_32FC1);
cv::SVD::compute(tempt, W, U, V);
cv::Mat w = Mat::zeros(Size(W.rows, W.rows), CV_32FC1);
int len = theratio * W.rows;
for (int i = 0; i < len; ++i)
w.ptr<float>(i)[i] = W.ptr<float>(i)[0];
cv::Mat result = U * w*V;
result.convertTo(outputImg, CV_8UC1);
}
int main(void)
{
cv::Mat scrX = imread("G:\1.jpg", 0);
cv::Mat result;
SVDRESTRUCT(scrX, result, 0.1);
cv::imshow("1", scrX);
waitKey(0);
}