2013-08-18 6 views
7

Ich versuche, eine einfache Hauptkomponentenanalyse mit Matplotlib.mlab.PCA zu tun, aber mit den Attributen der Klasse kann ich keine saubere Lösung für mein Problem bekommen. Hier ein Beispiel:Grundlegendes Beispiel für PCA mit Matplotlib

einige Dummy-Daten in 2D-Get und PCA starten:

from matplotlib.mlab import PCA 
import numpy as np 

N  = 1000 
xTrue = np.linspace(0,1000,N) 
yTrue = 3*xTrue 

xData = xTrue + np.random.normal(0, 100, N) 
yData = yTrue + np.random.normal(0, 100, N) 
xData = np.reshape(xData, (N, 1)) 
yData = np.reshape(yData, (N, 1)) 
data = np.hstack((xData, yData)) 
test2PCA = PCA(data) 

Nun, ich möchte nur die Hauptkomponenten als Vektoren erhalten in meiner ursprünglichen Koordinaten und zeichnen sie als Pfeile auf meine Daten.

Was ist eine schnelle und saubere Möglichkeit, dorthin zu gelangen?

Danke, Tyrax

Antwort

22

Ich glaube nicht die mlab.PCA Klasse ist angemessen für das, was Sie tun möchten. Insbesondere neu skaliert die PCA Klasse, um die Daten vor der Eigenvektoren zu finden:

a = self.center(a) 
U, s, Vh = np.linalg.svd(a, full_matrices=False) 

Die center Methode teilt durch sigma:

def center(self, x): 
    'center the data using the mean and sigma from training set a' 
    return (x - self.mu)/self.sigma 

Das in Eigenvektoren führt, pca.Wt, wie folgt aus:

[[-0.70710678 -0.70710678] 
[-0.70710678 0.70710678]] 

Sie sind senkrecht, aber nicht direkt relevant für die Hauptachsen Ihrer Originaldaten. Sie sind Hauptachsen in Bezug auf massierte Daten.

Vielleicht könnte es einfacher sein zu codieren, was Sie direkt möchten (ohne die Verwendung der mlab.PCA Klasse):

import numpy as np 
import matplotlib.pyplot as plt 

N = 1000 
xTrue = np.linspace(0, 1000, N) 
yTrue = 3 * xTrue 
xData = xTrue + np.random.normal(0, 100, N) 
yData = yTrue + np.random.normal(0, 100, N) 
xData = np.reshape(xData, (N, 1)) 
yData = np.reshape(yData, (N, 1)) 
data = np.hstack((xData, yData)) 

mu = data.mean(axis=0) 
data = data - mu 
# data = (data - mu)/data.std(axis=0) # Uncommenting this reproduces mlab.PCA results 
eigenvectors, eigenvalues, V = np.linalg.svd(data.T, full_matrices=False) 
projected_data = np.dot(data, eigenvectors) 
sigma = projected_data.std(axis=0).mean() 
print(eigenvectors) 

fig, ax = plt.subplots() 
ax.scatter(xData, yData) 
for axis in eigenvectors: 
    start, end = mu, mu + sigma * axis 
    ax.annotate(
     '', xy=end, xycoords='data', 
     xytext=start, textcoords='data', 
     arrowprops=dict(facecolor='red', width=2.0)) 
ax.set_aspect('equal') 
plt.show() 

enter image description here

+0

toll, danke. Das habe ich gesucht. – Tyrax

+0

was ist die Bedeutung der 1.618 Konstante? Woher kommt es ? – joaquin

+1

@joaquin: Es ist ungefähr das [goldene Verhältnis] (http://en.wikipedia.org/wiki/Golden_ratio). Sie können natürlich jede Konstante wählen, die Sie mögen, aber sie sieht oft gut aus (http://en.wikipedia.org/wiki/Golden_ratio#Painting). – unutbu