Skip to main content

Singular Value Decomposition of a Matrix




What You will Learn

  • You will learn to the singular value decomposition and implement it using Python.
  • You will understand SVD as a tool for trend analysis and dimensionality reduction.
  • You will use SVD as a primitive image compression scheme.

Singular Value Decomposition of a Matrix

A matrix $\mathbf{A}$ can be decomposed as \begin{equation*} \tilde{\mathbf{A}}=\sum_{i=0}^{r}\lambda_{i}U_{i}V_{i}^{T} \end{equation*} where $U_{i}$ and $V_{i}$ are the singular vectors and $\lambda_{i}$ are the eigen values with $\lambda_{i}< \lambda_{j}$ for $i>j$. The parameter $r$ is the number of eigen values of the matrix. Now let us consider a matrix of random integers and its SV decomposition using the code below.
import numpy as np
from pylab import *
A = np.mat(np.random.randint(1000, size=(1000, 1000)))
[a,b,c]=svd(A)
bnorm=b*((max(b))**-1)
figure(1) plot(bnorm[0:10],'*')
plot(bnorm[0:10])
show()
A $1000\times 1000$ matrix of random integers in the range $[0,1000]$ is created using the mat function from the numerical Python (numpy) module and its SVD is computed. The array b contains the $1000$ eigen values in the decreasing order. The arrays a and b contain the $\mathbf{U}$ and $\mathbf{V}$ with each vector corresponding to the eigen value in b. It can be seen that the eigen values are in the decreasing order. Figure below shows the first 10 normalized eigen values. It is observed that the first component is very strong and the remaining values are relatively weak. It means that the data matrix can be represented with the first few eigen values, resulting in good data compression. But it should not be forgotten that the matrix we used is purely random and the correlation between neighbouring elements is almost zero.
Let us look at the compression of the above matrix if only a few (say 10) principal eigen values and compute the Frobenius norm between the matrix and its approximation. The Frobenius norm, expressed as \begin{equation}\zeta=\sum_{i=1}^{N}\sum_{j=1}^{N}|a_{i,j}-\tilde{a_{i,j}}|^{2}\end{equation} is computed and plotted for different rank values using the code below. You can give diffrent values for rho and observe the compression.
import numpy as np
from pylab import *
A = np.mat(np.random.randint(50, size=(1000, 1000)))
a,b,c= np.linalg.svd(A)
bnorm=b*((max(b))**-1)
figure(1)
plot(bnorm[0:10],'*')
plot(bnorm[0:10])
title('Normalized eigen values')
grid('on')
show()
rho=10
frobnormarr=[]
for k in range(0,rho):

approxmat=np.dot(a[:,:k],np.dot(np.diag(b[:k]),c[:k,:]))

frobnorm=linalg.norm(A-approxmat,2)

frobnormarr.append(frobnorm)
figure(2)
plot(frobnormarr)
plot(frobnormarr,'*')
show()

Compression Ratio

You require $10^{6}$ locations for storing a $1000\times 1000$ matrix. Let us look at the compression based on SVD with say 10 principal eigen values. You require 10 locations for the eigen values, $10\times 1000$ for storing $\mathbf{U}$ (Each $\mathbf{U_{i}}$/$\mathbf{V_{i}}$ has $1000$ values) and $10\times 1000$ for storing $\mathbf{V}$, making a total of $20010$ values to store. So
\begin{equation} \text{Compression ratio}=\frac{\text{Size of the uncompressed data}}{\text{Size of the compressed data}}\\ =\frac{10^{6}}{20010}=49.98 \end{equation}

SVD of a Gray Scale Image

An image is a two dimensional array or matrix of numbers. If this image comes out of a camera or scanner, it is called a natural image. If it is a single array of integers in the range $[0,255]$, it is a gray scale image. Color images contain three such arrays each corresponding to the red, green and blue spectral components. Some hyper-spectral images such as satellite images contain 16 such channels.
The code below shows the SVD of a ($512\times512$) gray scale image. The image is read using the scipy.misc module and converted into a matrix. The rest of the steps in compression is similar to the previous code.

import scipy.misc as mis
import numpy as np
from pylab import *
img = mis.ascent()
A=mat(img)
a,b,c= np.linalg.svd(A)
bnorm=b*((max(b))**-1)
rho=40
frobnormarr=[]
for k in range(0,rho):

approxmat=np.dot(a[:,:k],np.dot(np.diag(b[:k]),c[:k,:]))

frobnorm=linalg.norm(A-approxmat,2)

frobnormarr.append(frobnorm)
figure()
subplot(221)
imshow(img)
title("Original image")
gray()
subplot(222)
imshow(approxmat)
title("Compressed image with 40 eigen values")
gray()
subplot(223)
plot(bnorm[0:10],'*')
plot(bnorm[0:10])
title('Normalized eigen values')
grid('on')
subplot(224)
plot(frobnormarr)
plot(frobnormarr,'*')
grid('on')
title("Frobenius norm between the original and compressed images")
show()

The top left figure shows the original image and the top right is the compressed image with the first $40$ eigen values. You may compare and recognize the same picture with loss of some features. The bottom left figure shows the variation of eigen values and the bottom right figure shows the variation in Frobenius norm with rank.

What You Learned

  • You learned to implement the singular value decomposition of a matrix using Python.
  • You used SVD as tool for trend analysis and dimensionality reduction.
  • You learned to use SVD as a primitive image compression scheme.

Comments

Popular posts from this blog

Functions in Python

Functions in Python Dr. Hari V S Department of Electronics and Communication College of Engineering Chengannur What You will Learn You will learn the syntax of Python functions You will learn to import the functions to other codes The Syntax The syntax used the keyword $def$ followed the name of the function again followed by a colon (:) that is then followed by an indented code block of instructions. The function def function_name(arg1.arg2,....argN): statements return results A Simple Python Function Needless to say that the statements and the return command should form an indented block. Consider a simple function that returns the sum of the input values. It is realized as the function below. def summ(x,y): return x+y Unlike MATLAB or IDL, it is possible to execute a function in the Python shell. You may type the above function in a Python shell or an enhanced Python shell such as IPython. Once the ...

Ex:2 Familiarization of Scientific Computing

Iterations and Conditions in Python

Dr. Hari V S Department of Electronics and Communication College of Engineering Chengannur What You Will Learn You will learn the syntax of for, while loops and if statement in Python You will apply these to solve a mathematical problem. For loop Python identifies code blocks by indentation. The for loop has the syntax shown below. Observe the colon at the end of the first line and the indentation at the start of the second line. Whatever is to happen under the for loop should be given as an indented block. If the indentation is wrong, it raises an exception. for i in range(0,10): print i The above code prints the integers from 0 to 9. One can modify the above code for appending the values to a blank array as shown in the following code. from scipy import * arr=[] for i in range(0,10): arr.append(i) print arr The loops being slow, the above method is not encouraged. Instead, vectorized computation is used as shown below. from scipy impor...