데이터로그😎

PCA (Principal Component Analysis) 본문

머신러닝/차원축소

PCA (Principal Component Analysis)

지연v'_'v 2023. 9. 5. 15:30
차원축소의 대표적인 알고리즘
1. PCA
2. LDA
3. SVD
4. NMF

 

고차원 데이터의 문제점

  • 수백 개 이상의 피처로 구성된 데이터 세트의 경우, 예측 신뢰도가 떨어진다.
  • 피처가 많으면 개별 피처 간에 상관관계가 높을 가능성이 큼 → 다중 공선성 문제 발생 → 모델 예측 성능 저하
  • 따라서 피처 축소 필요 (차원 축소)

 

차원축소란?

  • 피처 선택, 피처 추출로 나뉨
    • 피처 선택(feature selection): 주요 피처만 선택하고 불필요 피처 제거
    • 피처 추출(feature extraction): 잠재적 요소 추출. 
      • ex) 수능성적, 모의고사 성적, 내신성적 => 학업성취도로 요약
  • 말그대로 데이터의 차원을 줄이는 것
    • 고차원 데이터를 다룰 때 차원의 저주로 인해 모델링이 어려워지고 성능이 저하되는 문제 발생.
    • 이를 해결하기 위해 차원축소 실행
  • 데이터에서 중요한 특성만 남기고, 노이즈나 불필요한 특성을 제거할 수 있음.

 

PCA (Principal Component Analysis)

PCA

1. 목표

데이터의 평균으로부터 시작해 데이터의 분포를 가장 잘 설명해주는 방향을 찾는 것 (벡터를 찾는 것)

위의 붓꽃 데이터를 예시로 들어보면, 데이터를 가장 잘 설명하는 축을 찾아 정사영(Projection)을 시키면  2차원이었던 데이터를 1차원으로 축소할 수 있다.

 

2. 결론부터 말하자면..

분포를 가장 잘 설명하는 방향은 분포 분산이 가장 큰 방향이고, 그 다음으로 분포를 잘 설명하는 방향은 첫번째 축에 직교하는 방향이다.

 

여기서 의문을 가질 수 있다.

Q1. 왜 분산이 가장 큰 방향이 분포를 가장 잘 설명하는가?
Q2. 왜 그 다음으로 잘 설명하는 방향은 첫번째 축에 수직하는가?

 

이제부터 이 의문을 풀어보자!

 

Q1. 왜 분산이 가장 큰 방향이 분포를 가장 잘 설명하는가?

https://youtu.be/C21GoH0Y9AE?feature=shared

 

먼저 original data에서 x,y값 각각의 평균을 빼면 평균은 0이 되어 원점으로 이동하게 된다.

이제 데이터의 분포를 가장 잘 나타내는 축을 찾는 과정에서 Projection을 내렸을 때 데이터-축과의 거리 = 오차이고, 이 오차의 제곱의 평균이 가장 작은 축이 데이터의 분포를 가장 잘 나타내는 축이 된다. 

 

 

  • 주성분 분석 = 주가 되는 성분을 분석한다.
  • PCA는 데이터의 고차원 공간에서 *가장 많은 분산을 가지는 방향*을 찾아서 이를 기반으로 데이터를 저차원 공간으로 변환한다.
    • PCA에서 '가장 많은 분산을 가지는'은 주어진 데이터셋에서 가장 많은 정보를 가지는 축(axis)을 찾는 것을 의미
    • 분산이 커져야 관측치들의 차이점이 더 명확해진다.
  • PCA는 데이터셋의 고차원 공간에서 분산이 큰 방향으로 축을 설정하여, 그 방향으로 데이터를 변환한다.이때 분산이 큰 방향이란, 데이터가 퍼져 있는 정도가 가장 큰 방향을 의미한다. 따라서, 이 방향으로 데이터를 변환하면, 데이터의 가장 큰 차원을 가장 잘 보존하면서도, 차원을 축소할 수 있다.

 

PCA 순서

1. 가장 큰 데이터 변동성(Variance)을 기반으로 첫번째 벡터 축 생성

2. 두번째 축은 이 벡터 축에 직각이 되는 벡터(직교 벡터)를 축으로 함.

