OkBublewrap

주성분분석(PCA) 본문

Python/학습용

주성분분석(PCA)

옥뽁뽁 2022. 12. 6. 00:20

개요

차원 축소 : feature 변수가 매우 많은 다차원 데이터 세트의 차원을 축소해서 새로운 차원의 데이터 세트를 만들기

 

 차원 축소의 알고리즘에는 PCA, LDA, SVD, NMF이 있다. 피처가 많을 수록 개별 피처 간에 상관관계가 높을 가능성이 크다. 이는 다중 공선성 문제로 모델의 예측 성능이 저하가 된다.

 차원 축소에는 피처 선택, 피처 추출로 나눌 수 있다. 피처 선택은 데이터 특징을 나타내는 변수만 선택하는 것이다. 피처 추출은 저차원으로 중요피처로 압축해서 추출하는 것이다. 차원축소를 자주 쓰는 곳은 이미지를 함축적 형태의 이미지 변환, 압축을 수행하거나, 텍스트 문서의 숨겨진 의미 추출하는데 사용이 된다.

 

# iris data
from sklearn.datasets import load_iris
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

iris = load_iris()
columns = ['sepal_length','sepal_width','petal_length','petal_width']
irisDF = pd.DataFrame(iris.data, columns = columns)

# 공분산
irisDF.cov()

# target 공분산
irisDF['target'] = iris.target
irisDF.cov()

# target 상관계수
irisDF.corr()

irisDF.cov()
target포함한 cov
irisDF.corr()

# sepal_length, petal_length scatter plot
plt.scatter(irisDF['sepal_length'], irisDF['petal_length'])
plt.xlabel('sepal_length')
plt.ylabel('petal_length')
plt.show()

petal_length, sepal_length의 그래프를 보면 양의 상관관계가 있는 것으로 보인다. 상관계수를 확인 했을 때, 0.87으로 나왔다. 그외 설명변수간의  상관계수들의 강한 양의 상관관계가 있는 것을 확인할 수 있다. petel_length, sepal_length의 공분산은 1.27이다. 양의 관계를 확인 할 수 있다.

 

sns.pairplot(data = irisDF, hue = 'target', height = 1.5)
plt.show()

다음은 iris분류별 설명변수들 간의 분포를 시각화 한 것이다. iris데이터를 분류하는데 특징을 가진 변수들이 무엇을까?

irisDF.groupby('target').agg(['mean', 'std'])

# 랜덤포레스트로 변수중요도 보기
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

X_data = irisDF[irisDF.drop(['target'],axis=1).columns]
y_data = irisDF[['target']]

#정규화
ss = StandardScaler()
X_scaled = ss.fit_transform(X_data)
x_train, x_test, y_train, y_test = train_test_split(X_scaled, y_data, test_size=0.3,shuffle=True)

# 학습 진행
forest = RandomForestClassifier()
forest.fit(x_train, y_train)

# 변수중요도
forest.feature_importances_

변수중요도는 0.09774794, 0.0318080848, 0.4249855, 0.44545807 이렇게 나왔다.

petal_legnth, petal_width가 상대적으로 중요하다고 나왔다. 그에 반해 sepal_legnth, sepal_width은 상대적으로 중요도가 떨어졌다. 이 두변수로 3가지 품종을 분류하는데 특징을 지을수 있지 않을까??

 

# pca 2개의 주성분
from sklearn.decomposition import PCA
pca = PCA(n_components = 2)

iris_pca = pca.fit_transform(iris_scaled)

print(pca.explained_variance_)
# array([2.93808505, 0.9201649 ])
print(pca.explained_variance_ratio_)
# array([0.72962445, 0.22850762])

누적 기여율을 보면 0.73 + 0.23 = 약 0.96으로 데이터의 96%을 설명 할 수 있다. 이거는 irisDF에서 나오는 변수가 아니다. 4가지 변수들을 압축해서 만든 새로운 변수 pca1, pca2으로 새로운 데이터 프레임을 생성한 것이다.

# pca 시각화
iris_pca_df = pd.DataFrame(iris_pca, columns = ['pca1', 'pca2'])
iris_pca_df2 = pd.concat([iris_pca_df, irisDF['target']], axis = 1)
sns.scatterplot(data = iris_pca_df2, x = 'pca1', y= 'pca2', hue = 'target');

2개로 줄었을 때 target 0은 잘 나눠지는 것을 볼 수 있다. 하지만 1,2는 분류하기가 어려워보인다.

 

'Python > 학습용' 카테고리의 다른 글

군집화(Clustering)(1)  (0) 2022.12.10
LDA(선형판별분석)  (1) 2022.12.06
로지스틱 회귀분석  (0) 2022.12.04
회귀분석(4)  (0) 2022.11.21
회귀분석(3)  (0) 2022.11.21