2013-08-18 25 views
7

Tôi cố gắng thực hiện phân tích thành phần chính đơn giản với matplotlib.mlab.PCA nhưng với các thuộc tính của lớp tôi không thể có được một giải pháp sạch cho vấn đề của mình. Dưới đây là một ví dụ:Ví dụ cơ bản cho PCA với matplotlib

Nhận được một số dữ liệu giả trong 2D và bắt đầu PCA:

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) 

Bây giờ, tôi chỉ muốn để có được các thành phần chính như vectơ trong tọa độ ban đầu của tôi và âm mưu chúng như mũi tên vào dữ liệu của tôi.

Cách nhanh chóng và sạch sẽ để đến đó là gì?

Cảm ơn, Tyrax

Trả lời

22

Tôi không nghĩ rằng lớp mlab.PCA là phù hợp với những gì bạn muốn làm. Đặc biệt, lớp PCA lại tỷ lệ chia dữ liệu trước khi tìm các vector riêng:

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

Phương pháp center chia bởi sigma:

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

Điều này dẫn đến vector riêng, pca.Wt, như thế này:

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

Chúng vuông góc, nhưng không liên quan trực tiếp đến các trục chính của dữ liệu ban đầu của bạn. Chúng là các trục chính đối với dữ liệu mát xa.

Có lẽ nó có thể được dễ dàng hơn để mã hóa những gì bạn muốn trực tiếp (không có việc sử dụng các lớp mlab.PCA):

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

lớn, cảm ơn. Đó là những gì tôi đang tìm kiếm. – Tyrax

+0

ý nghĩa của hằng số 1.618 là gì? nó đến từ đâu ? – joaquin

+1

@joaquin: Khoảng [tỷ lệ vàng] của nó (http://en.wikipedia.org/wiki/Golden_ratio). Bạn có thể, tất nhiên, chọn bất kỳ hằng số nào bạn thích, nhưng nó thường có vẻ tốt (http://en.wikipedia.org/wiki/Golden_ratio#Painting). – unutbu

Các vấn đề liên quan