[데이터분석 필기] 차원 축소 - PCA, 주성분 분석 코드 (2)


저번에 공부한 PCA를 이번에는 파이썬 코드로 풀어보겠다.

예제 데이터셋 만들기

import numpy as np
np.random.seed(4)
m = 60
w1, w2 = 0.1, 0.3
noise = 0.1

angles = np.random.rand(m) * 3 * np.pi / 2 - 0.5
X = np.empty((m, 3))
X[:, 0] = np.cos(angles) + np.sin(angles)/2 + noise * np.random.randn(m) / 2
X[:, 1] = np.sin(angles) * 0.7 + noise * np.random.randn(m) / 2
X[:, 2] = X[:, 0] * w1 + X[:, 1] * w2 + noise * np.random.randn(m)

print('X.shape:', X.shape)
X.shape: (60, 3)

1) eigen-decomposition을 이용한 PCA 구하기

X_cen = X - X.mean(axis=0)  # 평균을 0으로
X_cov = np.dot(X_cen.T, X_cen) / 59
print(X_cov)
[[ 0.69812855  0.17640539  0.12137931]
 [ 0.17640539  0.1801727   0.07253614]
 [ 0.12137931  0.07253614  0.04552382]]

위에서 구한 공분산 행렬 X_cov에 대해 np.linalg.eig를 이용해 eigenvalue(w)와 eigenvector(v)를 구함

w, v = np.linalg.eig(X_cov)

print('eigenvalue :', w)
print('eigenvector :\n', v)
eigenvalue : [ 0.77830975  0.1351726   0.01034272]
eigenvector :
 [[ 0.93636116  0.34027485 -0.08626012]
 [ 0.29854881 -0.90119108 -0.31420255]
 [ 0.18465208 -0.2684542   0.94542898]]
('explained variance ratio :', w / w.sum())
('explained variance ratio :', array([ 0.84248607,  0.14631839,  0.01119554]))

2) Scikit-Learn을 이용한 PCA 구하기

from sklearn.decomposition import PCA

pca = PCA(n_components=3)
pca.fit(X)
PCA(copy=True, iterated_power='auto', n_components=3, random_state=None,
  svd_solver='auto', tol=0.0, whiten=False)
print('singular value :', pca.singular_values_)
print('singular vector :\n', pca.components_.T)
singular value : [ 6.77645005  2.82403671  0.78116597]
singular vector :
 [[-0.93636116  0.34027485 -0.08626012]
 [-0.29854881 -0.90119108 -0.31420255]
 [-0.18465208 -0.2684542   0.94542898]]
print('eigen_value :', pca.explained_variance_)
print('explained variance ratio :', pca.explained_variance_ratio_)
eigen_value : [ 0.77830975  0.1351726   0.01034272]
explained variance ratio : [ 0.84248607  0.14631839  0.01119554]

2-1) Explained Variance Ratio 와 적절한 차원 수 선택하기

# PC1에 projection
pc1 = v[:, 0]
proj1 = np.dot(X, pc1)

# PC2에 projection
pc2 = v[:, 1]
proj2 = np.dot(X, pc2)

# PC3에 projection
pc3 = v[:, 2]
proj3 = np.dot(X, pc3)

proj_list = np.array([proj1.var(), proj2.var(), proj3.var()])

print('variance(==eigenvalue) :', proj_list)
print('explained variance ratio :', proj_list / proj_list.sum())
variance(==eigenvalue) : [ 0.76533792  0.13291972  0.01017034]
explained variance ratio : [ 0.84248607  0.14631839  0.01119554]
# 한줄로 가능
print('explained variance ratio :', pca.explained_variance_ratio_)
explained variance ratio : [ 0.84248607  0.14631839  0.01119554]

위의 결과의 의미는 원 데이터셋 분산의 84.2%가 첫 번째 주성분 축에 놓여 있고, 14.6%가 두 번째 주성분 축에 놓여 있다는 것을 말한다. 그리고 세 번째 주성분 축에는 1.1% 정도로 매우 적은 양의 정보가 들어 있다는 것을 알 수 있다.

따라서, 첫 번째 주성분과 두 번째 주성분을 이용해 3차원의 데이터셋 X를 2차원으로 투영할 경우, 원래 데이터셋의 분산에서 1.1%를 잃게 된다.

2-2) 적절한 차원 수 선택하기

cumsum = np.cumsum(pca.explained_variance_ratio_)
d = np.argmax(cumsum >= 0.95) + 1
print('선택할 차원 수 :', d)
선택할 차원 수 : 2
pca = PCA(n_components=0.95)
X_proj = pca.fit_transform(X)

print('principal component vec :\n', pca.components_.T)
principal component vec :
 [[-0.93636116  0.34027485]
 [-0.29854881 -0.90119108]
 [-0.18465208 -0.2684542 ]]





© 2018. by statssy

Powered by statssy