A = randn(20,10);
[U,S,V] = svd(A);
norm(U*S*V' - A)
A = imread('image.png');
A = rgb2gray(A);
imshow(A)
For this image, the first singular value is dominant.
[U,S,V] = svd(double(A));
S(1:5,1:5)
If we reconstruct the image using only the first singular value, it looks terrible.
k = 1; % A = U S V^T
W = V';
[m,n] = size(A);
B = U(:,1:k)*S(1:k,1:k)*W(1:k,:);
B = uint8(B);
imshow(B)
fprintf('Compression ratio = %.5f', (m*k+k+n*k)/(m*n))
This required less then 1% of the storage required to store the full matrix.
Next, we look at the size of the singular values, relative to the top singular value:
DiagS = diag(S);
for i = 1:length(S)
if DiagS(i)/DiagS(1) < 0.05
i
break
end
end
The 55th singular value is less than 5% of the magnitude of the top singular value. So, we will chop there and see what image we reconstruct.
W = V';
[m,n] = size(A);
B = U(:,1:i)*S(1:i,1:i)*W(1:i,:);
B = uint8(B);
imshow(B)
fprintf('Compression ratio = %.5f', (m*i+i+n*i)/(m*n))
With just over 20% of the storage, we can compress the image so that it is at least recognizable. There are some issues that affect the true amount of storage. These are related to the fact that the original image was an integer matrix and $U,V,S$ are now double precision numbers. Whether justified, or not, we ignore that here for simplicity.
A = [1, 3; 3, 1];
eig(A)
[V,D] = eig(A)
A*V(:,1) - D(1,1)*V(:,1)
A*V(:,2) - D(2,2)*V(:,2)
A = [0, 1;-1,0];
eig(A)
[V,D] = eig(A)
A*V(:,1) - D(1,1)*V(:,1)
A*V(:,2) - D(2,2)*V(:,2)
A = [1, 3; 3, 1]; % a symmetric matrix
[V,D] = eig(A)
V*D*V'
A
A = [1, 3; 3, 1];
for i = 1:10
[Q,R] = qr(A);
A = R*Q;
end
A
eig(A)
A = [1, 3, 1; 3, 0, -1; 1, -1, 1]
for i = 1:100
[Q,R] = qr(A);
A = R*Q;
end
A
eig(A)