PCA(Principal Conponents Analysis)란
차원을 축소 즉 변수(feature)들의 갯수를 함축시키는 방법이다.
예를 들면 국어 성적과 영어성적을 합쳐서 문과적능력으로 합치는 것과 같다.
국어 , 영어 성적 ( 2차원) --> 문과적능력(1차원)으로 차원을 축소시킨다.
차원축소는 언제 사용하는가?
- Visualization - 시각화
3차원 이하의 데이터로 만들어 차트로 보여줘 데이터의 이해를 돕는다. - reduce noise - 이미지의 노이즈 감소
- preserve useful info in low memory - 메모리 절약
- less time complexity - 시간절약
- less space complexity - 공간절약
차원축소법(PCA)
2차원 공간상의 점을 1차원으로 줄인다고 가정할 때.
첫 번째 방법은 하나의 축(X1)으로 몰아넣는다.
이렇게 될 경우 위의 그림과 같이 정보가 겹치게되서 유실이된다.
X2 축으로 데이터를 몰아넣을 경우에도 X1보다는 덜하지만 겹치는 부분이 있어 이 역시도 정보가 유실된다.
그렇다면!
유실을 줄이는 가장 좋은 방법은 무엇일까?
좀 더 과학적인 방법은 분산이 가장 넓은 지역을 찾는 것이다.
분산이 가장 넓은 하나의 축에다가 점들을 놓으면 퍼져있는 정도를 지켜줌으로써
점들이 서로 최대한 겹치지않고 모이게 된다.
이것이 바로 PCA 알고리즘이다.
그럼 축 PC(Principal Component)를 어떻게 그었을까?
점들이 어떻게 가장 잘 퍼져있는 정도(분산)을 계산해가지고 가장 살릴 수 있는 방향으로 축을 긋는다.
PC(Principla Component)는 수학적으로 접근했을 때
PC = Eigen Vector from Covariance Matrix
점들이 갖고 있는 변수(feature)들의 공분산행렬(Covariance Matrix)의 고유벡터(Eigen Vector)이다.
그럼 공분산행렬(covariance matrix)이란 무엇일까?
데이터 구조적 의미 : 각 feature의 변동이 얼마나 닮았나
행렬에서 열들의 합이 0이라고 가정한다.
열들의 합이 0 이라는 뜻은 feature들의 데이터값의 평균을 뺀 상태
키의 평균이 170이라고 할때 180인 사람의 값은 10이고 160인 사람은 -10이다.
그래서 결국 열을 다 더하게 되면 0이됨.
변동의 닮은 정도를 보기위해선 내적이 필요하게 되고 그 과정은 위의 식처럼 행렬의 곱으로 표현가능하다.
행렬의 곱을하게되면
이런식으로 분산 dot(X1,X1)과 공분산 dot(X1,X2) 의 모양이 나타나게 된다. ( 완전한 모양은 아님 )
위의 행렬은 symmetric matrix로 대칭행렬이다. dot(X1,X2)와 dot(X2,X1)의 값이 같다.
위의 식 (XTX)ij 는 i번째 feature와 j 번째 feature의 변동이 닮은 정도를 말해주고 있다.
하지만 sample의 수(n)가 많아질 수록 위의 값은 커지고 이 문제를 방지해주기 위해 값은 n으로 나눠주면
공분산행렬의 값을 얻을 수 있다.
*행렬의 곱은 곱해서 더해주는 형식임으로 샘플이 많아지면 + 횟수가 증가하게 되어 값은 커지게된다.
공분산 행렬의 수학적 의미 : 선형 변환 (shearing)
선형 변환을 하기전에 데이터 분포
데이터셋을 공분산 행렬로 변환하게 되면 위의 분포처럼 선형의 모양으로 변경된다.
PCA 알고리즘은 데이터의 구조를 잘 살려주면서 차원 감소를 할 수 있게끔 하는 방법이다.
2차원 평면 상의 산점도를 1차원에 정사영시켜 차원을 감소시켜준다고 하면
어떤 벡터에 정사영 시키는 것이 가장 좋을까?
정사영이란?
n차원의 데이터를 줄이면서 한 축으로 데이터를 옮기는 과정
variance(퍼진정도)가 크면 클수록 데이터 유실이 적게되고 좋은 벡터(설명력이 뛰어난)라고 볼 수 있다.
공분산 행렬을 통해 선형변환 할 때의 주축(PC)에 대해 정사영 하는 것이 제일 좋다.
이 과정에서 PC를 구하는 방법을 찾게 되고 PC를 찾는 과정에서 Eigen Vector와 Eigen Value가 등장한다.
Eigen Vector는 선형변환의 주축이라고 불린다.
즉, 선형변환을 했을 때 크기만 바뀌고 방향은 바뀌지 않는 벡터를 의미한다.
EigenVector의 정사영해야 variance가 가장 큰 결과를 얻을 수 있다.
고유벡터(Eigen Vector)는 2차원이면 2개 , n차원에서는 n개를 가지고 있다.
2차원 공간에서는 2개의 Eigen Vactor가 존재하고 그 중 가장 넓게 퍼져있는
하나의 Eigen Vactor를 선택해야하는데 선택의 기준은 Eigen Value(고유값)을 통해서 선택한다.
Eigen Value 가 높으면 가장 넓게 퍼져있다는 뜻이다.
Eigen Value를 기준으로 Eigen Vactor를 선택을해서 점들을 선택한 Eigen Vactor로 옮겨주는 것이 바로 PCA 이다!!!
자 그럼 실습을 해보자!!
Python - Code
import pandas as pd
#데이터 프레임 생성
df = pd.DataFrame(columns=['calory','breakfast','lunch','dinner','exercise','body_shape'])
#데이터 셋
df.loc[0] = [1200,1,0,0,2,'Skinny']
df.loc[1] = [2800,1,1,1,1,'Normal']
df.loc[2] = [3500,2,2,1,0,'Fat']
df.loc[3] = [1400,0,1,0,3,'Skinny']
df.loc[4] = [5000,2,2,2,0,'Fat']
df.loc[5] = [1300,0,0,1,2,'Skinny']
df.loc[6] = [3000,1,0,1,1,'Normal']
df.loc[7] = [4000,2,2,2,0,'Fat']
df.loc[8] = [2600,0,2,0,0,'Normal']
df.loc[9] = [3000,1,2,1,1,'Fat']
print(df.head(10))
cs |
x = df[['calory','breakfast','lunch','dinner','exercise']]
print(x.head(10))
y = df[['body_shape']]
print(y.head(10))
cs |
X (독립변수)와 Y(종속변수) 분리
from sklearn.preprocessing import StandardScaler
xStd = StandardScaler().fit_transform(x)
print(xStd)
cs |
여기서 calory data가 나머지 값들에 비해 크기때문에 비슷한 크기로 변환해줘야한다.
비슷한 크기로 변환해주는 함수가 StandardScaler() 함수이다.
값들이 비슷한 값으로 전부 바뀐다.
import numpy as np
features = xStd.T
convarianceMatrix = np.cov(features)
print(convarianceMatrix)
|
여기서 스탠다드한 행렬을 트렌스포즈(T) 해서 feature라는 변수에 저장해주고 numpy 패키지에 있는
cov( ) 함수를 사용해서 convarianceMatrix 즉 공분산행렬을 구해준다.
* 공분산 행렬은 위의내용처럼 대각선 diagonal을 기준으로 대칭행렬이다.
자 공분산행렬을 구했으면 우리는 최종목표인 eigenVactor와 eigenValue를 구해야한다.
eigValue , eigVector = np.linalg.eig(convarianceMatrix)
print('EigenVactors \n%s' %eigVector)
print('\nEigenValues \n%s' %eigValue)
|
eigenVector 와 eigneValue도 numpy의 linalg.eig( ) 함수를 통해서 구할수있다.
공분산행렬을 인자로 넣어주면된다.
고유값과 고유벡터를 구했으니 이제 PC(Principal Component)의 값을 구해볼까?
해석) 첫 번째 PC가 전체데이터의 73%를 설명해주고있다. 즉 , 1개만 사용했을 경우 27%의 데이터유실이있다.
projectedX = xStd.dot(eigVector.T[0])
print(projectedX)
result = pd.DataFrame(projectedX,columns=['PC1'])
result['y-axis'] = 0.0
result['label'] = y
import matplotlib.pyplot as plt
import seaborn as sns
sns.lmplot('PC1','y-axis',data=result,fit_reg=False,
scatter_kws={"s":50},
hue="label")
plt.title("PCA result")
plt.show()
cs |
자 이제 dot( ) 함수를 통해 eigenVector에다가 데이터를 올려놓고 projectedX 변수에 넣습니다.
그리고 시각화 패키지 matplotlib 를 통해 산점도를 그려보도록 합니다.
짠! PCA 알고리즘에 대해서 알아봤습니다.
위의 처럼 구현하는 것도 좋지만 PCA는 이미 패키지로 나와있습니다.
#패키지로 PCA 알고리즘 사용하기
from sklearn import decomposition
pca = decomposition.PCA(n_components=1)
sklPcaX = pca.fit_transform(xStd)
sklResult = pd.DataFrame(sklPcaX,columns=['PC1'])
sklResult['y-axis'] = 0.0
sklResult['label'] = y
sns.lmplot('PC1','y-axis',data=sklResult,fit_reg=False,
scatter_kws={"s":50},
hue="label")
plt.title("PCA result")
plt.show()
cs |
'Machine learning' 카테고리의 다른 글
[기계학습] KNN ( K-Nearest neighborhood ) k-최근접 이웃 (0) | 2020.07.09 |
---|---|
[기계학습] 나이브 베이즈 분류 - Naive bayes classifier (0) | 2020.07.07 |
[기계학습]회귀계수 축소법 ( Ridge regression, Ridge 회귀) (0) | 2020.06.25 |
[기계학습] 변수 선택법 알고리즘( Python Code - 파이썬 예제 ) (0) | 2020.06.18 |
[기계학습]. 다중선형회귀(Multiple Linear Regression)실습 Python code -예제 (0) | 2020.06.17 |