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

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

차원축소


8.3.7 압축을 위한 PCA


차원을 축소하고 난 후에는 훈련 세트의 크기가 줄어듭니다.


예를 들어 MNIST 데이터셋에 분산의 95%를 유지하도록 PCA를 유지하도록 PCA를 적용해보겠습니다. 각샘플은 원래 784개 특성이 아니라 150개 정도만 가지고 있을 것입니다.  대부분의 분산은 유지되었지만 데이터셋은 원본크기의 20% 미만이 되었습니다. 이는 상당한 압축률이고 svm등에 훈련 속도를 높일 수 있습니다. 


또한 압축된 데이터에 PCA투영의 변환을 반대로 적용하여 784개의 차원으로 되돌릴 수 있습니다. 물론 PCA압축을 하면서 분산  5%정도의 손실이 일어날 수 있습니다. 그러므로 원래 데이터와 완전히 같진 않겠지만 원본데이터와 매우 비슷할 것 입니다. 원본데이터와 복원된 데이터 사이의 평균 제곱 거리를 재구성 오차라고 합니다. 


예를 들어 mnist를 154차원으로 작게 만들고 784차원으로 다시 만들어 보겠습니다. 





 8.3.8 점진적 PCA 


pca 구현의 문제는  SVD 알고리즘을 실행하기 위해 전체 훈련 세트를 메모리에 올려야한다는 것 입니다. 다행히 점진적 PCA 알고리즘이 개발되었습니다. 훈련세트를 미니배치로 나눈 뒤 IPCA알고리즘에 한번에 하나씩 주입합니다. 


이런 방식은 훈련세트가 클 때 유용하게 온라인으로 PCA를 적용할 수 있습니다. 


아래는 Mnist 데이터에 이 알고리즘을 활용해보겠습니다. 100개의 미니배치로 나누어서 IncremenalPCA 파이썬 클래스에 주입하여 Mnist 데이터셋의 차원을 154개로 줄입니다. 전체 훈련 세트를 사용하는 fit이 아니라 partial_fit 메서드를 사용합니다. 



from sklearn.decomposition import IncrementalPCA

n_batches = 100
inc_pca = IncrementalPCA(n_components=154)
for x_natch in np.array_split(X_train, n_batches):
inc_pca.partial_fit(X_batch)

X_reduced = inc_pca.transform(X_train)

 또 다른 방법은 넘파이의 memmap 파이썬의 클래스를 사용해 하드 디스크의 이진 파일에 저장된 매우 큰 배열을 메모리에 들어 있는 것 처럼 다루는 것 입니다. 이 파이썬 클래스는 필요할 때 데이터를 메모리에 적재합니다. IncrementalPCA는 특정 순간에 배열의 일부만 사용하기 때문에 메모리 부족 문제를 해결할 수 있습니다. 다음 코드처럼 이방식을 적용하면 일반적인 fit() 메서드를 사용할 수 있습니다. 


X_mm = np.memmap(filename, dtype="float32", mode="readonly", shape=(m, n))

batch_size = m
inc_pca = IncrementalPCA(n_components=154, batch_size=batch_size)
inc_pca.fit(X_mm)




8.3.9 랜덤 PCA 


사이킷 런에는 PCA의 또 다른 옵션으로 랜덤 PCA를 제공합니다. 이방식은 확률적인 알고리즘으로, 첫 d개의 주성분에 대한 근삿값을 빠르게 찾습니다. 


rnd_pca = PCA(n_components=154, svd_solver="randomized")
X_reduced = rnd_pca.fit_transform(X_train)



8.4 커널 PCA 


svm에서 rbf커널을 이용하여 저차원의 데이터셋을 임의로 고차원으로 만들어서 비선형 회귀와 분류등을 실행한적이 있다. 이 커널을 PCA에도 사용할 수 있다. 


이기법은 투영된 후 샘플의 군집을 유지학나 꼬인 매니폴드에 가까운 데이터셋을 펴칠 때도 유용합니다. 


from sklearn.decomposition import KernelPCA

