ML - 차원 축소(Dimension Reduction)
기본적인 내용은 '핸즈온 머신러닝'에 기반합니다.
*Index*
0. Intro
1.차원의 저주
2. 차원 축소를 위한 접근 방법
3. PCA
4. 커널 PCA
5.LLE
6. 다른 차원 축소 기법
0. Intro
본 내용에 들어가기에 앞서
차원 축소를 인코딩으로 해석하면 쉽게 이해가 가능합니다.
고화질 영상을 해상도를 낮게 조정하여 인코딩 하는 경우 화질은 낮아지지만 용량은 감소합니다.
일부 정보(인코딩의 경우는 화질이겠죠?)가 유실되긴 하지만 영상을 재생하는 것에는 큰 문제가 없습니다.
차원 축소를 고려하기 전에는 훈련이 느린지 먼저 원본 데이터로 시스템을 훈련해봐야 합니다.
경우에 따라 잡음이나 불필요한 세부사항을 걸러내므로 성능을 높일 수 있지만
일반적으로는 훈련 속도만 빨라지기 때문입니다.
차원 축소는 훈련 속도를 높이는 것 외에 데이터 시각화에도 아주 유용합니다.
차원 수를 둘 또는 셋으로 줄이면 하나의 압축된 그래프로 그릴 수 있어 시각적 패턴을 얻어
인사이트를 얻는 경우가 많습니다.
이제
차원 축소의 두 가지 주요 접근법
a. 투영(Projection)
b. 매니폴드 학습(Manifold learning)
&
가장 인기 있는 차원 축소 기법
PCA, 커널 PCA, LLE
등을 이제 소개하겠습니다.
1. 차원의 저주

머신러닝의 훈련 샘플은 보통 수천~수백만 개의 특성을 가지고 있고
이러한 많은 특성들은 훈련 속도를 느리게 하고 좋은 솔루션을 찾기 어렵게 합니다.
이러한 문제를 보통 차원의 저주(Curse of dimensionality)라고 합니다.
이론적으로 차원의 저주를 해결하는 방법 중 하나는
훈련 샘플의 밀도가 충분히 높아질 때까지 훈련 세트의 크기를 키우는 것입니다.
(여기서 밀도가 높다는것은 훈련 데이터가 서로 가까이 있다는 것을 의미합니다.)
즉, 넓은 공간(높은 차원)에 충분한 데이터가
(위의 이미지의 3차원공간에 정육각형의 데이터를 채운다고 생각)
있으면 밀도가 높아지고 그럴 경우
차원의 저주에서 탈출할 수 있다는 것으로 이해할 수 있습니다.
하지만 일정 밀도를 충족시키기 위해 훈련 샘플 수를 늘리는 것은 차원 수가 커짐에 따라
샘플 수가 기하급수적으로 늘어나기 때문에 한계가 있습니다.
(ex : 10cm*10cm 공간에는 데이터가 100개 들어가지만
1차원이 늘어난 10cm*10cm*10cm 공간에는 데이터 1000개가 들어가야 꽉 참 )
2. 차원 축소를 위한 접근 방법
투영 & 매니 폴드 개념
2.1 투영(projection)


위의 이미지를 보면 projection을 이해하기 편할 것입니다.
어느 한 축 또는 평면을 기준으로 projection을 할 경우 위의 이미지와 같이 한 차원 축소된 것을 볼 수 있습니다.
하지만 차원 축소에 있어서 projection이 최선의 방법은 아닙니다.

예를 들어 swiss roll data set을 X3 축의 특성을 버리고 X1-X2 평면에 투영 시키면

좌측의 뭉개진 2D 데이터 셋을 얻을 것입니다.
하지만 우리가 원하는 것은 우측의 데이터가 잘 나뉘어진 데이터 셋 이겠죠?
2.2 매니폴드 학습

