[핸즈온 머신러닝]8강 차원축소 1편

2018. 8. 4. 01:03Python-이론/python-인공지능2

차원 축소


머신러닝을 사용할 때 훈련데이터는 수천개에서 ~ 수백만개의 특성을 갖고 있습니다. 이 부분은 훈련의 속도를 늦추거나 더 나은 솔루션을 찾기 힘들게 합니다. 이런 문제를 차원의 저주라고 합니다. 


예를 들어 Mnist를 사용할 때 흰바탕의 특성을 줄인다고 해도 검사를 하는데 많은 문제가 되지 않을 것입니다. 하지만 머신러닝을 공부하면서 느끼지만 항상 양날의 검이 있는 것 같습니다. 차원 축소에서도 분명히 차원을 줄여주면 시간 단축이 될 수 있겠지만 시스템의 성능이 나빠질 수 있습니다. 차원을 축소하다 중요한 특성을 지워버릴 수 도 있으니깐요. 그래서 항상 자신의 상황과 데이터를 잘고려해서 차원 축소를 잘진행해주어야 하는 것 같습니다. 


그리고 훈련 속도를 높이는 것 이외에도 데이터를 고차원으로 보여주어야 하는 시각적인 부분에서 좀더 쉽게 보여줄 수 있고 군집 같은 시각적인 패턴을 감지해 중요한 통찰을 많이 얻을 수 있습니다. 



8.1 차원의 저주 


우리는 3차원의 세계에 살고 있어서 아마도 고차원을 이해하기 어렵습니다.  우리가 평소에 살고있지 않은 곳이라서 그렇죠. 


그리고 고차원이 될 수록 


1. 무작위로 점을 선택했을 때 경계선내에 위치할 가능성이 매우 가깝습니다. 차원이 늘어 날 수록 점들 사이에 경계선이 늘어나서 그렇습니다. 


2. 위의 사진을 보면 차원이 늘어날 수 록 점들 사이의 길이가 길어지는 것을 알 수 있다. 하지만 이와같이 차원이 늘어나면서 점이 길어지면 데이터들이 분산될 가능성이 높습니다. 하지만 멀어질 수 록 이럴 수록 더 외삽(이전의 데이터와 새로운 데이터를 예측하는 기법이다.)을 진행해야 한다. 이는 과대적합의 위험이 커지게 됩니다. 


이런 문제점을 해결하기 위해서 샘플의 밀도가 충분히 높아질 때까지 계속해서 데이터를 늘리는 것이다. 하지만 이러한 것의 단점은 차원이 늘어날 수록 데이터가 기하급수적으로 늘어나게 되는 문제가 발생하게 됩니다. 


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


두가지의 축소법 투영, 매니폴드 학습에 대해 알아 보겠습니다. 


8.2.1 투영 


대부분의 실전문제는 훈련샘플이 모든 차원에 균일하게 퍼져있지 않습니다. 많은 특성은 거의 변화가 없고 다른 특성들은 서로 강하게 연관되어 있다. 결과적으로 데이터들은 고차원속의 저차원 부분 공간에 놓여 있습니다. 


쉽게 말하면 아래의 사진과 같이 3차원의 모습이 되어있다. 


3차원은 2차원 면이 여러개로 이루어 진 것을 알 수 있다. 데이터를 표현할 수 있는 2차원 면을 나타낼 수 있습니다. 이렇게 데이터를 표현할 수 있는 2차원 면하나를 나태는 것을 투영이라고 합니다.    


이런식으로 


그러나 차원 축소에 있어서 투영이 언제나 좋은 방법이 아닙니다. 스위스 롤이라는 3차원에서 데이터 모형들이 롤케익 모형으로 만들어 진 것을 의미합니다. 

           스위스 롤 모형 

                                              투영                                                                        단순히 펴놓은 데이터




위 사진과 같이 투영이 꼭 맞지 않을 때도 있다.


8.2.2 매니폴드 학습 


매니폴드는 고차원 공간을 휘어지거나 뒤틀린 (원본 보다는) 저차원 공간을 나타내는 것 입니다. 대부분의 차원 축소 알고리즘에 자주 사용됩니다. 


그리고 예를 들어 Mnist와 같이 겉은 흰색이고 가운데 쯤 검은색으로 숫자가 적용되어있습니다. 이런 규제가 있어서 자유도가 낮은 데이터들은 저차원의 매니폴드로 압축할 수 있도록 도와줍니다. 


매니폴드 학습법은 다른 과정들과 함께 사용되곤 합니다. 예를 들어 회귀, 분류의 기능을 구현하는데 쓰이곤 합니다. 
                                              


                                                      단순한 경우가 더 간단할 때                매니폴드가 유용한 경우        



1열의 사진을 보면 결정경계가 x1 = 5로 정해졌는데 2D로 바꾸었을 때는 훨씬 복잡해졌습니다. 이점을 보아서 훈련시키기 전에 모델을 단순히 하는 것은 훈련속도도 빨라지고 더 단순한 데이터를 만들 수 있지만 항상 알맞은 솔루션이 되는 것이 아닙니다. 이는 전적으로 데이터셋에 달려있습니다.  