rbf_pca = KernelPCA(n_components=2, kernel="rbf", gamma=0.04)
X_reduced = rbf_pca.fit_transform(X)

 각종 커널을 사용해서 나타내기 





8.4.1 커널 선택과 하이퍼라리미터 튜닝 


Kpca는 비지도 학습이기 때문에 좋은 커널과 하이퍼파라미터를 선택하기 위한 명확한 성능 측정 기준이 없습니다. 하지만 차원 축소는 종종 지도학습의 전처리 단계로 활용되므로 그리드 탐색을 사용하여 주어진 문제에서 성능이 가장 좋은 커널과 하이퍼 파라미터를 선택할 수 있습니다. 


예를 들어 다음 코드는 두 단계의 파이프라인을 만드는데 먼저 kPCA를 사용해 차원을 2차원으로 축소하고 분류를 위해 로지스틱 회귀를 적용합니다. 



from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline

clf = Pipeline([
("kpca", KernelPCA(n_components=2)),
("log_reg", LogisticRegression())
])

pram_grid = [{
"kpca_gamma":np.linspace(0.03, 0.05, 10),
"kpca_kernel":["rbf", "sigmoid"]
}]

grid_search = GridSearchCV(clf, param_grid, cv=3)
grid_search.fit(X,y)

gridSearchCv를 통해서 좋은 커널과 gamma파라미터를 찾습니다. 

print(grid_search.best_params_)

위의 코드에서 좋은 커널과 파라미터를 찾을 수 있습니다. 



완전한 비지도 학습 방법으로 가장 낮은 재구성 오차를 만드는 커널과 하이퍼파라미터를 선택하는 방식도 있습니다. 하지만 재구성은 선형 PCA만큼 쉽지않습니다. 


커널 트릭 덕분에 훈련 세트를 특성맵를 사용한 무한 차원의 특성 공간에 매핑한 다음, 변환된 데이터셋을 선형 PCA를 사용해 2D로 투영한 것과 수학적으로 동일합니다. 


축소된 공간에 있는 샘플에 대해 선형 PCA를 역전시키면 재구성된 데이터 포인트는 원본 공간이 아닌 특성 공간에 놓이게 됩니다. 이특성 공간은 무한 차원이기 때문에 재구성된 포인트를 계산할 수 없고 재구성에 따른 실제 에러를 계산할 수 없습니다. 다행히 재구성된 포인트에 가깝게 매핑된 원본 공간의 포인트를 찾을 수 있습니다. 이를 재구성 원상이라고 부릅니다. 

재구성 원상을 얻게 되면 원본과 제곱거리를 구할 수 있습니다. 오차를 최소화하는 커널과 하이퍼 파라미터를 선택할 수 있습니다. 


재구성 방법은 투영된 샘플을 훈련 세트로, 원본 샘플을 타깃으로 하는 지도 학습 회귀 모델을 훈련시키는 것입니다. 사이킷런에서는 다음 코드와 같이 fit_inverse_transform=True로 지정하면 이를 자동으로 수행합니다. 



rbf_pca = KernelPCA(n_components=2, kernel='rbf', gamma=0.0433,
fit_inverse_transform=True)
X_reduced = rbf_pca.fit_transform(X)
X_preimage = rbf_pca.inverse_transform(X_reduced)

그럼 다음 아래와 같이 재구성 오차를 구해줄 수 있습니다.


from sklearn.metrics import mean_squared_error
mean_squared_error(X, X_preimage)


8.5 LLE(지역 선형 임베딩)


LLE는 강력한 비선형 차원 축소 기술입니다. 이전처럼 투영에 의존하지 않는 매니폴드 학습입니다. 


1. 간단히 해서 LLE는 먼저 각 훈련 샘플이 가장 가까운 이웃에 얼마나 선형적으로 연관되어 있는지 측정합니다. 


2. 그런 다음 국부적인 관계가 가장 잘보존되는 훈련 세트의 저차원 표현을 찾습니다. 


-> 이는 특별히 잡음이 너무 많지 않은 경우 꼬인 매니폴드를 펼치는데 잘 작동합니다.