Phân tích thành phần chính và hồi quy trong Python


11

Tôi đang cố gắng tìm ra cách tái tạo trong Python một số công việc tôi đã thực hiện ở SAS. Sử dụng bộ dữ liệu này , trong đó vấn đề đa cộng đồng là một vấn đề, tôi muốn thực hiện phân tích thành phần chính trong Python. Tôi đã xem xét scikit-learn và statsmodels, nhưng tôi không chắc chắn làm thế nào để lấy đầu ra của chúng và chuyển đổi nó sang cấu trúc kết quả giống như SAS. Đối với một điều, SAS dường như thực hiện PCA trên ma trận tương quan khi bạn sử dụng PROC PRINCOMP, nhưng hầu hết (tất cả?) Các thư viện Python dường như sử dụng SVD.

Trong tập dữ liệu , cột đầu tiên là biến trả lời và 5 cột tiếp theo là các biến dự đoán, được gọi là pre1-pre5.

Trong SAS, quy trình làm việc chung là:

/* Get the PCs */
proc princomp data=indata out=pcdata;
    var pred1 pred2 pred3 pred4 pred5;
run;

/* Standardize the response variable */
proc standard data=pcdata mean=0 std=1 out=pcdata2;
    var response;
run;

/* Compare some models */
proc reg data=pcdata2;
    Reg:     model response = pred1 pred2 pred3 pred4 pred5 / vif;
    PCa:     model response = prin1-prin5 / vif;
    PCfinal: model response = prin1 prin2 / vif;
run;
quit;

/* Use Proc PLS to to PCR Replacement - dropping pred5 */
/* This gets me my parameter estimates for the original data */
proc pls data=indata method=pcr nfac=2;
    model response = pred1 pred2 pred3 pred4 / solution;
run;
quit;

Tôi biết rằng bước cuối cùng chỉ hoạt động vì tôi chỉ chọn PC1 và PC2 theo thứ tự.

Vì vậy, trong Python, đây là khoảng cách mà tôi đã nhận được:

import pandas as pd
import numpy  as np
from sklearn.decomposition.pca import PCA

source = pd.read_csv('C:/sourcedata.csv')

# Create a pandas DataFrame object
frame = pd.DataFrame(source)

# Make sure we are working with the proper data -- drop the response variable
cols = [col for col in frame.columns if col not in ['response']]
frame2 = frame[cols]

pca = PCA(n_components=5)
pca.fit(frame2)

Số lượng phương sai mà mỗi PC giải thích?

print pca.explained_variance_ratio_

Out[190]:
array([  9.99997603e-01,   2.01265023e-06,   2.70712663e-07,
         1.11512302e-07,   2.40310191e-09])

Cái gì đây? Eigenvector?

print pca.components_

Out[179]:
array([[ -4.32840645e-04,  -7.18123771e-04,  -9.99989955e-01,
         -4.40303223e-03,  -2.46115129e-05],
       [  1.00991662e-01,   8.75383248e-02,  -4.46418880e-03,
          9.89353169e-01,   5.74291257e-02],
       [ -1.04223303e-02,   9.96159390e-01,  -3.28435046e-04,
         -8.68305757e-02,  -4.26467920e-03],
       [ -7.04377522e-03,   7.60168675e-04,  -2.30933755e-04,
          5.85966587e-02,  -9.98256573e-01],
       [ -9.94807648e-01,  -1.55477793e-03,  -1.30274879e-05,
          1.00934650e-01,   1.29430210e-02]])

Đây có phải là giá trị riêng?

print pca.explained_variance_

Out[180]:
array([  8.07640319e+09,   1.62550137e+04,   2.18638986e+03,
         9.00620474e+02,   1.94084664e+01])

Tôi có một chút mất mát về cách lấy từ kết quả Python để thực sự thực hiện hồi quy thành phần chính (trong Python). Có bất kỳ thư viện Python nào điền vào chỗ trống tương tự như SAS không?

