Wie zeichnet man einen Geröllplot in Python? [geschlossen]

11

Ich verwende eine singuläre Vektorzerlegung auf einer Matrix und erhalte die U-, S- und Vt-Matrizen. An dieser Stelle versuche ich, einen Schwellenwert für die Anzahl der beizubehaltenden Dimensionen auszuwählen. Mir wurde vorgeschlagen, mir ein Geröllplot anzusehen, aber ich frage mich, wie ich es in Numpy planen soll. Derzeit mache ich Folgendes mit numpy und scipy Bibliotheken in Python:

U, S, Vt = svd(A)

Irgendwelche Vorschläge?

Legende
quelle
1
Nehmen Sie die Diagonale von S, wenn es noch keine Diagonale ist, quadrieren Sie sie, sortieren Sie sie in absteigender Reihenfolge, nehmen Sie die kumulative Summe, dividieren Sie durch den letzten Wert und zeichnen Sie sie dann auf.
Shabbychef
@shabbychef: Du meinst, nimm die kumulative Summe und dividiere durch die Summe aller Werte, oder?
Legende
Ja. In Matlab wäre es[U,S,V] = svd(X);S = cumsum(sort(diag(S).^2,1,'descend'));S = S ./ S(end);plot(S);
Shabbychef

Antworten:

13

Hier ist ein Beispiel, das in eine IPython-Eingabeaufforderung eingefügt werden kann und ein Bild wie unten generiert (es werden zufällige Daten verwendet):

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

Geben Sie hier die Bildbeschreibung ein

Josh Hemann
quelle
Hermann: +1 Danke für deine Zeit! Ich weiß, es ist lange her, aber trotzdem ist das wirklich gut zu haben :)
Legende
was ist num_vars? Es scheint nicht in Ihrem Skript definiert zu sein.
TheChymera
@TheChymera - Danke, dass du das verstanden hast. Ich habe meine Antwort aktualisiert.
Josh Hemann
@ Josh Hemann Ja, ich habe das auch in der Zwischenzeit herausgefunden - aber ich denke, es ist vielleicht besser, es aus der Form von A zu berechnen
TheChymera
1
@JoshHemann kannst du das erklären: eigvals = S ** 2 / np.cumsum (S) [- 1] ?? Ich habe basierend auf einigen Papieren eigvals = S ** 2 / (n-1) gesehen, wobei n die Anzahl der Merkmale ist
makis