위에 나왔던 스위스롤은 2D 매니폴드의 한 예입니다.
위 그림을 예로 보면 (a)그림은 3차원이지만
말린(b)를 펴게 되면(=2차원 매니폴드로 이해하게 되면) 2차원으로 볼 수 있습니다.
일반적으로 d차원 매니폴드는 d차원 초평면으로 보일 수 있는 n차원 공간의 일부입니다.( n > d)
(-> 내가 보고자하는 차원 = d, 원데이터셋 공간의 차원 = n)
많은 차원 축소 알고리즘이 스위스롤 처럼 말리거나 꼬여 있는 매니폴드를 풀어헤친 형태를 모델링하는 방법으로 작동하는 데 이를 매니폴드 학습이라 합니다.
그리고 이는 대부분 실제 고차원 데이터셋이 더 낮은 저차원 매니폴드에 가깝게 놓여있다는
매니폴드 가정(=매니폴드 가설)에 근거합니다.
경험적으로도 이런 가정은 자주 발견된다고 합니다.
( -> 위의 스위스롤 예에서 3D데이터셋을 2D매니폴드로 볼 수 있음)

매니폴드 학습이 많이 활용되는 이유는 분류(Classification)나 회귀(Regression)같은 작업 시
저차원 매니폴드 형태로 데이터를 표현하면 더 간단해질 거라고 가정하기 때문입니다.
하지만 위 그림을 보면 매번 간단해지는 것은 아니라는 것을 알 수 있습니다.
요약하면 모델을 훈련 시키기 전에 차원을 감소시키면
훈련 속도는 빨라지지만 항상 더 낫거나 간단한 솔루션이 되는 것은 아닙니다.
이는 전적으로 데이터셋에 달렸습니다.
3. PCA(Principal component analysis / 주성분 분석)
PCA는 가장 인기 있는 차원 축소 알고리즘입니다.
먼저 데이터에 가장 가까운 초평면(기준 축)을 정의 후, 데이터를 이 평면에 투영시킵니다.
(데이터의 분포를 최대한 유지하면서 저차원에 투영)
3.1 분산 보존 개념 이해

이미지 우측 직선의 분포를 보면 가장 위에 있는 분산 그래프를 보면
분산이 최대로 보존되는 축을 선택하는 것이 정보가 가장 적게 손실되는 것을 확인할 수 있습니다.
3.2 주성분이란?
PCA는 훈련 세트에서 위에서 살펴본 것과 같이 분산이 최대로 보존되는 축(c1)을 찾습니다.
또한 첫 번째 축에 직교하고 남은 분산을 최대한 보존하는 두 번째 축(c2)을 찾습니다.
이렇게 i = 1,2,3... 축이 존재한다고 가정할 때
i번째 축을 해당 데이터의 i번째 주성분이라고 부릅니다.
따라서 차원이 커지면 주성분이 많아지겠죠?
주성분을 찾는 방법은?
-> SVD 표준 행렬 분해 기술 사용

위의 코드는 넘파이의 svd()함수를 사용해 훈련 세트의 모든 주성분을 구한 후
처음 두 개의 주성분을 정의하는 두 개의 단위 벡터(c1,c2)를 추출한 것입니다.
3.3 d차원으로 투영하기
(d : 내가 보고자하는 차원)
다음 코드는 첫 두 개의 주성분으로 정의된 평면에 훈련 세트를 투영한 것입니다.

PCA가 하는 작업을 요약 하자면
a. 주어진 데이터에서 분산을 가장 많이 보존하는 n개의 축을 찾는다.
b. 투영할 저차원이 d차원이라면 분산을 가장 많이 보존하는 축부터 d개의 축을 선택 후
이 축들로 이루어진 d차원 공간에 데이터를 투영
https://box-world.tistory.com/33
[머신러닝 순한맛] PCA(Principal Component Analysis) 알고리즘이란?
″성공의 핵심 요소는 인내심이다.” -Bill Gates- 시작하며 우리 저번 포스팅에서 Data Compression 또는 Dimentianality Reduction의 기본적인 원리를 알아보았습니다. 이번 시간에는 이러한 원리를 바탕으
box-world.tistory.com
* 참고- 그림을 통한 주성분에 대한 이해 과정
3.4 사이킷런 사용한 PCA

사이킷런의 PCA 모델은 앞서 한 것처럼 SVD 분해 방법을 사용하여 구현합니다.
(사이킷런의 PCA 모델은 자동으로 데이터를 중앙에 맞춰준다.)
3.5. 설명된 분산의 비율
explained_variance_ratio_ 변수에는 원본 데이터셋에 대해 주성분이 보존하는 분산의 비율이 들어있습니다.
다음 코드를 통해 보존율이 높은 상위 2개 주성분을 살펴보겠습니다.