Bất kỳ lời khuyên được đánh giá cao. Tôi hơi hư hỏng khi sử dụng nhãn trong đầu ra của SAS và tôi không rành lắm về gấu trúc, numpy, scipy hoặc scikit-learn.


Biên tập:

Vì vậy, có vẻ như sklearn sẽ không hoạt động trực tiếp trên khung dữ liệu gấu trúc. Hãy nói rằng tôi chuyển đổi nó thành một mảng numpy:

npa = frame2.values
npa

Đây là những gì tôi nhận được:

Out[52]:
array([[  8.45300000e+01,   4.20730000e+02,   1.99443000e+05,
          7.94000000e+02,   1.21100000e+02],
       [  2.12500000e+01,   2.73810000e+02,   4.31180000e+04,
          1.69000000e+02,   6.28500000e+01],
       [  3.38200000e+01,   3.73870000e+02,   7.07290000e+04,
          2.79000000e+02,   3.53600000e+01],
       ..., 
       [  4.71400000e+01,   3.55890000e+02,   1.02597000e+05,
          4.07000000e+02,   3.25200000e+01],
       [  1.40100000e+01,   3.04970000e+02,   2.56270000e+04,
          9.90000000e+01,   7.32200000e+01],
       [  3.85300000e+01,   3.73230000e+02,   8.02200000e+04,
          3.17000000e+02,   4.32300000e+01]])

Nếu sau đó tôi thay đổi copytham số PCA của sklearn để False,nó hoạt động trực tiếp trên mảng, theo nhận xét bên dưới.

pca = PCA(n_components=5,copy=False)
pca.fit(npa)

npa

Trên mỗi đầu ra, có vẻ như nó đã thay thế tất cả các giá trị npathay vì nối thêm bất cứ thứ gì vào mảng. Các giá trị trong npabây giờ là gì? Điểm thành phần chính cho mảng ban đầu?

Out[64]:
array([[  3.91846649e+01,   5.32456568e+01,   1.03614689e+05,
          4.06726542e+02,   6.59830027e+01],
       [ -2.40953351e+01,  -9.36743432e+01,  -5.27103110e+04,
         -2.18273458e+02,   7.73300268e+00],
       [ -1.15253351e+01,   6.38565684e+00,  -2.50993110e+04,
         -1.08273458e+02,  -1.97569973e+01],
       ..., 
       [  1.79466488e+00,  -1.15943432e+01,   6.76868901e+03,
          1.97265416e+01,  -2.25969973e+01],
       [ -3.13353351e+01,  -6.25143432e+01,  -7.02013110e+04,
         -2.88273458e+02,   1.81030027e+01],
       [ -6.81533512e+00,   5.74565684e+00,  -1.56083110e+04,
         -7.02734584e+01,  -1.18869973e+01]])

1
Trong scikit-learn, mỗi mẫu được lưu dưới dạng một hàng trong ma trận dữ liệu của bạn. Lớp PCA hoạt động trực tiếp trên ma trận dữ liệu, nghĩa là nó sẽ tính toán ma trận hiệp phương sai , và sau đó là các hàm riêng của nó. Về 3 câu hỏi cuối cùng của bạn, vâng, các thành phần_ là các hàm riêng của ma trận hiệp phương sai, được giải thích là phương sai mà mỗi PC giải thích và phương sai được giải thích phải tương ứng với các giá trị riêng.
hóa học ánh sáng

@lightalchemist Cảm ơn bạn đã làm rõ. Với sklearn, có đúng không khi tạo một khung dữ liệu mới trước khi thực hiện PCA, hoặc có thể gửi trong khung dữ liệu gấu trúc 'hoàn chỉnh' và nó không hoạt động trên cột ngoài cùng (phản hồi)?
Đất sét

Tôi đã thêm một chút thông tin. Nếu tôi chuyển đổi thành một mảng numpy trước và sau đó chạy PCA copy=False, tôi sẽ nhận được các giá trị mới. Là những điểm thành phần chính?
Đất sét

