주성분 분석 (PCA, principal component analysis)란
차원축소와 변수추출 기법을 통해 전체 dataset(=독립변수)의 분산을 가장 잘 설명하는 성분을 말한다. 즉, 데이터 자원을 줄이고 중요한 정보를 추출하기 위해 사용되는 통계 기법이다. PCA는 다차원 dataset를 가장 중요한 변수(주성분)로 변환하여 데이터의 변동성을 최대한 보존하면서 아래 그림과 같이 차원을 축소한다.
분류(classification) 모델의 대표적인 dataset인 Iris 데이터와 Python 코드를 활용한 주성분 분석은 다음과 같다.
PCA결과 원본 dataset의 대부분의 정보를 2차원으로 축소하여 표현할 수 있으며, 이렇게 축소된 데이터는 시각화 및 분석에 활용 할 수 있다.
앞서 사용한 예는 분류(classification) 문제를 분석한 결과이다. 그렇다면 회기(Regression) 문제는 어떻게 접근하여 올바른 분석을 수행할지 생각해보자.
분류(classification) 모델의 대표적인 dataset인 Iris 데이터와 Python 코드를 활용한 주성분 분석은 다음과 같다.
1 2 3 4 5 6 7 | import pandas as pd import numpy as np # Fisher,R. A.. (1988). Iris. UCI Machine Learning Repository. https://doi.org/10.24432/C56C76. url = "https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv" # name = ['sepal length', 'sepal width', 'petal length', 'petal width', 'target'] df = pd.read_csv(url) print(df) |
주성분 분석을 하기 전에 데이터 스케일링을 하는 이유는 데이터의 스케일에 따라 주성분의 설명 가능한 분산량이 달라질 수 있기 때문에 표준화를 진행한다. 여기서 표준화란 각 변수에 평균을 빼주고 표준편차로 나눠준다.
사이킷런의 preprocessing 서브 패키지를 이용하면 아래와 같다. 데이터 스케일링을 위한 StandardScaler 클래스를 제공한다.
1 2 3 4 5 6 7 8 9 10 11 12 | # 표준화 스케일 패키지 from sklearn.preprocessing import StandardScaler # dataset x값(독립변수) y값(종속변수) 분리 x = df.drop(['species'], axis=1).values y = df['species'].values # dataset x에 표준화x 저장 x = StandardScaler().fit_transform(x) # dataframe 만들기 features = ['sepal length', 'sepal width', 'petal length', 'petal width'] pd.DataFrame(x, columns=features).head() |
pd.DataFrame(x, columns = features).head() =
사이킷런의 decomposition 서브 패키지는 PCA분석을 위한 PCA 클래스를 제공한다. 사용법은 아래와 같다.
| 표준화된 dataset |
주요 함수
- 입력 인수: n_components → 정수 값
- 매서드
- fit_transform() → 낮은 차원의 근사행렬로 변환
- inverse_transform() → 변한된 근사행렬을 원래의 차원으로 복귀
- 속성: mean_ → 평균 벡터
- components_ → 주성분 백터
- explained_veriance_ratio_ → 주성분별 분산 비율
1 2 3 4 5 6 7 | from sklearn.decomposition import PCA pca = PCA(n_components = 4) principal_component = pca.fit_transform(x) principal_name = ['PC1', 'PC2', 'PC3', 'PC4'] principal_df = pd.DataFrame(data = principal_component, columns = principal_name) print(pca.explained_variance_ratio_) |
전체에서 해당 주성분의 고유값이 차지하는 비율은 다음과 같고 바차트로 표현하면 아래와 같다. 사이킷런 decomposition 서브 패키지의 explained_veriance_ratio_ 함수를 이용하면 각각의 비율을 출력할 수 있다.
explained_veriance_ratio_ = [0.72770452 0.23030523 0.03683832 0.00515193]
각 주성분 고유값이 차지하는 비율의 상위 2개를 합산하면 약0.95이다. 다시말하면, 해당 그래프의 의미는 PC1 축이 전체 데이터 특징의 73% 정도를 나타내고 있으며, PC2 축이 전체 데이터 특징의 23% 정도를 나타내고 있다는 뜻이다. 즉, 주성분 1과 2만으로도 충분히 모델을 설명할 수 있음을 확인할 수 있다.
explained_veriance_ratio_ = [0.72770452 0.23030523 0.03683832 0.00515193]
각 주성분 고유값이 차지하는 비율의 상위 2개를 합산하면 약0.95이다. 다시말하면, 해당 그래프의 의미는 PC1 축이 전체 데이터 특징의 73% 정도를 나타내고 있으며, PC2 축이 전체 데이터 특징의 23% 정도를 나타내고 있다는 뜻이다. 즉, 주성분 1과 2만으로도 충분히 모델을 설명할 수 있음을 확인할 수 있다.
1 2 3 4 5 | import matplotlib.pyplot as plt pca_ratio_df = pd.DataFrame(pca.explained_variance_ratio_) pca_ratio_df.plot(kind='bar', logy=False, color='b') plt.ylabel('Percentate of Variance Explained') plt.xlabel('Principal Component') |
그렇다면 주성분 1과 2를 축으로하는 scatter plot을 확인해 각 species별 분산을 확인해보자. 여기서 사용할 패키지는 matplotlib.pyplot 사용이며, sctter함수를 사용하겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import matplotlib.pyplot as plt fig = plt.figure(figsize = (6, 6)) ax = fig.add_subplot(1, 1, 1) ax.set_xlabel('Principal Component 1', fontsize = 12) ax.set_ylabel('Principal Component 2', fontsize = 12) ax.set_title('component PCA', fontsize = 12) features = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width'] species = ['setosa', 'versicolor', 'virginica'] colors = ['r', 'b', 'g'] pca_df = pd.concat([principal_df, df[['species']]], axis = 1) for species, colors in zip(species, colors): add_data = pca_df['species'] == species ax.scatter(pca_df.loc[add_data, 'PC1'], pca_df.loc[add_data, 'PC2'], c = colors, s = 50) ax.legend(species, loc='lower right', labels = ['setosa', 'versicolor', 'virginica']) ax.grid() loadings = pca.components_.T * np.sqrt(pca.explained_variance_) for i, features in enumerate(features): plt.arrow(0, 0, loadings[i,0], loadings[i,1], color='k',alpha=0.5) plt.text(loadings[i,0]*1.5, loadings[i,1]*1.5, features, color='k', ha='center', va='center') |
앞서 사용한 예는 분류(classification) 문제를 분석한 결과이다. 그렇다면 회기(Regression) 문제는 어떻게 접근하여 올바른 분석을 수행할지 생각해보자.



댓글
댓글 쓰기