본문 바로가기

Data Science/Machine Learning

[핸즈온 머신러닝 2/E] 8장. 차원 축소

우리가 마주하는 머신러닝 문제에서 훈련 샘플이 무수히 많은 특성(feature)을 갖고 있는 경우가 존재한다.

 

이렇게 많은 특성들이 존재하게 되면, 훈련 속도가 느려질 뿐만 아니라 좋은 솔루션을 찾기가 힘들다.

 

이번 챕터에서는 이러한 문제를 해결할 수 있는 방법인 "차원 축소"에 대해서 정리해보도록 하겠다.

 

자, 그럼 시작해볼까?

 

 

<들어가기에 앞서 간단한 preview...>

  • 차원을 축소시키면 일부 정보가 유실된다.
    • 따라서 훈련 속도가 빨라질 수는 있지만, 정보 손실의 문제가 발생할 수도 있다.
    • 또한 작업 파이프라인이 더 복잡해지고 유지 관리가 어려워진다.
  • 차원 수를 둘 또는 셋으로 줄이면 고차원 훈련 세트를 하나의 압축된 그래프로 표현할 수 있고, 군집과 같은 시각적인 패턴 또한 감지하기 쉬워서 중요한 insight를 도출해내는 경우가 많다.

 

 

차원의 저주(Curse of Dimensionality)

  • 데이터에서 모델을 학습할 때 독립적인 샘플이 많을수록 학습이 잘 되는 반면, 차원이 커질수록 학습이 어려워지고 더 많은 데이터를 필요로 하는 현상을 말한다.
    • 간단하게 말하면 차원이 증가함에 따라(변수의 수가 증가할수록) 모델의 성능이 안 좋아지는 현상이다.
    • 즉, "관측치 수 < 변수의 수"일 때 발생하는 현상이다.

차원이 증가함에 따라 빈 공간이 많이 생기는 것을 확인할 수 있다. (차원의 저주)

  • 이를 해결하기 위한 방안으로는 두 가지가 있다.
    • 많은 양의 데이터 획득
      • 사실상 이건 불가능...
    • 차원 축소
      • 결국 우리는 이 방법을 써야한다!!

 

 

▶ 차원 축소를 위한 접근 방법

1. 투영(Projection)

  • 모든 훈련 샘플은 고차원 공간 안의 저차원 부분 공간에 놓여 있다.
    • 쉽게 말하면, 아래 그림처럼 대부분의 훈련 샘플들이 저차원 부분 공간에 위치한다는 소리...
    • 굳이 고차원일 필요가 없다는 말이죠!! ^^;;

2차원에 가깝게 배치된 3차원 데이터 셋

  • 따라서 이 저차원 부분 공간에 수직으로(즉, 샘플과 평면 사이의 가장 짧은 직선을 따라) 투영(projection)하면, 아래와 같이 2차원 데이터 셋을 얻을 수 있다.

투영(projection)해서 만들어진 새로운 2차원 데이터 셋

  • 이처럼 투영(projection)을 통해 고차원 데이터를 저차원으로 만들어 줄 수 있으나, 이 방법이 항상 최선인 것은 아니라는 점을 기억하자.
    • 아래와 같은 "스위스 롤" 형태의 데이터 셋은 부분 공간이 뒤틀려있기 때문에, 투영(projection)을 통해 차원을 축소시키는 방법은 좋지 못한 결과를 초래한다.

스위스 롤 형태의 데이터 셋(왼쪽)과 투영(projection) 이후의 뭉개진 2차원 데이터 셋(오른쪽)

2. 매니폴드 학습

  • "스위스 롤"2차원 매니폴드의 한 예이다.
    • 즉, 2차원 매니폴드고차원 공간에서 휘어지거나 뒤틀린 모양이다.
  • 일반적으로 d차원 매니폴드전체의 어느 한 부분에만 한정되는(국부적으로) d차원 초평면으로 보일 수 있는 n차원 공간의 일부이다.
  • 대다수의 차원 축소 알고리즘매니폴드 학습 방식을 사용한다.
    • 이는 대부분 실제 고차원 데이터 셋이 더 낮은 저차원 매니폴드에 가깝게 놓여 있다는 "매니폴드 가정(가설)"에 근거한다.
    • "매니폴드 가정(가설)"은 종종 다른 가정과 같이 병행되는데, 바로 처리해야 할 작업(ex. 분류 또는 회귀 문제)이 저차원의 매니폴드 공간에 표현되면 더 간단해질 것이라는 가정이다.

 

  • 요약하면 모델을 훈련시키기 전에 훈련 세트의 차원을 감소시키면, 훈련 속도는 빨라지지만 항상 더 나은 솔루션을 제공해주지는 않는다는 것이다!!

 

 