Tôi không quen thuộc với Pandas vì vậy tôi không có câu trả lời cho phần câu hỏi của bạn. Về phần thứ hai, tôi không nghĩ chúng là thành phần chính. Tôi tin rằng chúng là các mẫu dữ liệu gốc nhưng có nghĩa là bị trừ. Tuy nhiên, tôi không thể thực sự chắc chắn về nó.
hóa học ánh sáng

Câu trả lời:


15

Scikit-learn không có triển khai kết hợp PCA và hồi quy như ví dụ gói xin vui lòng trong R. Nhưng tôi nghĩ người ta có thể làm như dưới đây hoặc chọn hồi quy PLS.

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

from sklearn.preprocessing import scale
from sklearn.decomposition import PCA
from sklearn import cross_validation
from sklearn.linear_model import LinearRegression

%matplotlib inline

import seaborn as sns
sns.set_style('darkgrid')

df = pd.read_csv('multicollinearity.csv')
X = df.iloc[:,1:6]
y = df.response

Scikit-học PCA

pca = PCA()

Chia tỷ lệ và chuyển đổi dữ liệu để có được Thành phần chính

X_reduced = pca.fit_transform(scale(X))

Phương sai (% tích lũy) được giải thích bởi các thành phần chính

np.cumsum(np.round(pca.explained_variance_ratio_, decimals=4)*100)

array([  73.39,   93.1 ,   98.63,   99.89,  100.  ])

Có vẻ như hai thành phần đầu tiên thực sự giải thích hầu hết các phương sai trong dữ liệu.

CV gấp 10 lần, có xáo trộn

n = len(X_reduced)
kf_10 = cross_validation.KFold(n, n_folds=10, shuffle=True, random_state=2)

regr = LinearRegression()
mse = []

Làm một CV để nhận MSE chỉ cho việc chặn (không có thành phần chính nào trong hồi quy)

score = -1*cross_validation.cross_val_score(regr, np.ones((n,1)), y.ravel(), cv=kf_10, scoring='mean_squared_error').mean()    
mse.append(score) 

Làm CV cho 5 thành phần nguyên tắc, thêm một thành phần vào hồi quy tại thời điểm đó

for i in np.arange(1,6):
    score = -1*cross_validation.cross_val_score(regr, X_reduced[:,:i], y.ravel(), cv=kf_10, scoring='mean_squared_error').mean()
    mse.append(score)

fig, (ax1, ax2) = plt.subplots(1,2, figsize=(12,5))
ax1.plot(mse, '-v')
ax2.plot([1,2,3,4,5], mse[1:6], '-v')
ax2.set_title('Intercept excluded from plot')

for ax in fig.axes:
    ax.set_xlabel('Number of principal components in regression')
    ax.set_ylabel('MSE')
    ax.set_xlim((-0.2,5.2))

nhập mô tả hình ảnh ở đây

Scikit-learn PLS hồi quy

mse = []

kf_10 = cross_validation.KFold(n, n_folds=10, shuffle=True, random_state=2)

for i in np.arange(1, 6):
    pls = PLSRegression(n_components=i, scale=False)
    pls.fit(scale(X_reduced),y)
    score = cross_validation.cross_val_score(pls, X_reduced, y, cv=kf_10, scoring='mean_squared_error').mean()
    mse.append(-score)

plt.plot(np.arange(1, 6), np.array(mse), '-v')
plt.xlabel('Number of principal components in PLS regression')
plt.ylabel('MSE')
plt.xlim((-0.2, 5.2))

nhập mô tả hình ảnh ở đây


7

Đây chỉ là SVD trong Python và NumPy (năm sau).
(Điều này không giải quyết các câu hỏi của bạn về SSA / sklearn / gấu trúc, nhưng có thể giúp một con trăn một ngày nào đó.)

#!/usr/bin/env python2
""" SVD straight up """
# geometry: see http://www.ams.org/samplings/feature-column/fcarc-svd

