주성분 분석을 통한 비지도 차원 축소
- 특성 선택과 마찬가지로 여러 특성 추출 기법을 사용하여 데이터셋의 특성 개수를 줄일 수 있다.
- 특성 선택과 특성 추출의 차이는 원본 특성을 유지하느냐에 있다.
- 순차 후진 선택 같은 특성 선택 알고리즘을 사용할 때는 원본 특성을 유지하지만, 특성 추출은 새로운 특성 공간으로 데이터를 변환하거나 투영한다.
- 차원 축소 관점에서 보면 특성 추출은 대부분의 관련 있는 정보를 유지하면서 데이터를 압축하는 방법으로 이해할 수 있다.
- 특성 추출이 저장 공간을 절약하거나 학습 알고리즘의 계산 효율성을 향상할 뿐만 아니라 차원의 저주 문제를 감소시켜 예측 성능을 향상하기도 한다. 특히 규제가 없는 모델로 작업할 때 그렇다.
주성분 분석의 주요 단계
- PCA는 비지도 선형 변환 기법으로 주로 특성 추출과 차원 축소 용도로 많은 분야에서 널리 사용된다.
- PCA는 특성 사이의 상관관계를 기반으로 하여 데이터에 있는 특성을 잡아낼 수 있다.
- 요약하자면 PCA는 고차원 데이터에서 분산이 가장 큰 방향을 찾고 좀 더 작거나 같은 수의 차원을 갖는 새로운 부분 공간으로 이를 투영한다.
- 새로운 부분 공간의 직교 좌표는 주어진 조건 하에서 분산이 최대인 방향으로 해석할 수 있다.
- 새로운 특성 축은 아래 그림과 같이 서로 직각을 이룬다. 아래 그림에서 $x1, x2$는 원본 특성 축이고 $PC1, PC2$는 주성분이다.
https://drive.google.com/uc?id=1dzul1QtBNylA7Nt7FBZLBpTGWfDo4l9f
- PCA를 사용하여 차원을 축소하기 위해 $d \times k$차원의 변환행렬 $W$를 만든다.
- 이 행렬로 샘플 벡터 $x$를 새로운 $k$차원의 특성 부분 공간으로 매핑한다.
- 이 부분 공간은 원본 $d$차원의 특성 공간보다 작은 차원을 가진다.
$x = [x_{1}, x_{2}, ... , x_{d}], x \in \mathbb{R}^{d}$
$\downarrow xW, W \in \mathbb{R}^{d \times k}$
$z = [z_{1}, z_{2}, ... , z_{k}], z \in \mathbb{R}^{k}$
- 원본 $d$차원 데이터를 새로운 $k$차원의 부분 공간(일반적으로 $k < d$)으로 변환하여 만들어진 첫 번째 주성분이 가장 큰 분산을 가질 것이다.
- 모든 주성분은 다른 주성분들과 상관관계가 있더라도 만들어진 주성분은 서로 직각을 이룰 것이다.
- PCA 방향은 데이터 스케일에 매우 민감하다.
- 특성의 스케일이 다르고 모든 특성의 중요도를 동일하게 취급하려면 PCA를 적용하기 전에 특성을 표준화 전처리해야 한다.
- 차원 축소 PCA 알고리즘의 단계는 다음과 같다.
- $d$차원 데이터셋을 표준화 전처리한다.
- 공분산 행렬(covariance matrix)을 만든다.
- 공분산 행렬을 고유 벡터(eigenvector)와 고윳값(eigenvalue)으로 분해한다.
- 고윳값을 내림차순으로 정렬하고 그에 해당하는 고유 벡터의 순위를 매긴다.
- 고윳값이 가장 큰 $k$개의 고유 벡터를 선택한다. 여기서 $k$는 새로운 특성 부분 공간의 차원이다. ($k \leq d$)
- 최상위 $k$개의 고유벡터로 투영행렬(projection matrix) $W$를 만든다.
- 투영 행렬 $W$를 사용해서 $d$차원 입력 데이터셋 $X$를 새로운 $k$차원의 특성 부분 공간으로 변환한다.
주성분 추출단계
- 우선 PCA 처음 4단계를 처리한다.
- 데이터를 표준화 전처리 한다.
- 공분산 행렬을 구성한다.
- 공분산 행렬의 고윳값과 고유벡터를 구한다.
- 고윳값을 내림차순으로 정렬하여 고유 벡터의 순위를 매긴다.
- Wine 데이터셋을 가져와서 70:30 비율로 훈련 세트와 테스트 세트를 나누고 표준화를 적용하여 단위 분산을 갖도록 한다.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
df_wine = pd.read_csv('<https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data>', header=None)
X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:,0].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=0)
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)
- 그 다음으로 공분산 행렬을 만드는 단계를 진행한다. 공분산 행렬은 $d \times d$차원의 대칭 행렬로 특성 상호 간의 공분산을 저장한다. $d$는 데이터셋에 있는 차원 개수이다.
- 예컨대 전체 샘플에 대한 두 특성 $x_{j}$와 $x_{k}$사이의 공분산은 다음 식으로 계산할 수 있다.
$\sigma_{jk} = {1 \over n} \sum_{i = 1}^{n} (x_{j}^{(i)} - \mu_{j})(x_{k}^{(i)} - \mu_{k})$