Unexpected results using SVD to separate components that make up a function
Show older comments
As preliminary to a larger project, I was trying out the SVD function with a test matrix made up by adding three 2D gaussians p1, p2, p3. I was hoping the SVD would be able to separate the function into these three components, and they would have the largest singular values in the S matrix.
I then tried to remake these components by setting everything except one singuar value in the S matrix to zero and calculating U*S_new*V'.
This does not make anything resembling my original components. Have I misunderstood how SVD should work, or have I misunderstood how separating the components should work?
I have attached my code:
% SVD test
clear all;
[X,Y] = meshgrid(-2:.1:4);
mu1 = [1 2];
Sigma1 = [5 3;3 5];
p1 = mvnpdf([X(:) Y(:)],mu1,Sigma1);
p1 = reshape(p1,size(X));
mu2 = [0 1];
Sigma2 = [3 0;0 1];
p2 = mvnpdf([X(:) Y(:)],mu2,Sigma2);
p2 = reshape(p2,size(X));
mu3 = [3 0];
Sigma3 = [2 1;1 2];
p3 = mvnpdf([X(:) Y(:)],mu3,Sigma3);
p3 = reshape(p3,size(X));
p = p1+p2+p3;
[U, S, V] = svd(p, "econ");
p_remade = U*S*V';
figure;
subplot(3,1,1); imagesc(p1)
subplot(3,1,2); imagesc(p2)
subplot(3,1,3); imagesc(p3)
sgtitle("original components making p")
figure;
subplot(2,1,1); imagesc(p)
title("original p")
subplot(2,1,2); imagesc(p_remade)
title("SVD p")
num_comp = 3;
Si = zeros(size(S));
figure;
comp = zeros(length(S),length(S),num_comp);
for i = 1:num_comp
Si(i,i) = S(i,i);
comp(:,:,i) = U*Si*V';
subplot(num_comp,1,i); imagesc(squeeze(comp(:,:,i)));
end
Accepted Answer
More Answers (2)
Chuguang Pan
on 14 Aug 2025
1 vote
As far as I konw, the SVD of a matrix P is equal to the summation of rank-1 components.
1 Comment
John D'Errico
on 14 Aug 2025
Yes, you are correct. The SVD will essentially split any matrix into linear combinations of rank 1 terms.
But even at that, the components it will generate will be orthogonal. As such, it would not reproduce the original PDFs, since they were not orthogonal themselves. The result would be arbitrarily random looking, and would not resemble a PDF at all.
Others have already explained why you cannot recover p1, p2 and p3 from an SVD of p = p1 + p2 + p3.
All you can do is write
p = sum_{i=1}^{i=61} S(i,i)*U(:,i).*(V(:,i).')
and it will turn out that the quality of approximation of p is already remarkable if you don't sum up to 61, but only up to 3. But note that the number 3 has nothing to do with the fact that p is the sum of 3 different PDFs - it's only based on the magnitude of the first 3 singular values.
% SVD test
clear all;
[X,Y] = meshgrid(-2:.1:4);
mu1 = [1 2];
Sigma1 = [5 3;3 5];
p1 = mvnpdf([X(:) Y(:)],mu1,Sigma1);
p1 = reshape(p1,size(X));
mu2 = [0 1];
Sigma2 = [3 0;0 1];
p2 = mvnpdf([X(:) Y(:)],mu2,Sigma2);
p2 = reshape(p2,size(X));
mu3 = [3 0];
Sigma3 = [2 1;1 2];
p3 = mvnpdf([X(:) Y(:)],mu3,Sigma3);
p3 = reshape(p3,size(X));
p = p1+p2+p3;
[U, S, V] = svd(p, "econ");
p_remade = U*S*V';
% Use only first three singular values to approximate p
num_comp = 3;
p_approx = zeros(size(p));
for i = 1:num_comp
p_approx = p_approx + S(i,i)*U(:,i).*(V(:,i).');
end
figure;
subplot(3,1,1); imagesc(p1)
subplot(3,1,2); imagesc(p2)
subplot(3,1,3); imagesc(p3)
sgtitle("original components making p")
figure;
subplot(3,1,1); imagesc(p); colorbar
title("original p")
subplot(3,1,2); imagesc(p_remade) ; colorbar
title("SVD p")
subplot(3,1,3); imagesc(p_approx);colorbar
title("approximate p")
3 Comments
John D'Errico
on 14 Aug 2025
Edited: John D'Errico
on 14 Aug 2025
You seem to be missing the point though. Suppose you start with a single PDF. Can you then reconstruct that PDF from only the first component using an SVD? And the answer is: Only very poorly, if that multivariate PDF has non-zero covariances.
% SVD test
clear all;
[X,Y] = meshgrid(-2:.1:4);
mu1 = [1 2];
Sigma1 = [5 3;3 5];
p1 = mvnpdf([X(:) Y(:)],mu1,Sigma1);
p1 = reshape(p1,size(X));
p = p1;
[U, S, V] = svd(p, "econ");
p_remade = U*S*V';
% Use only first three singular values to approximate p
num_comp = 1;
p_approx = zeros(size(p));
for i = 1:num_comp
p_approx = p_approx + S(i,i)*U(:,i).*(V(:,i).');
end
figure;
imagesc(p1);colorbar
sgtitle("original p1 component")
figure;
imagesc(p_approx);colorbar
title("approximate p")
With only one component available, the result will be only a rank 1 matrix. And therefore, we will see now a circular PDF, instead of the elliptical one of the original. Again, this ends up as a poor approximation. That p1 array is actually a mathematically rank 61 matrix (though it will be far lower when computed in double precision. Probably only numerically rank 15 or so.)
Using 3 components when you had 3 terms in the sum is not the same thing as extracting them independently from the sum.
You showed what cannot be done using SVD, I showed what can be done. Of course you are right: it doesn't help for the OP's task. But I think it's also worth to mention what SVD is good for in a different context. Especially I refer to the last part of the OP's code
num_comp = 3;
Si = zeros(size(S));
figure;
comp = zeros(length(S),length(S),num_comp);
for i = 1:num_comp
Si(i,i) = S(i,i);
comp(:,:,i) = U*Si*V';
subplot(num_comp,1,i); imagesc(squeeze(comp(:,:,i)));
end
corrected it and placed it in the correct context.
Do you know of another mathematical method that can do what the OP aims at ? My guess is that it's not possible to decompose the signal p = p1 + p2 + p3 in an adequate way.
Categories
Find more on Annotations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!