from __future__ import division
import sys
import numpy as np

__version__ = "2015-06-15 jun  denis-bz-py t-online de"

# from bz.etc import numpyutil as nu
def ints( x ):
    return np.round(x).astype(int)  # NaN Inf -> - maxint

def quantiles( x ):
    return "quantiles %s" % ints( np.percentile( x, [0, 25, 50, 75, 100] ))


#...........................................................................
csvin = "ccheaton-multicollinearity.csv"  # https://gist.github.com/ccheaton/8393329
plot = 0

    # to change these vars in sh or ipython, run this.py  csvin=\"...\"  plot=1  ...
for arg in sys.argv[1:]:
    exec( arg )

np.set_printoptions( threshold=10, edgeitems=10, linewidth=120,
    formatter = dict( float = lambda x: "%.2g" % x ))  # float arrays %.2g

#...........................................................................
yX = np.loadtxt( csvin, delimiter="," )
y = yX[:,0]
X = yX[:,1:]
print "read %s" % csvin
print "y %d  %s" % (len(y), quantiles(y))
print "X %s  %s" % (X.shape, quantiles(X))
print ""

#...........................................................................
U, sing, Vt = np.linalg.svd( X, full_matrices=False )
#...........................................................................

print "SVD: %s -> U %s . sing diagonal . Vt %s" % (
        X.shape, U.shape, Vt.shape )
print "singular values:", ints( sing )
    # % variance (sigma^2) explained != % sigma explained, e.g. 10 1 1 1 1

var = sing**2
var *= 100 / var.sum()
print "% variance ~ sing^2:", var

print "Vt, the right singular vectors  * 100:\n", ints( Vt * 100 )
    # multicollinear: near +- 100 in each row / col

yU = y.dot( U )
yU *= 100 / yU.sum()
print "y ~ these percentages of U, the left singular vectors:", yU


-> đăng nhập

# from: test-pca.py
# run: 15 Jun 2015 16:45  in ~bz/py/etc/data/etc  Denis-iMac 10.8.3
# versions: numpy 1.9.2  scipy 0.15.1   python 2.7.6   mac 10.8.3

read ccheaton-multicollinearity.csv
y 373  quantiles [  2823  60336  96392 147324 928560]
X (373, 5)  quantiles [     7     47    247    573 512055]

SVD: (373, 5) -> U (373, 5) . sing diagonal . Vt (5, 5)
singular values: [2537297    4132    2462     592      87]
% variance ~ sing^2: [1e+02 0.00027 9.4e-05 5.4e-06 1.2e-07]
Vt, the right singular vectors  * 100:
[[  0   0 100   0   0]
 [  1  98   0 -12  17]
 [-10 -11   0 -99  -6]
 [  1 -17   0  -4  98]
 [-99   2   0  10   2]]
y ~ these percentages of U, the left singular vectors: [1e+02 15 -18 0.88 -0.57]

Tôi đến bữa tiệc hơi muộn nhưng câu trả lời tuyệt vời
plumbus_bouquet

3

Hãy thử sử dụng một đường ống để kết hợp phân tích thành phần nguyên tắc và hồi quy tuyến tính:

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline

# Principle components regression
steps = [
    ('scale', StandardScaler()),
    ('pca', PCA()),
    ('estimator', LinearRegression())
]
pipe = Pipeline(steps)
pca = pipe.set_params(pca__n_components=3)
pca.fit(X, y)

3

Câu trả lời của tôi đã đến gần năm năm và có một cơ hội tốt là bạn không cần trợ giúp về việc thực hiện PCR trong Python nữa. Chúng tôi đã phát triển một gói Python có tên hoggorm thực hiện chính xác những gì bạn cần trước đó. Xin hãy xem các ví dụ PCR ở đây . Ngoài ra còn có một gói âm mưu bổ sung có tên hoggormplot để trực quan hóa các kết quả được tính toán với hoggorm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.