8.3 PCA


pca은 가장 인기 있는 차원 축소 알고리즘입니다.  먼저 데이터에 가장 가까운 초평면을 정의한 다음, 데이터를 이 평면에 투영시킵니다. 


초평면이란 

어떠한 차원에서 class를 분류시켜주는 어떠한 차원 - 1을 의미한다. 


8.3.1 분산보존


저차원의 초평면에 훈련세트를 투영하기 전에 먼저 올바른 초평면을 선택해야합니다.
예를 들어 
왼편의 2차원 데이터에 3개의 초평면이 있고 오른쪽은 이런 초평면을 투영한 결과입니다. 


오른쪽을 보면 일반 직선이 가장 많은 분산이 보존되고 있고 점선이 가장 적은 분산을 보존하고있다. 

분산을 많이 보존하는게 데이터를 가장 적게 손실시킨다. 결국 이는 평균제곱거리(오차)를 최소하 할 수 있다.  

8.3.2 주성분 


pca는 훈련 세트에서 분산이 최대인 축을 찾습니다. 왼쪽 사진에서는 실선이 됩니다. 그리고 이와 직교하며 남은 분산을 최대한 보존하는 두번째 축을 찾습니다. 즉 점선이 됩니다. 그리고 제일 작은 선은 위나 아래로 수직하게 됩니다. 고차원이 되면 그만큼 계속해서 초평면이 생기게 됩니다. 


i번째 축을 정의하는 단위 벡터를 i번째 주성분이라고 부릅니다. 첫번째 주성분을 c1 두번째를 c2라고 부릅니다. 

그렇다면 훈련세트의 주성분을 어떻게 구할 수 있을까요?? 


다행히 특잇값 분해(SVD)라는 표준 행렬 기술이 있어서 훈련 세트 행렬 X를 세개 행렬의 접곱인 U, V전치행렬, 시그마 등으로 분해할 수 있다. 


여기 찾고자하는 주성분이 V와 같이 담겨있습니다. 


파이썬에서 이용 



X_centered = X - X.mean(axis=0)
U, s, Vt = np.linalg.svd(X_centered) c1 = Vt.T[:, 0] c2 = Vt.T[:. 1]



8.3.3 d차원으로 투영하기 


주성분을 모두 추출 했다면 처음 d개의 주성분으로 정의한 초평면에 투영하여 데이터셋의 차원을 d차원으로 축소할 수 있습니다. 

그러니깐 d개 만큼의 초평면을 그려진 그래프에 투영해서 d차원으로 축소할 수 있습니다.  이 초평면은 분산을 최대치로 유지한채 투영하는 것이다. 



W2 = Vt.T[:, :2]
X2D = X_centered.dot(W2)




8.3.4 사이킷런 사용하기



from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X2D = pca.fit_transform(X)



이와 같이 훈련시키고 나서 components_변수를 사용해 주성분을 확인할 수 있습니다. 



8.3.5 설명된 분산의 비율 


explained_variance_ratio_ 변수에 저장된 주성분의 설명된 분산의 비율도 유용한 정보입니다. 이 값은 각 주성분의 축을 따라 있는 데이터 셋의 분산 비율을 나타냅니다. 


위의 사진의 데이터를 이용하면 



pca.explained_variance_ratio_
array([0.84248607, 0.14631839])


첫 주성분은 84%이고 두번째는 14%를 나타낸다. 세번째 주 성분이 2퍼센트를 나타낸다. 


8.3.6 적절한 차원 수 선택하기 


어떻게 감소할 차원으 수를 정할 수 있을까?? 
축소할 차원 수를 임의로 정하기 보단 충분한 분산이 될 때 까지 차원수를 줄여가는 방법을 사용하면 된다. 데이터 시각화를 위한 감소는 2차원이나 3차원이면 된다. 


방법 1. 


다음 코드는 차원을 축소하지 않고 PCA를 계산한 뒤 훈련세트의 분산을 95%를 유지하는 데 필요한 최소한의 차원수를 계산합니다.  


pca = PCA()
pca.fit(X_train)
cumsum = np.cumsum(pca.explained_variance_ratio_)
d = np.argmax(cumsum >= 0.95) + 1 방법2 .

하지만 위의 방법보다는 n_componenets 에 차원보다는 유지하려는 분산을 0.95로 유지할 수 있게 하는 편이 훨씬 더편합니다. pca = PCA(n_components=0.95)

x_reduced = pca.fit_transform(X_train)



또다른 방법은 설명된 분산을 차원수에 대한 함수로 그리는 것 입니다. 일반적으로 그래프는 설명된 분산의 빠른 성장이 멈추는 변곡점이 있습니다. 차원수를 감소함에 따라 분산이 너무 많이 감소하지 않는 값을 찾으면 됩니다.