% 对5*4矩阵A进行奇异值分解,并求其左右变换阵U,V
A = [1 5 7 9;
8 4 9 4;
76 5 23 9;
8 1 1 4;
6 5 3 9;];
% 从大到小排列奇异值
S = zeros(size(A));
eigen_value = svd(A);
for i = 1:1:size(eigen_value)
S(i,i) = eigen_value(i);
end
% 特征向量按照特征值从大到小的排列顺序,
[U, dia_U] = eig(A*A.');
[V, dia_V] = eig(A.'*A);
U(:,[1 2 3 4 5]) = U(:,[5 4 3 2 1]);
V(:,[1 2 3 4]) = V(:,[4 3 2 1]);
% 验证是否能够还原,运行结果来看不能还原,为你就在于U、V中某一个或几个特征向量的正负号问题
U*S*V'
运行结果,显然不能还原A矩阵
ans =
7.6947 -5.3569 -3.9229 -7.2599
12.8998 -1.6256 -2.5242 -1.2576
74.5972 7.3145 25.0283 12.8974
7.8552 -0.4563 4.2709 -1.3592
9.4310 -2.6365 1.6074 -7.2472
% 对5*4矩阵A进行奇异值分解,并求其左右变换阵U,V
A = [1 5 7 9;
8 4 9 4;
76 5 23 9;
8 1 1 4;
6 5 3 9;];
% Step1:通过求A*A'的特征值,得到A的奇异值,然后从大到小排列(为了step2生成奇异值矩阵S)
eigen_value = eig(A*A');
eigen_value = sort(sqrt(eigen_value), 'descend');
% Step2:把eigen_value变成奇异值矩阵S的形式
S = zeros(size(A));
for i = 1:1:size(eigen_value)
% 只把大于0的特征值添加到S矩阵对角位置,得到奇异值矩阵S
if eigen_value(i) >= 1e-4
S(i,i) = eigen_value(i);
end
end
% Step3:Matlab中计算出来的特征向量是按照特征值从小到大排列的,所以对列进行交换,变为特征向量按照特征值从大到小的排列顺序
[U, dia] = eig(A*A');
V1 = A'*U; % 关键之处在于这里,不能够利用[V, dia] = eig(A'*A)求V,因为这样计算得到的V中的每一个特征向量的正负号是随机的,自然复原之后的结果就与原矩阵不相符,所以要保证V的每一列与U中对应特征值的特征向量符号一致才行,所以采用V=A'*U,并消去多于列
V = V1(:,2:5); % 消去第一列与0特征值相关的向量,这里要变为方阵
% 除此之外还要记得单位化
for i = 1:4
V(:,i) = V(:,i)/norm(V(:,i));
end
% 特征向量按照特征值从大到小的排列顺序,对列交换顺序即可
U(:,[1 2 3 4 5]) = U(:,[5 4 3 2 1]);
V(:,[1 2 3 4]) = V(:,[4 3 2 1]);
% Step4:验证是否能够还原
U*S*V'
可以正确还原
ans =
1.0000 5.0000 7.0000 9.0000
8.0000 4.0000 9.0000 4.0000
76.0000 5.0000 23.0000 9.0000
8.0000 1.0000 1.0000 4.0000
6.0000 5.0000 3.0000 9.0000