3. 세번째 축은 다시 두번째 축과 직각이 되는 벡터를 설정하는 방식으로 축 생성.

 

선형대수 관점

 

3.5 PCA — 데이터 사이언스 스쿨

\(N\)개의 \(M\)차원 데이터 벡터 \(x_1, x_2, \cdots, x_N\)에 대해 어떤 상수 벡터 \(x_0\)를 뺀 데이터 벡터 \(x_1-x_0, x_2-x_0, \cdots, x_N-x_0\)를 정규직교인 기저벡터 \(w_1, w_2, \cdots, w_K\)로 이루어진 \(K\)차원

datascienceschool.net

 

 

✅ 공분산 행렬이란?

  • 분산 = 한 개의 특정한 변수의 데이터 변동을 의미. 공분산 = 두 변수 간의 변동을 의미
    • 키 X, 몸무게 Y → Cov(X, Y) > 0 : 키 X가 증가할 때 몸무게 Y도 증가한다.
  • 공분산 행렬 = 여러 변수와 관련된 공분산을 포함하는 정방형 행렬
  • 공분산 행렬 = 정방행렬(square matrix) & 대칭행렬(symmetric matrix)
    • 정방행렬: 열 수 = 행 수
    • 대칭행렬: 대각 원소를 중심으로 원소 값이 대칭되는 행렬. ( A = A) 
      • 대칭행렬은 항상 고유벡터를 직교행렬로, 고유값을 정방행렬로 대각화할 수 있다.
  X Y Z
X 3.0 -0.71 -0.24
Y -0.71 4.5 0.28
Z -0.24 0.28 0.91

위의 표를 공분산 행렬이라 생각하자.

대각선 원소는 각 변수 X,Y,Z의 분산을 의미하며, 대각선 이외의 원소는 타 변수와의 공분산을 의미한다.

 

 

✅ 고유 벡터

  • 행렬 A를 곱하더라도 방향이 변하지 않고 크기만 변하는 벡터.
  • Ax = ax (A: 행렬, x: 고유벡터, a: 스칼라) 

 

 

✅ PCA

PCA = 분산행렬!!

(공)분산행렬 = 대칭행렬 (**VᵀV = VVᵀ = I, 따라서 V=V^-1)**→ 대각화 가능(A = V Λ Vᵀ)

  • 어떤 데이터의 공분산 행렬=A. 공분산 행렬은 대칭행렬이므로 대각화 식으로 표현 가능 A = V Λ Vᵀ
    • 대칭행렬  (**VᵀV = VVᵀ = I, 따라서 V=V^-1) 
    • A = VΛV^-1
      • A: n x n 크기의 정방행렬
      • V: A의 고유벡터(eigenvector)들을 열로 쌓아 만든 고유벡터 행렬
      • Λ: A의 고유값(eigenvalue)들을 대각원소로 갖는 대각행렬
      • V^-1: V의 역행렬
  • 여기서 PCA 차원축소가 실행되면 PCA(n_components=2)에 입력된 요소만큼 차원이 축소됨.
  • 먼저 V(고유벡터행렬)과 Λ(고유값 행렬)이 내적되며 차원이 축소됨
    • V는 가장 큰분산을 가진 고유벡터 순으로 나열되어 있고, Λ(고유값 행렬)의 감마는 고유벡터의 크기임.

 

 

실습

from sklearn.datasets import load_iris
import pandas as pd

iris= load_iris()
data = iris.data
feature_names = iris.feature_names
target = iris.target
target_names = iris.target_names

iris_df = pd.DataFrame(
            data =data,
            columns = feature_names)
iris_df['target'] = target
iris_df.head()

 

 

import matplotlib.pyplot as plt
import seaborn as sns


# 꽃잎과 꽃받침을 따로따로 시각화
sepal_columns=[feature_names[0],feature_names[1]]
petal_columns = [feature_names[2],feature_names[3]]


# 꽃받침 시각화
sns.scatterplot(
    x=sepal_columns[0],
    y=sepal_columns[1],
    hue='target',
    palette='muted',
    data=iris_df)

plt.title('Sepal')
plt.show()
# 0(setosa)는 잘 나뉠 수 있지만, 1과(versicolor) 2(virginica)는 분산이 크지 않음.


