Principal Component Analysis(PCA, 주성분 분석)
-
주성분 분석은 차원축소를 위해 사용됨 -> 고차원의 데이터를 저차원의 데이터로 변환
- 목적
- 차원(dimension)을 감소시켜 해석을 용이하게 하고, 시각화에 도움
- 기대효과
- 통계 : 적은 수의 특성으로 특정 현상을 설명
- 머신러닝 : 모델 성능 강화
- 목적
-
개념
- 여러개의 양적 변수들 사이의 분선-공분산 관계를 이용하여, 변수들의 선형결합으로 표시되는 주성분을 찾음(축의 개념)
- 2-3개의 주성분으로 전체 분산(variance)의 대부분을 설명하고자 하는 다변량 분석법
- 원 데이터의 손실을 최소화하면서 데이터를 잘 설명할 수 있는 변수들의 선형 조합을 찾는 것이 목표
- 라면 데이터를 이용한 PCA()
import pandas as pd
import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
lamen = dict({'name':['쇠고기라면','해물라면','얼큰라면','떡라면','짬뽕라면','만두라면','치즈라면','된장라면','볶음라면','김치라면'],
'noodle':[2,1,5,2,3,4,4,1,3,5],
'bowl':[4,5,3,2,5,3,4,2,3,5],
'soup':[5,1,4,3,5,2,3,1,2,3]})
lamen
lamen1 = pd.DataFrame(lamen)
lamen1
- 데이터 프레임으로 변경하면 위와 같은 표가 나오게 된다. (면, 그릇, 국물에 대한 수치)
# 1. 데이터 분리
lamenEval = lamen1[['noodle','bowl','soup']]
lamenName = lamen1['name']
# 2. 스케일러로 값 변환
# scaling using StandardScaler
scaler = StandardScaler()
scaler.fit(lamenEval.values)
lamen_scaled = scaler.transform(lamenEval.values)
lamen_scaled.shape
# (10,3)
# 3. PCA 모델링
# - PCA.fit() : 주성분 찾음
# - PCA.transform() : 새로운 주성분으로 데이터 변환
# PCA modelling
from sklearn.decomposition import PCA
pca_lamen = PCA()
pca_lamen.fit(lamen_scaled)
# data transform
X_pca_lamen = pca_lamen.transform(lamen_scaled)
# look into data shape
print("original data : {}".format(str(lamen_scaled.shape)))
print("transform data : {}".format(str(X_pca_lamen.shape)))
# original data : (10, 3) transform data : (10, 3)
- 사이킷런에서 제공하는 PCA를 호출하여 적용을 시켰을 때 결과르 확인하면 전과 후의 데이터 형태가 같은 것을 확인할 수있다.
pca_lamen.components_
# output
array([[-0.571511 , -0.52211611, -0.63306393],
[-0.60447096, 0.78960694, -0.105526 ],
[-0.5549685 , -0.32235949, 0.76687308]])
- PCA 모델에 의해 산출된 값을 보면 --> pca_lamen.components_
- 첫 행부터 각 pc1, pc2, pc3 을 의미하며, 열은 각각 noodle, bowl, soup를 의미함
- 산출한 특성별 주성분 요소 값과 특성들의 평가 스코어를 이용하여, 역산을 해보고 PCA 모델링을 통해 변환된 최종 데이터와 일치하는지 확인해보세요
# PCA 1,2,3 에 대한 변환 스코어
pc1=0
pc2=0
pc3=0
for j in range(len(pca_lamen.components_)):
pc1 += pca_lamen.components_[0][j] * lamen_scaled[:,j] # 계수 3개에 있어서 스케일된 모든 열을 다 곱하고 더한 것 = pc1
pc2 += pca_lamen.components_[1][j] * lamen_scaled[:,j]
pc3 += pca_lamen.components_[2][j] * lamen_scaled[:,j]
pc1 = pc1.reshape(10,1)
pc2 = pc2.reshape(10,1)
pc3 = pc3.reshape(10,1)
np.round(np.hstack((pc1,pc2,pc3)),3) == np.round(X_pca_lamen,3)
- 결과가 모두 True로 pca_lamen.components_의 값들과 스케일링 된 lamen_scaled 데이터와 곱하고 더하면 PCA의 결과인 X_pca_lamen 과 데이터가 같은 것을 확인할 수 있다.
- 시각적으로 확인하고 싶을 때
def biplot2(score, coeff, label, pcax, pcay, labels = None):
pca1=pcax-1
pca2=pcay-1
ㅇ xs = score[:,pca1]
ys = score[:,pca2]
n=score.shape[1]
scalex = 1.0/(xs.max() - xs.min())
scaley = 1.0/(ys.max() - ys.min())
for i in range(len(xs)):
plt.scatter(xs[i]*scalex, ys[i]*scaley)
plt.annotate(label.iloc[i], xy=(xs[i]*scalex, ys[i]*scaley), ha='right')
for i in range(n):
plt.arrow(0, 0, coeff[i,pca1], coeff[i,pca2], color='r', alpha=1)
if labels is None:
plt.text(coeff[i,pca1]*1.15, coeff[i,pca2]*1.15, "Var"+str(i+1), color='g', ha = 'center', va='center')
else:
plt.text(coeff[i,pca1]*1.15, coeff[i,pca2]*1.15, labels[i], color='g', ha='center', va='center', size=15)
plt.xlim(-0.8, 0.75)
plt.ylim(-1,1)
plt.xlabel("PC{}".format(pcax))
plt.ylabel("PC{}".format(pcay))
plt.grid()
##한글 폰트 설정
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
font_path="C:\\Windows\\Fonts\\malgun.ttf"
font_name=fm.FontProperties(fname=font_path).get_name()
plt.rcParams['font.family']=font_name
%matplotlib inline
biplot2(X_pca_lamen, pca_lamen.components_, lamenName, 1,2,labels=lamenEval.columns)
- 그래프 해석
-
면과 국물의 축이 가까우므로, 둘 사이에 비교적 강한 양의 상관관계가 있다
-
그릇은 나머지 변수와 비교적 상관관계가 적다(같은 방향 : 약한 양의 상관관계)
-
얼큰라면은 나머지 변수에 비해 면에서 높은 점수를 받았다
-
짬뽕라면과 김치라면은 전체적으로 점수가 높을 것이며, 짬뽕라면은 그릇의 점수도 높을 것이다
-
해물라면은 면, 국물과 반대방향이므로 음의 상관관계가 있다. 반면, 그릇의 점수는 상당히 높을 것
-
된장라면은 그릇의 점수가 낮을 것이며, 면과 국물의 점수 역시 낮을 것이다.
-
볶음, 만두, 떡은 전체적으로 점수가 고르며, 큰 특성을 보이지 않을 것
'머신러닝 in Python' 카테고리의 다른 글
[Python] 비지도 학습 - 군집분석 (0) | 2019.09.04 |
---|---|
[Python] openCV 이용한 얼굴인식 (0) | 2019.09.03 |
[Python] Cross-validation + Grid Search (1) | 2019.08.30 |
[Python] Grid Search (0) | 2019.08.30 |
[Python] Cross-validation(교차검증) (1) | 2019.08.30 |