이는 데이터셋 분산의 95.4%가 첫 번째 주성분을 따라 놓여있고
4.6%가 두 번째 주성분을 따라 놓여있음을 알려줍니다.
3.6 적절한 차원 수 선택하기
축소할 차원 수를 정하기보다는 충분한 분산이 될 때까지 더해야 할 차원 수를 선택하는 것이 더 간단합니다.
(but 시각화를 위한 차원 축소는 2개나 3개가 일반적)
다음 코드는 분산을 95%를 유지하는데 필요한 최소한의 차원 수를 계산합니다.

분산을 차원 수에 대한 함수로 그려 확인하는 방법도 있습니다.

위 그래프에는 분산의 빠른 성장이 멈추는 변곡점이 있습니다.
여기서는 차원을 약 100으로 축소해도 분산을 크게 손해 보지는 않을 것으로 확인되네요.
3.7 압축을 위한 PCA
차원을 축소하고 나면 훈련 세트의 크기가 줄어듭니다.
예를 들어 MNIST 데이터셋에 분산의 95%를 유지하도록 PCA를 적용하면
원래의 784개의 특성이 아닌 150개 정도만 가지고 있을 것입니다.
분산은 대부분 유지되었지만 데이터셋은 원본의 20%미만이 되었습니다.
이는 상당한 압축률이고 이러한 크기 축소는 SVM 같은 분류 알고리즘의 속도를 크게 높일 수 있습니다.
또한 압축된 데이터셋을 PCA를 역으로 적용하여 784개의 차원으로 되돌릴 수도 있습니다.
하지만 이미 5%의 유실된 분산이 있었기 때문에 재구성하여도 원본 데이터와는 같지 않습니다.
원본 데이터와 재구성된 데이터 사이의 평균 제곱 거리를 재구성 오차라고 합니다.

*(아래 글에서 MNIST 데이터셋에 대한 내용을 확인할 수 있습니다.)
아래 코드와 그림은 원본 훈련세트(좌)와 압축 후 복원한 결과(우)를 보여줍니다.
이미지 품질은 손실되었지만 숫자 모양은 거의 온전한 상태인 것을 확인할 수 있습니다.

3.8 랜덤 PCA
svd_solver = "randomized"로 지정하면 사이킷런은 랜덤 PCA라는 확률적 알고리즘을 이용하여 축소할 d차원에 대한 d개의 주성분을 근삿값으로 빠르게 찾습니다.

svd_solver의 기본값은 "auto"인데 원본 데이터의 크기나 차원 수가 500보다 크고
축소할 차원이 이것들의 80%보다 작으면 사이킷런은 자동으로 랜덤 PCA 알고리즘을 사용합니다.
이것을 방지하려면 "auto" 대신 "full"을 사용하면 됩니다.
3.9 점진적 PCA
PCA구현에 있어 문제점은 SVD 알고리즘 실행을 위해 전체 데이터셋을 메모리에 올려야 한다는 점입니다.
이러면 당연히 훈련 속도가 느려질 것이라는 것을 예상하실 수 있으실 겁니다.
이를 개선하고자 점진적 PCA 알고리즘이 개발되었습니다.
점진적 PCA는 데이터셋을 미니배치로 나눈 뒤 하나씩 주입하여 적용하여 문제점을 보완합니다.
아래 코드는 MNIST 데이터셋을 100개의 미니배치로 나눠 차원을 축소하는 코드입니다.

4. 커널 PCA
커널 트릭을 PCA에 적용하여 차원 축소를 위한 복잡한 비선형 투영 가능.
이를 커널 PCA(kPCA)라 합니다.
* 커널 트릭
SVM은 인기 있는 분류 알고리즘이지만
비선형 방식에서는 다른 방법으로 분류를 하는데 이때 사용되는 방법이 커널 트릭입니다.
즉, 선형 분류가 불가능한 데이터(좌측 이미지)를 처리를 하기 위해 데이터의 차원을 증가시켜 분류(우측 이미지)할 수 있도록 도와주는 커널 함수를 의미합니다. 선형 분류가 힘든 데이터를 분류하기 위한 방법이다 보니 연산량이 증가하고 그에 따른 시간도 증가하지만 정확도는 높일 수 있습니다.

다음 코드는 사이킷런 kernelPCA의 서로 다른 커널을 사용해 2차원으로 축소시킨 스위스롤의 형태입니다.


