SVD
可谓线性代数的登峰造极者。
其本质就是找到将任何一个矩阵对角化分解的两组标准正交的基底,同时对应的奇异值反映了对应基底变换的性质,为0表示对应的维度缺少信息,越大表明对应的维度容纳的信息方差越大。
认识一个问题总要追根究底,为什么要有SVD
这个东西呢?
要了解这一点,必须知道矩阵对角化
是个奇妙的东西,以及并不是所有的矩阵都可以对角化。同时引出了今天的重点——如何让每个矩阵都可以对角化?
矩阵分析中,我们都想要好的矩阵,好的矩阵的一大特点就是可以对角化。
对角化的对象矩阵有两类:
对角化的方法也有两类:
所以,综合对角化对象矩阵的形状以及对角化的方法,有以下结论:
对角化的优点是(以特征值分解举例):
那么,具体如何将一个矩阵分解成对角矩阵和标准正交矩阵的乘积?
SVD的几何意义是对于特定的矩阵 Amn ,寻找行空间 Rn 中的一组标准正交基,通过线性变换 A 得到列空间 Rm 中的一组标准正交基。 σi 也可以理解成变换到 AV 空间后的模 Avi=σiui 。
同时,如果矩阵的秩为 r ,那么行空间、零空间、列空间、左零空间的示意与转换如上图所示。
采用matlab
中的eigshow
函数,可以得到类似的解释:
通过选择一组合适的正交基 V ,使得 AV=US 也是正交的。然后分别以这两组正交且单位化的 V,U 为基, S 中包含了他们的比例系数,构建了对角化的矩阵 S ,实现了对角化解耦的线性变换。
首先,先来看看原来的RGB图片以及RGB分量的灰度图片:
SVD之后,先来看看SVD的奇异值大小的分布情况和累计分布比率:
接着,看一看选择不同数量的奇异值的结果。
最后,看一看图像的压缩比,原图像是 686×482 ,选择最大的100个奇异值已经能够得到相当好的结果了。这时候奇异值的累积比例为 89.6% ,压缩比是
具体代码如下:
% 读入图像RGB数据,并从Uint8转换成double类型方便之后的处理。
p = imread('/Users/yangguangyao/Desktop/test/p.jpg');
pr = p(:,:,1);
pg = p(:,:,2);
pb = p(:,:,3);
pr = double(pr);
pg = double(pg);
pb = double(pb);
% 可视化图像
figure()
subplot(2,2,1);
imshow(p)
title('原来的RGB图像')
subplot(2,2,2);
imshow(mat2gray(pr))
title('R分量的灰度图像')
subplot(2,2,3);
imshow(mat2gray(pg))
title('G分量的灰度图像')
subplot(2,2,4);
imshow(mat2gray(pb))
title('B分量的灰度图像')
% SVD分解
[Ur,Sr,Vr] = svd(pr);
[Ug,Sg,Vg] = svd(pg);
[Ub,Sb,Vb] = svd(pb);
% 分析SVD,计划选取1 3 5 10 30 50 100 150
svdD = diag(Sr);
cumsumD = cumsum(svdD);
plot(svdD,'LineWidth',2)
plot(cumsumD,'LineWidth',2)
% 分解后按照singular value从大到小选择
fr = @(n) Ur(:,1:n)*Sr(1:n,1:n)*Vr(:,1:n)';
fg = @(n) Ug(:,1:n)*Sg(1:n,1:n)*Vg(:,1:n)';
fb = @(n) Ub(:,1:n)*Sb(1:n,1:n)*Vb(:,1:n)';
param = [1,3,5,10,30,50,100,150];
figure()
for i = 1:8
subplot(2,4,i);
n = param(i);
pnew(:,:,1) = fr(n);
pnew(:,:,2) = fg(n);
pnew(:,:,3) = fb(n);
pnew = uint8(pnew);
imshow(pnew)
title(strcat(num2str(param(i)),'个奇异值'))
end
上图是一个 15×25 的图像,其本质上是 15×25 的矩阵,白色的元素代表相应位置上是1,黑色代表相应位置上是0。其一共有三种模式:
这个矩阵的特征值有3,对应了三种的模式,选择最大的三个奇异值进行SVD后的结果是:
代码如下:
% 构建目标图像矩阵X
x1 = ones(25,1);
x2 = [ones(5,1);zeros(15,1);ones(5,1);];
x3 = [ones(5,1);zeros(3,1);ones(9,1);zeros(3,1);ones(5,1);];
X = [repmat(x1,1,2),repmat(x2,1,3),repmat(x3,1,5),repmat(x2,1,3),repmat(x1,1,2)];
% 查看矩阵的秩
r = rank(X);
% 进行SVD
[U,S,V] = svd(X);
Xnew = U(:,1:r)*S(1:r,1:r)*V(:,1:r)';
% 分析画图
figure()
subplot(1,2,1)
imshow(X)
title('原始的图像')
subplot(1,2,2)
imshow(Xnew)
title('选择秩数量3的奇异值分解')
SVD总能找到标准化正交基后方差最大的维度,因此可以用它进行降维去噪等等。
下面分别用SVD
和linear regression
去拟合直线,结果如下,看来效果还不错哦。
代码如下:
% 模拟线性数据,加上一定的高斯噪声
X = 1:10;
Xb = ones(1,10);
Y = 2*X + random('Normal',0,1,1,10);
% 进行SVD分解并选择原输入空间的一个奇异值比较大的基,实现了数据降维
M = [X;Y];
[U,S,V] = svd(M);
U1 = U(:,1);
u1 = U1(1);
u2 = U1(2);
k = (u2/u1);
% 进行线性回归
w = pinv([X;Xb])'*Y';
% 分别是SVD和线性回归拟合的数据
Y1 = k*X;
Y2 = w(1)*X+w(2);
% 画图并比较
figure()
% 注释蛮方便的函数ezplot('y-2*x-1')
% refline(u2/u1,0)
hold on
plot(X,Y,'ko','LineWidth',2)
plot(X,Y1,'r-','LineWidth',1)
plot(X,Y2,'b-','LineWidth',1)
legend('数据点','SVD拟合','线性回归拟合')
LSA(Latent Semantic Analysis
也叫作Latent Semantic Indexing
)分析文档发现潜在的概念意义。
介绍下几种矩阵分解
A的行列式的绝对值等于奇异值的乘积,等于主元乘积的绝对值,等于高度 hi 乘积的绝对值,等于特征值的乘积。