▶ 주성분 분석(PCA; Pricipal Component Analysis)

  • 주성분 분석. 즉, 흔히들 말하는 PCA는 데이터에 가장 가까운 초평면(hyperplane)을 정의한 다음, 데이터를 이 평면에 투영시키는 기법이다.
  • 따라서 투영하기 전에 올바른 초평면을 찾는 것이 중요한데, 분산이 최대로 보존되는 축을 선택하면 된다.
    • 분산이 최대로 보존되는 축을 선택하게 되면, 정보 손실이 가장 적게 발생하기 때문이다.
    • 다시 말해, 원본 데이터 셋과 투영된 데이터 셋 사이의 평균 제곱 거리를 최소화하는 축을 선택한다고 할 수 있겠다.

실선(c1 벡터)에 투영된 것은 분산을 최대로 보존(오른쪽 맨 위) vs 점선(c2 벡터)에 투영된 것은 분산을 매우 적게 유지(오른쪽 맨 아래)

  • PCA는 데이터 셋의 평균이 0이라고 가정한다.
    • 따라서 사이킷런을 통해 코드를 구현하는 것이 아니라, PCA를 직접 코드로 구현하게 될 경우에는 먼저 데이터를 원점에 맞춰주는 작업이 필요하다.

◆ 주성분이란 무엇인가?

  • 고차원 데이터 셋이라면 PCA(주성분 분석)는 이전의 두 축에 직교하는 세 번째 축을 찾으며, 데이터 셋에 있는 차원의 수만큼 네 번째, 다섯 번째, ... , n번째 축을 찾는다.
  • 여기서 i번째 축i번째 주성분(PC; Pricipal Component)이라고 부른다.
    • 위 그림을 예시로 들면, 첫 번째 PC는 벡터 c1이 놓인 축이고, 두 번째 PC는 벡터 c2가 놓인 축이다.
  • 특잇값 분해(SVD; Singular Value Decomposition)를 통해 주성분을 찾을 수 있다.
    • 특잇값 분해에 대한 내용을 완벽하게 이해하려면, 선형대수 지식과 다변량 통계 지식이 필요하다.
    • 따라서 일단은 이런게 있구나 정도로만 이해하고 넘어가도록 하겠다.
  • 위 과정을 통해 주성분을 모두 추출했다면, 처음 d개의 주성분으로 정의한 초평면에 투영하여 데이터 셋의 차원을 d차원으로 축소시킬 수 있다.
    • 사이킷런의 PCA 모델은 앞서 언급한 SVD 분해 방법을 사용한다.
      • <참고> - 사이킷런의 PCA 모델은 자동으로 데이터를 중앙에 맞춰준다.
    • n_components 매개변수
      • 주성분 개수를 지정
    • components_ 속성
      • 주성분 벡터
    • explained_variance_ratio_ 변수
      • 주성분의 설명된 분산의 비율
      • 즉, 전체 분산에서 차지하는 비율(이 비율이 높을수록 차원 축소 과정에서 정보 손실이 적게 발생)
      • 주로 이 비율을 확인해서 주성분의 개수(즉, 적절한 차원 수)를 결정한다.

ex) 2개의 주성분으로 전체 분산의 약 98%를 설명 가능

◆ 압축을 위한 PCA

  • 차원 축소를 하면 훈련 세트의 크기가 줄어들어, 분류 알고리즘의 속도를 크게 높일 수 있다.
  • 또한 반대로 압축된 데이터 셋에 PCA 투영 반환을 적용시켜, 원본 데이터와 유사하게 만들 수 있다.
    • inverse_transform( ) 메소드를 사용하면 된다. 
    • 단, 원본 데이터와 똑같이 복구시킬 수는 없다!!

◆ 랜덤 PCA

  • 기본값(default 값)이 "auto" svd_solver 매개변수"randomized"로 지정하면, 사이킷런은 랜덤 PCA라는 확률적 알고리즘을 사용한다.
    • 랜덤 PCA를 사용하면, 처음 d개의 주성분에 대한 근사값을 빠르게 찾을 수 있다.

