PCA
비지도 학습의 일종으로 한국어로 번역하면 '주성분 분석'이라고 부른다.
지금까지 정리한 내용들 중에 중요도 순위를 매기면 1, 2위를 다툴 정도로 머신러닝에서 매우 중요한 개념이다.
차원의 저주
지금까지는 데이터나 데이터들을 다루는 작업과 관련된 함수를 찾았었다.
회귀는 데이터 자체와 직접 관련된 함수였고, 분류와 클러스터링은 데이터를 다루는 작업과 관련된 함수였다.
그런데 28*28 크기의 작은 흑백 이미지 데이터를 분류하려고 하면, 하나의 데이터당 28*28 = 784 개 픽셀 정보를 다루다보니 kNN같은 단순한 알고리즘에서도 동작 시간이 오래 걸렸다.
게다가 흑백 이미지가 아니라 실제와 비슷한 이미지라면 rgb 값이 들어가면서 차원이 하나 더 늘어나 784 * 3 이 된다.
그래서 이렇게 실제 자주 사용하는 데이터에 가까울수록 그 크기가 매우 커진다.
위 이미지는 700 * 470 크기의 컬러 이미지이며, 데이터 하나당 픽셀 수가 대략 100만개에 이른다.
이런 데이터 수천, 수만장을 다루는 경우에는 당연히 시간이 오래 걸릴 것이다.
거기에 만약 다루려는 데이터가 이미지들이 수천장 쌓이는 비디오거나, 3D 공간을 표현하는 데이터라면 그 크기가 기하급수적으로 커질 것이다.
이렇게 다루는 데이터의 크기가 커지고 복잡해질수록 모델의 학습 속도도 떨어지고 성능도 떨어지는 것을 가리켜 '차원의 저주 (Curse of Demensionality)' 라고 부른다.
기본 아이디어
차원의 저주를 해결하기 위해서 고차원의 데이터를 그대로 넣어 학습시키기보다,
해당 데이터에서 중요한 데이터만 뽑아서 차원을 낮추더라도 모델의 성능을 유지하거나 오히려 더 끌어올릴 수 있는 방법이 등장했다.
그리고 그 중에 하나가 PCA 이다.
즉, PCA는 주어진 데이터의 차원을 낮추는 기법이다.
PCA의 구체적인 방법을 살펴보기 위해 간단하게 2차원 데이터의 차원을 낮추는 과정을 생각해보자.
예를 들어 키-몸무게 정보에 대한 2차원 데이터가 주어졌는데, 마침 위 그림과 같이 일렬로 정렬이 되어있었다고 가정해보자.
이때 이 데이터 중 하나가 (180, 80) 이라고 하면, 이 데이터를 x, y 라는 축 벡터(basis vector)를 이용해서 180x + 80y 로 표현할 수 있다.
이때 각 축벡터의 계수는 수학적으로 (180, 80) 을 축벡터 (1, 0), (0, 1) 과 각각 내적하여 구한 것이다.
그런데 꼭 축벡터를 x, y 로 사용할 필요는 없다.
만약 축 벡터를 위 그림과 같이 정의한다면 어떨까?
데이터가 정렬된 방향에 맞춘 PC1 벡터를 x축처럼 보고, PC2 벡터를 y축처럼 보아 데이터를 표현하는 것이다.
(이때 PC1 과 같이 데이터의 방향에 맞춘 벡터를 principal component vector 라고 한다.)
그러면 이 데이터는 aPC1 + bPC2 의 형태로 표현할 수 있을 것이다.
그런데 이렇게 표현한 모든 데이터의 PC2 성분을 보면 모두 0이기 때문에 사실상 PC2 벡터를 생략할 수 있게 된다.
결론적으로는 데이터를 표현하는 차원이 하나 줄어든 것과 같아졌다.
이렇게 데이터 표현의 기준이되는 basis vector 를 주성분 벡터(PC vector)로 변경하여 데이터를 표현하는 차원을 줄이는 기법이 PCA 이다.
그런데 보통 실제 데이터는 위 그림에서 본 것과 같이 직선 형태로 정렬되어있지 않다.
이런 경우에는 어떻게 새로운 PC 벡터를 정의해야 할까?
효과적으로 기계학습이 되려면 이 데이터들을 가장 잘 나타내는 방향, '주성분'을 PC 벡터로 설정해야 할 것이다.
그래서 PCA ('주성분 분석') 가 필요한 것이다.
데이터들을 새로운 벡터로 표현하기 위해 PC 벡터들을 찾다보면
위 예시는 기존 데이터가 2차원 데이터이기 때문에 주성분 벡터를 포함하여 총 2개의 벡터가 나온다.
만약 기존 데이터가 100만 차원이었다면 100만개의 방향을 뽑아낼 것이다. (그리고 이 100만개 방향은 모두 수직해야 한다.)
그리고 그 중 데이터를 가장 잘 설명하는 벡터가 주성분벡터로서 첫 번째 벡터가 된다.
이제 기존 데이터를 주성분 벡터를 기준으로 다시 표현하면 왼쪽 그림과 같이 표현할 수 있다.
그리고 이렇게 표현한 데이터를 (a, b) 로 표현하면 이때 b 의 절댓값은 a의 절댓값들에 비해 상대적으로 작은 값들이다.
PC1의 성분에 비해 PC2의 성분이 작은 것이다.
그리고 주성분 분석 기법에서는 이렇게 절댓값들이 작은, 주성분이 아닌 PC2 성분을 제거해버린다.
PC2 성분을 제거한다는 것은 모든 데이터를 PC1 벡터 축에 정사영 내리는 것과 같다.
하지만 이렇게 데이터를 표현하여 분류한다고 해도, 정보의 손실이 적어 기존 데이터를 분류할 때와 비슷하게 분류할 수 있다.
즉, 데이터의 차원은 낮아졌지만 모델 성능은 비슷하게 유지되는 것이다. (심지어 운이 좋으면 성능이 올라가기도 한다!)
주성분을 찾는 방법
이제 왜 주성분을 찾는지, 어떻게 주성분을 기반으로 효과적인 기계학습을 달성할 수 있는지 이해했다.
그렇다면 제일 중요한 '주성분을 찾는 방법' 이 남았다.
주성분을 찾을 때는 서두에 적었듯 비지도 학습 기반의 알고리즘을 활용하여 찾는다.
먼저 데이터가 이렇게 주어져있을 때, 선형회귀와 똑같이 임의 선분식을 Wx+b 로 두고, SSE (sub of square error) 가 최소가 되는 직선을 찾는다. 그러면 그 직선을 기존의 x, y 축벡터 기반으로 표현할 때 크기가 1인 벡터 (= 방향 벡터) 로 표현하면 그 벡터가 PC1 벡터가 된다. (위 그림에서 분홍색 선)
PC1 벡터를 찾은 후에는 모든 데이터에서 PC1 성분을 제거한다. 그러면 차원이 하나 줄어들게 된다.
(위 그림에서는 모든 파란색 점 데이터가 빨간색 점 위치로 정렬된 것)
차원이 하나 줄어든 나머지 데이터에 대해 위 과정을 반복하여 계속 차원을 하나씩 줄여나가면 그것이 PCA 이다.
(정리하다보니 내가 앞서 이해한 것과 반대로 설명해주시는 느낌이라 혼란스럽다.
SSE가 최소가 되는 분홍색 직선을 찾았다면, 해당 직선으로 정사영을 떨구기 위해서 PC1 벡터와 수직한 벡터의 성분을 없애야 하지 않나? 왜 PC1 벡터 성분을 제거하는 걸까?)
GPT 말을 보면 PC1 방향으로 투영해서 해당 성분 값을 취했으니, 이제 나머지 성분값들에 대해서 다시 PCA를 적용하기 위해 PC1 성분을 제거해야 한다고 하는 듯 하다.
내가 이해한 PCA는 3차원 기준으로 가장 쓸모없는 성분을 제거해서 모든 점을 어떤 2차원 평면에 정사영시키고, 다시 그 2차원 평면에 대해서 PCA를 수행해서 1차원 직선으로 정사영하는 느낌을 생각했었다.
제일 쓸모없는 성분을 1개씩 제거해 나가는 그림.
그런데 GPT 말로는 그게 아니라 제일 쓸모있는 성분을 1개씩 추출해 나가는 과정이기 때문에, 제일 쓸모있는 PC1 성분을 추출한 뒤에는 해당 성분을 버리고, 그 다음으로 쓸모있는 성분을 추출하는 과정을 반복하는 것이 PCA라고 하는 듯 하다.
그런 거라면 이해가 된다.
이때 주성분을 찾는 것은 선형대수학에서 SVD(특이값 분해) 와 관련이 있다.
특이값 분해는 m x n 행렬을 m x m 크기의 직교행렬, m x n 크기의 직교행렬, n x n 크기의 직교행렬 곱으로 분해햐는 것이다.
이때 PCA에서는 분해할 행렬 X 가 data matrix 가 되고, 이 행렬을 특이값 분해해서 나온 m x m 크기의 직교행렬(U)이 Principal Component가 된다.
이때 U 행렬을 구성하는 벡터가 (u1, u2, ...., um) 으로 구성되어 있을 때, u1 = PC1, u2 = PC2, ... 가 된다.
따라서 내가 r 차원으로 낮추고 싶다면 U 행렬에서 상위 r개 벡터를 뽑아 만든 행렬을 기존의 오리지널 데이터와 곱해 상위 r개의 주성분만 남긴 저차원 데이터로 줄일 수 있다.
(기존 좌표계로 표현된 데이터를 새로운 PC1 기준의 좌표계로 표현한뒤, 해당 좌표계에서 r 개의 축만 남기고 나머지 축을 제거한 것과 같다.)
U 벡터에서 PC1, PC2 만 남겼다면, 기존 데이터와 PC1 을 내적해서 PC1 성분(계수)을 구하고, 기존 데이터와 PC2 를 내적해서 PC2 성분(계수)을 구하는 것이다. (마치 (180, 80) 에서 180x + 80y 가 (180, 80) 과 (1,0) / (0, 1) 의 내적인 것과 같다.)
PCA reconstruction
PCA로 차원을 낮춘 이유는 저차원으로 머신러닝을 용이하게 하기 위함이었다.
따라서 PC 벡터를 기반으로 표현된 값을 그대로 사용하면 기존 데이터와 다르게 보일 것이다.
이를 기존 데이터와 비슷하게 다시 보기 위해, 다시 기존 좌표축 체계로 변환해줄 수 있다.
물론 기존 좌표축 체계로 변환하더라도 날려버렸던 성분이 돌아오지는 않으니 기존 데이터와는 조금 달라져있을 것이다.
(원래 좌표계로 돌릴 때도 똑같이 다시 PC를 곱해준다고 한다.)
PCA 활용
1. 데이터 차원 감소
기존의 MNIST 데이터셋을 기반으로 kNN으로 분류하는 모델은 96.9% 정확도를 가지지만, 하나의 데이터를 분류하기까지 1분의 시간이 걸렸다.
이미지 하나의 크기가 28*28 = 784 차원의 데이터였기 때문이다.
이를 효율적으로 하기위해 PCA를 사용해 10차원 데이터로 줄여서 kNN 알고리즘을 돌리면 비록 정확도는 92.8%로 감소하지만 분류에 걸리는 시간이 1.5초로 매우 빨라진 것을 확인할 수 있다.
이처럼 머신러닝을 돌릴 때 시간을 줄이기 위해, 또는 데이터의 크기가 너무 크면 컴퓨터가 받아들이지 못하는 문제 때문에 어쩔 수 없이 PCA를 사용하여 차원을 낮추고 모델을 학습시키는 상황이 존재한다.
2. 데이터 압축
PCA는 데이터를 압축하는데도 사용할 수 있다.
예를 들어 200 * 200 크기의 4만 차원 사람 얼굴 이미지를 그대로 저장하면 너무 용량이 크니, 훈련용 데이터셋을 기반으로 4개의 기준 이미지 성분만 뽑아낸 다음, 어떤 이미지를 저장할 때는 4만 차원 데이터가 아니라 PC1 ~ PC4 까지 4개 기준 이미지 성분에 곱해지는 계수 4개만 저장하여 4차원 데이터로 저장하는 것이다.
그리고 4차원 데이터로부터 원본 얼굴 이미지를 복원할 때는 그 계수를 그대로 PC1 ~ PC4 에 곱해주기만 하면 된다.
3. 이미지 노이즈 제거
이미지에 노이즈가 껴있으면 학습에 방해가 된다.
따라서 해당 이미지에서 중요한 성분만 남겨두고 노이즈를 제거하고 싶을 때도 PCA를 적용할 수 있다.
위 그림에서 왼쪽 이미지는 노이즈가 없는 이미지이다.
만약 가운데 이미지처럼 노이즈가 낀 이미지로부터 노이즈를 제거하고 싶을 때 PCA를 사용하여 주성분만 남긴 뒤, PCA reconstruction 을 사용해 원복시키면 노이즈가 날아간 원본 이미지로 복원할 수 있다.
오른쪽 이미지를 보면 기존의 이미지에 비해 배경 노이즈가 옅어진 것을 볼 수 있다.
다만 이 방법도 노이즈를 완벽하게 제거하기 힘들고, 주성분에 들어있는 노이즈는 제거가 안된다는 한계가 있다.
지금까지 데이터의 주성분만 남겨서 기계학습을 효율적으로 하기 위한 PCA 에 대해 정리하였다.
PCA는 비지도 학습 기법의 일환으로 차원 축소, 데이터 압축, 노이즈 제거 등에 활용할 수 있었으며, SVD 를 사용해 비교적 간단하게 차원을 줄일 수 있다.
하지만 PCA는 기본 아이디어가 반드시 직교하는 형태로 축을 설정하여 데이터를 잘라내기 때문에, 위 그림과 같이 오히려 직교하지 않는 축 형태로 데이터를 표현하는 것이 좋은 경우에는 잘 맞지 않는다는 한계가 있다.
그래서 오른쪽 그림과 같이 직교하는 성분이 아닌 2개의 주 성분을 기반으로 데이터를 표현하는 방법이 있는데 이를 가리켜 ICA 라고 한다.
PCA는 기본적으로 데이터에 행렬을 곱해서 차원을 줄이기 때문에 선형 기법이며, 차원감소와 관련된 선형 기법중에서는 제일 성능이 좋다.
그리고 PCA를 적용할 때는 '좌표축'을 바꾸는 것과 비슷하기 때문에, 그 좌표축의 중심이 될 '원점' 역시 함께 고려를 해야한다.
따라서 PCA를 적용하기 전에는 전체 데이터의 평균값을 좌표계의 원점으로 보고 모든 데이터를 해당 원점에 맞춰 평행이동 시킨다음 SVD를 적용하여 PC 성분을 뽑아 변환한다고 한다.
'CS > 기계학습심화' 카테고리의 다른 글
[기계학습심화] 11. 딥러닝 (2) - Neural Network & Back Propagation (2) | 2025.04.21 |
---|---|
[기계학습심화] 10. 딥러닝 (1) - 선형 분류 모델 (2) | 2025.04.20 |
[기계학습심화] 8. K-Means (0) | 2025.04.18 |
[기계학습심화] 7. SVM (support vector machine) (1) | 2025.04.18 |
[기계학습심화] 6. KNN 구현 (4) | 2025.04.17 |