코딩초보 김씨
[ML] 데이터 전처리 - 선형 차원 축소 본문
[ 차원 축소란? ]
많은 피처로 구성된 다차원의 데이터 셋의 차원을 축소하여 새로원 차원의 데이터 세트를 생성하는 것
아래 이미지가 가장 직관적이고 이해가 쉬워서 가져왔다.
각 차원 공간의 25%에 해당하는 데이터가 위치하는 비율이 42%, 14% ..., 3%로 점차 줄어드는 것을 볼 수 있다.

[ 차원이 너무 클 때의 문제점 ]
1. 차원의 저주에 빠지기 쉽다.
2. 다중 공산성 문제
많은 feature 중 몇 feature들끼리는 강한 상관관계를 보이는 경우가 있을 것이다.
이처럼 상관관계가 높은 feature들을 함께 학습 시키면, 모델의 과적합이 발생하여 학습 성능 저하 가능성이 있음.
" 따라서 모델에 데이터 셋을 적용하기 전에 어떤 feature가 모델의 성능에 큰 영향을 줄지 파악하고,
feature를 선택/가공 하는 과정이 필요하다. "
[ 차원 축소의 종류 ]
1. 피처 선택(feature selection) : 불필요한 feature는 아예 제거하고, 데이터의 특징을 잘 나타내는 주요 feature만 선택
2. 피처 추출(feature selection) : 기존 feature를 저차원이 중요 feature로 압축해서 추출.
이렇게 추출된 중요 feature는 기존과 완전히 다른 값이 된다.
[ PCA (Princial Component Analysis) 주성분분석 ]
PCA는 고차원의 데이터를 저차원으로 압축하는 대표적인 차원 축소 방법이며,
데이터를 가장 잘 표현하는 방향으로 축을 생성하고, 새롭게 생성된 축으로 데이터를 투영시킨다.
데이터들이 겹치면 정보의 유실이 발생할 수 있기 때문에
축을 설정할 때 데이터가 가장 넓게 펼쳐지는 축, 즉 가장 큰 분산(=공분산)을 가지는 축을 설정해야한다.
바로 이 축을 주성분 (Principal Component) 이라고 한다.
PC는 2차원에서는 2개, 3차원에서는 3개, 300차원에서는 300개가 있다.

분산을 크게 하려면 Eigen Value가 큰 지점을 찾아야 하는데,
Convariance Matrix 중 Eigen Value가 큰 값의 Eigen Vector를 찾고, 그를 기준으로 차원축소한다.
↑ 무슨 말인지 잘 모르겠으면, 아래 예시를 보고 이해하도록 하자!
[ PCA 방법 ]
방법 1. 어려움 (내 기준)
예시 출처 : github.com/minsuk-heo/python_tutorial/blob/master/data_science/pca/PCA.ipynb
# 데이터 생성
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']
# feature vectors 설정
X = df[['calory', 'breakfast', 'lunch', 'dinner', 'exercise']]
# 타겟값 설정
Y = df[['body_shape']]
0. 전처리 : StandardScaler로 데이터 Normalization (평균을 0, 표준편차를 1로 변환)
# 표준정규화
from sklearn.preprocessing import StandardScaler
x_std = StandardScaler().fit_transform(X)

1. 입력 데이터 세트의 공분산 행렬을 생성
import numpy as np
# 전처리한 x_std의 Transpose (column에 있는 feature들을 row로 변경)
features = x_std.T
# 공분산 행렬 생성
covariance_matrix = np.cov(features)
print(covariance_matrix)

2. 공분산 행렬의 고유벡터와 고유값을 계산
# np.linalg.eig 함수는 Eigenvalue와 Eigenvector 반환
eig_vals, eig_vecs = np.linalg.eig(covariance_matrix)
print('Eigenvectors \n%s' %eig_vecs)
print('\nEigenvalues \n%s' %eig_vals)


3. 고유값이 가장 큰 순으로 K개(PCA 변환 차수만큼)만큼 고유벡터를 추출
# 고유벡터 1개로도 73%의 충분한 분산을 갖기 때문에 데이터를 1차원으로 축소
eig_vals[0] / sum(eig_vals)
4. 고유값이 가장 큰 순으로 추출된 고유벡터를 이용해 새롭게 입력 데이터를 변환
# eigen vector 위에 projection(투영) -> eigen vector 위에 데이터를 올려놓겠다
projected_X = x_std.dot(eig_vecs.T[0])
result = pd.DataFrame(projected_X, columns=['PC1'])
result['y-axis'] = 0.0
result['label'] = Y
5. 시각화
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
sns.lmplot('PC1', 'y-axis', data=result, fit_reg=False, # x-axis, y-axis, data, no line
scatter_kws={"s": 50}, # marker size
hue="label") # color
plt.title('PCA result')

방법 2. 매우 간단
from sklearn import decomposition
# n_components : 차원수
pca = decomposition.PCA(n_components=1)
# fit_transform을 통해 차원축소
sklearn_pca_x = pca.fit_transform(x_std)
sklearn_result = pd.DataFrame(sklearn_pca_x, columns=['PC1'])
sklearn_result['y-axis'] = 0.0
sklearn_result['label'] = Y
'Python > Machine Learning' 카테고리의 다른 글
| [ML] 지도학습 (0) | 2021.06.13 |
|---|---|
| [ML] 비지도학습 - Clustering (군집화) 중 k-Means (0) | 2021.06.09 |