<참고>

  • m(특성 개수)이나 n(데이터 개수)이 500보다 크고, d(차원)가 m이나 n의 80%보다 작으면 사이킷런은 자동으로 랜덤 PCA 알고리즘을 사용한다.
  • 사이킷런에서 강제로 완전한 SVD 방식을 사용하려면, svd_solver 매개변수"full"로 지정해주면 된다.

◆ 점진적 PCA (IPCA)

  • PCA를 구현할 때의 문제점은 SVD 알고리즘을 실행하기 위해 전체 훈련 세트를 메모리에 올려야 한다는 것이다.
    • 이를 해결하기 위해 나온 알고리즘이 바로 IPCA이다.
  • 개인적으로 IPCA는 메모리 문제 때문에 개발된 알고리즘이며, 훈련 세트가 크고 온라인(실시간)으로 PCA를 적용할 때 유용하다고만 이해하고 넘어갔다...

 

 

▶ 커널 PCA (kPCA)

  • 커널 기법을 PCA에 적용해서 차원 축소를 위한 복잡한 비선형 투영을 수행할 수도 있다.
  • 이 기법은 투영된 후에 샘플의 군집을 유지하거나 꼬인 매니폴드에 가까운 데이터 셋(ex. 스위스 롤)을 펼칠 때도 유용하다.
  • 사이킷런의 KernelPCA를 사용하며, kernel 매개변수를 통해 사용할 커널을 지정해 줄 수 있다.

각기 다른 커널을 사용하여, 2차원을 축소시킨 스위스 롤의 모습

  • kPCA비지도 학습이므로 좋은 커널과 하이퍼 파라미터를 선택하기 위한 명확한 기준이 없다.
    • 그러나 차원 축소종종 지도 학습의 전처리 단계에서 활용되기에, 그리드 탐색을 통해 성능이 뛰어난 커널과 하이퍼 파라미터를 선택할 수 있다.

 

 

▶ 지역 선형 임베딩(LLE; Locally Linear Embedding)

  • 강력한 비선형 차원 축소 기법이며, 투영(projection)에 의존하지 않는 매니폴드 학습이다.
  • 그러나 대용량 데이터 셋에 적용하기는 어렵다.
  • 사이킷런의 LocallyLinearEmbedding 클래스를 사용하면 된다.
  • 이 학습 기법의 작동 원리는 수식을 봐도 잘 이해가 되지 않으므로 일단 넘기도록 하겠다...

 

 

▶ 다른 차원 축소 기법 → 선형 판별 분석(LDA)외에는 그냥 이런게 있구나 정도로만 이해하고 넘어갔다..

  • 랜덤 투영
    • 랜덤한 선형 투영을 사용해 데이터를 저차원 공간으로 투영한다.
    • 사이킷런의 random_projection 패키지를 사용하면 된다.
  • 다차원 스케일링(MDS; Multidimensional Scaling)
    • 샘플 간의 거리를 보존하면서 차원을 축소한다.
  • Isomap
    • 먼저 각 샘플을 가장 가까운 이웃과 연결하는 식으로 그래프를 만든다.
    • 그 다음, 샘플 간의 geodesic distance를 유지하면서 차원을 축소한다.
  • t-SNE(t-distributed stochastic neighbor embedding)
    • 비슷한 샘플은 가까이, 비슷하지 않은 샘플은 멀리 떨어지도록 하면서 차원을 축소한다.
    • 주로 시각화에 많이 사용된다. (특히 고차원 공간에 있는 샘플의 군집을 시각화할 때)
  • 선형 판별 분석(LDA; Linear Discriminant Analysis)
    • 분류 알고리즘임에도 훈련 과정에서 클래스 사이를 가장 잘 구분하는 축을 학습한다.
      • 이 축은 데이터가 투영되는 초평면을 정의하는 데 사용할 수 있다.
    • 투영을 통해 가능한 한 클래스가 멀리 떨어지게 유지시키므로, 다른 분류 알고리즘을 적용하기 전에 차원을 축소시키는 데 좋다.

 

여기까지 해서 "8장. 차원 축소"에 대한 정리를 마치도록 하겠다.

 

차원 축소는 선형대수 지식다변량 통계 지식을 요구하는 파트라 어려운 것이 당연하다.

 

공부를 하면 할수록 "아직 갈 길이 멀구나..." 라는 것을 느낀다.

 

그래도 힘내서 끝까지 달려보자!!

 

★ 참고 자료

- 핸즈온 머신러닝 2/E 교재

- 파이썬 머신러닝 완벽 가이드 교재