如何在python中绘制碎石图?[关闭]


11

我在矩阵上使用奇异矢量分解,并获得了U,S和Vt矩阵。在这一点上,我试图为保留的维数选择一个阈值。有人建议我看一下碎石图,但想知道如何用numpy绘制它。目前,我正在使用python中的numpy和scipy库执行以下操作:

U, S, Vt = svd(A)

有什么建议么?


1
取的对角线S,如果还不是对角线,则将其平方,以降序排序,取累加和,除以最后一个值,然后绘制。
shabbychef 2011年

@shabbychef:您的意思是,取累加和除以所有值的和,对吗?
传奇

是。在matlab中,它将是[U,S,V] = svd(X);S = cumsum(sort(diag(S).^2,1,'descend'));S = S ./ S(end);plot(S);
shabbychef 2011年

Answers:


13

这是一个示例,可以粘贴到IPython提示符并生成如下图像(它使用随机数据):

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

#Make a random array and then make it positive-definite
num_vars = 6
num_obs = 9
A = np.random.randn(num_obs, num_vars)
A = np.asmatrix(A.T) * np.asmatrix(A)
U, S, V = np.linalg.svd(A) 
eigvals = S**2 / np.sum(S**2)  # NOTE (@amoeba): These are not PCA eigenvalues. 
                               # This question is about SVD.

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()

在此处输入图片说明


赫尔曼:+1谢谢您的时间!我知道已经很长时间了,但是拥有它真的很好:)
Legend

是什么num_vars?它似乎没有在脚本中定义。
TheChymera 2014年

@TheChymera-感谢您抓住这个问题,我已经更新了回复。
2014年

@Josh Hemann是的,我也同时想出了这一点-但我认为从A的形状进行计算可能会更好
TheChymera 2014年

1
@JoshHemann您能解释一下:eigvals = S ** 2 / np.cumsum(S)[-1]?根据一些论文,我已经看到eigvals = S ** 2 / /(n-1),其中n是特征数
makis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.