4.1 커널 선택과 하이퍼파라미터 튜닝
kPCA는 비지도 학습이기 때문에 어떤 커널과 하이퍼파라미터를 선택해야 하는지
명확하게 알 수 있는 기준이 없어 그리드 탐색을 이용하여 보완합니다.
다음 코드는 kPCA를 이용하여 2차원으로 축소하고 로지스틱 회귀로 분류를 진행합니다.
그리고 가장 높은 정확도를 얻기 위해 GridSearchCV를 사용해 kPCA에
가장 좋은 커널과 gamma 파라미터를 사용합니다.

다음 코드로 커널과 파라미터 확인

완전한 비지도 학습으로 가장 낮은 재구성오차를 만드는 커널과 하이퍼파라미터를 선택하는 방법도 있습니다.
재구성은 선형 PCA만큼 쉽지는 않지만 커널 트릭을 이용해 이러한 문제를 해결할 수 있습니다.

차원 축소된 데이터를 복원하면
이때의 데이터는 원래 차원의 공간이 아닌 특성공간(feature space, 이미지 우측 하단)에 놓이게 됩니다.
하지만 특성공간은 차원이 무한하기 때문에 재구성 오차 등의 계산이 불가능합니다.
다행히 재구성된 데이터의 위치와 가깝게 매핑된 원본 공간의 위치는 찾을 수 있는데
이를 재구성된 원상(pre-image, 이미지 좌측 하단)이라고 합니다.
원상을 얻으면 원본 데이터와의 제곱 거리를 측정하여 오차를 구할 수 있게 되고
최적의 커널과 하이퍼파라미터를 찾는 것이 가능해집니다.
재구성 방법
축소된 데이터를 훈련세트로 하고, 원본 데이터를 타깃으로 해서
비지도 학습 모델 훈련을 진행합니다.
사이킷런에서는 fit_inverse_tranform = True로 지정하면 자동 수행합니다.

재구성 오차 확인

5. LLE(Locally Linear Embedding, 지역 선형 임베딩)
LLE는 비선형 차원 축소 기술이고 투영에 의존하지 않는 매니폴드 학습입니다.
즉, 각 data가 가장 가까운 이웃에 얼마나 선형적으로 연관되어 있는지 측정합니다.
그리고 앞서 살펴본 스위스롤을 3D에서 2D로 보이게끔 펼쳐놓은 표현과 같이
원본 데이터의 저차원 표현을 찾습니다.
이 방법은 잡음이 많지 않은 경우 꼬인 매니폴드를 펴는데 잘 작동합니다.
다음 코드는 사이킷런의 Locally Linear Embedding을 사용해 스위스롤을 펼쳐줍니다.


데이터가 왼쪽은 확장, 오른쪽은 압축되어 있어 크게 보면 샘플 간 거리가 잘 유지되어 있지 않지만
LLE는 매니폴드를 모델링 하는데 잘 동작하는것을 볼 수 있습니다.
6. 다른 차원 축소 기법

a. MDS(Multidimensional scaling, 다차원 스케일링)
샘플 간의 거리를 보존하면서 차원 축소
b. Isomap
각 샘플을 가장 가까운 이웃과 연결하는 방법으로 그래프를 만듭니다.
그리고 샘플 간의 지오데식 거리(geodesic distance)를 유지하며 차원을 축소합니다.
* 지오데식 거리 : 그래프에서 두 노드 사이의 최단 경로를 이루는 노드의 수
c. t-SNE
데이터끼리 비슷한 것은 가까이, 그렇지 않은 것은 멀리하여 차원 축소.
주로 시각화에 사용되고 특히 고차원 공간에 있는 데이터의 군집을 시각화할 때 사용됩니다.
(ex : MNIST 데이터셋을 2D로 시각화할 때)
d. 랜덤 투영

이름 그대로 linear한 투영을 랜덤하게 해서 데이터를 저차원으로 투영합니다.
e. LDA(Linear Discriminant Analysis, 선형 판별 분석)

분류 알고리즘으로 학습 시에 클래스들을 가장 잘 구분하는 축을 학습해서
이 축으로 데이터가 투영되는 초평면을 정의하는 데 사용합니다.
장점 - 투영을 통해 가능한 한 클래스를 멀리 떨어지게 유지시키므로
SVM 분류기 같은 다른 분류 알고리즘을 적용하기 전에 차원을 축소시키는데 좋습니다.
이상 차원 축소에 대한 내용이었습니다.
읽어주셔서 감사합니다.