Tell me more ×
Cross Validated is a question and answer site for statisticians, data analysts, data miners and data visualization experts. It's 100% free, no registration required.

I am using singular vector decomposition on a matrix and obtaining the U, S and Vt matrices. At this point, I am trying to choose a threshold for the number of dimensions to retain. I was suggested to look at a scree plot but am wondering how to go about plotting it in numpy. Currently, I am doing the following using numpy and scipy libraries in python:

U, S, Vt = svd(A)

Any suggestions?

share|improve this question
1  
take the diagonal of S, if it is not already a diagonal, square it, sort it in decreasing order, take the cumulative sum, divide by the last value, then plot it. – shabbychef Jul 9 '11 at 4:39
@shabbychef: You mean, take the cumulative sum and divide by the sum of all the values right? – Legend Jul 10 '11 at 1:24
yes. In matlab, it would be [U,S,V] = svd(X);S = cumsum(sort(diag(S).^2,1,'descend'));S = S ./ S(end);plot(S); – shabbychef Jul 10 '11 at 2:35

1 Answer

up vote 3 down vote accepted

Here is an example that can be pasted to an IPython prompt and generate an image like below (it uses random data):

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

#Make a random array and then make it positive-definite
A = A = np.random.randn(6, 9)
A = np.asmatrix(A) * np.asmatrix(A.T)
U, S, V = np.linalg.svd(A) 
eigvals = S**2 / np.cumsum(S)[-1]

fig = plt.figure(figsize=(8,5))
sing_vals = np.arange(num_vars) + 1
plt.plot(sing_vals, eigvals, 'ro-', linewidth=2)
plt.title('Scree Plot')
plt.xlabel('Principal Component')
plt.ylabel('Eigenvalue')
#I don't like the default legend so I typically make mine like below, e.g.
#with smaller fonts and a bit transparent so I do not cover up data, and make
#it moveable by the viewer in case upper-right is a bad place for it 
leg = plt.legend(['Eigenvalues from SVD'], loc='best', borderpad=0.3, 
                 shadow=False, prop=matplotlib.font_manager.FontProperties(size='small'),
                 markerscale=0.4)
leg.get_frame().set_alpha(0.4)
leg.draggable(state=True)
plt.show()

enter image description here

share|improve this answer
Hermann: +1 Thank You for your time! I know it's been a long time but nevertheless this is really good to have :) – Legend Oct 18 '11 at 19:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.