# 꽃잎 시각화
sns.scatterplot(
    x=petal_columns[0],
    y=petal_columns[1],
    hue='target',
    palette='muted',
    data=iris_df)

plt.title('Petal')
plt.show()

 

  • 0: setosa, 1: versicolor, 2:virginica
  • setosa의 경우, sepal_width>3.0 & sepal_length < 6.0 인 경우에 일정하게 분포되어 있음.
  • versicolor, virginica의 경우 sepal width, length 만으로는 분류가 어려움.

 

스케일링 & PCA (2차원)

from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

iris_scaled = StandardScaler().fit_transform(iris_df.iloc[:,:-1])

pca_2 = PCA(n_components=2)
pca_2.fit(iris_scaled)

# 데이터 변환 수행
iris_pca = pca_2.transform(iris_scaled)
iris_pca.shape # (150,2) --> 2차원으로 축소됨


# PCA로 변환된 데이터를  DataFrame으로 만들기
pca_columns = ['Component 1','Component 2']
iris_pca_df = pd.DataFrame(
            data = iris_pca,
            columns = pca_columns
            )

iris_pca_df['target'] = target

iris_pca_df.head()

 

 

PCA 2차원 시각화

sns.scatterplot(
    x='Component 1',
    y='Component 2',
    hue='target',
    palette='muted',
    data=iris_pca_df)

plt.title('PCA n_component=2')
plt.show()

PCA 변환 후에도 setosa(0)은 여전히 잘 구분됨.

Versicolor, Virginica는 Component1축을 기준으로 겹치는 부분이 있긴 하지만 전에 비해서는 비교적으로 잘 구분됨.

왜? Component1 축이 기존 데이터의 변동성(분산)을 잘 반영하고 있기 때문이다.

아래에서 PCA 개별 컴포넌트 별로 차지하고 있는 변동성 비율을 확인해보자.

 

PCA 후 설명력

pca_2.explained_variance_ratio_
# 각 주성분의 축을 따라 있는 데이터셋의 분산 비율. 

# >>>array([0.72962445, 0.22850762])
  • Component1 이 전체 변동성의 73%를,Component2 가 전체 변동성의 23%를 차지
  • PCA를 2개 요소로만 변환해도 전체 변동성의 96%를 설명할 수 있다는 말임
  • 데이터셋 분산의 73%가 첫번째 주성분을 따라 놓여있고, 23%가 두번째 주성분을 따라 놓여있다는 말임. 세번째 주성분에는 4% 미만이 남아있을 것이라 추정 가능.

 

 

PCA (3차원)

pca_3 = PCA(n_components=3)
iris_pca_3 = pca_3.fit_transform(iris_df.drop('target',axis=1))

pca_columns = ['Component 1','Component 2','Component 3']
iris_pca_df = pd.DataFrame(
            iris_pca_3,
            columns = pca_columns
            )

iris_pca_df['target'] = target

 

PCA 3차원 시각화

color=[]
for n in iris.target:
    if n==0:
        color.append('r')
    elif n==1:
        color.append('g')
    else:
        color.append('b')
        
        
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(projection='3d')
colors = ['r', 'g', 'b']  


ax.scatter(iris_pca_df['Component 1'], iris_pca_df['Component 2'], iris_pca_df['Component 3'],alpha=0.5, c = color)

 

 

이미지, 설명 출처

https://datascienceschool.net/02%20mathematics/03.05%20PCA.html

 

3.5 PCA — 데이터 사이언스 스쿨

\(N\)개의 \(M\)차원 데이터 벡터 \(x_1, x_2, \cdots, x_N\)에 대해 어떤 상수 벡터 \(x_0\)를 뺀 데이터 벡터 \(x_1-x_0, x_2-x_0, \cdots, x_N-x_0\)를 정규직교인 기저벡터 \(w_1, w_2, \cdots, w_K\)로 이루어진 \(K\)차원

datascienceschool.net

 

'머신러닝 > 차원축소' 카테고리의 다른 글

SVD (Singular Value Decomposition)  (0) 2023.09.05
LDA (Linear Descriminant Analysis)  (0) 2023.09.05