본문 바로가기
  • 조금 느려도, 꾸준히
Artificial Intelligence/Machine Learning

핸즈온 머신러닝(4) - 연습문제 1

by chan 2020. 1. 22.
반응형

# MNIST 데이터셋으로 분류기를 만들어 테스트 세트에서 97% 정확도를 달성하라

 97%의 정확도를 달성하기 위해서는 먼저 적절한 분류기 모델을 설정해야 한다. MNIST 데이터셋은 숫자 손글씨를 분류하는 것이며, 각각의 데이터들은 유사성을 띈 군집 하에 동일한 레이블을 가지므로, 이번 연습문제 풀이에서는 K-최근접 이웃 알고리즘 (KNeighborsClassifier)을 사용하도록 한다. 

 

 프로젝트를 처음부터 다시 시작하므로 데이터셋을 내려받도록 한다.

from sklearn.datasets import fetch_openml 
import numpy as np

mnist = fetch_openml('mnist_784', version=1)
X, y = mnist["data"], mnist["target"]
y = y.astype(np.int)

 

 이미 했던 것과 마찬가지로 훈련 세트를 섞어 랜덤하게 배치시킨다.

X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
shuffle_index = np.random.permutation(60000) 
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]

우선 간단하게 k-최근접 이웃 알고리즘 객체인 knn_clf 를 만들어 전체 훈련 세트에 대해 훈련시키고, sklearn.metrics의 accuracy_score() 메서드를 이용해 분류기의 예측 정확도를 평가한다.

 

knn_clf = KNeighborsClassifier(n_neighbors=2, weights='distance',n_jobs=-1)
knn_clf.fit(X_train, y_train)

"""
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=-1, n_neighbors=2, p=2,
                     weights='distance')
"""

from sklearn.metrics import accuracy_score
y_predict = knn_clf.predict(X_test)
accuracy_score(y_test, y_predict)
# 0.9691

이때 knn_clf 모델의 n_neighbors 하이퍼파라미터는 2, weights 하이퍼파라미터는 'distance' 로 설정했다. K-최근접 이웃 알고리즘 하이퍼파라미터 중, 간단하게 설명해서 n_neighbors 값의 의미는 가장 가까운 이웃을 몇 개 고를지에 대한 파라미터 이며 weights 파라미터의 'distance'값의 의미는 이웃과의 거리에 따라서 가중치를 부여한다는 의미이다.

 

자세한 내용은 K-neariest neighbors algorithm 에 대한 포스트에서 다루기로 하고, 우선 결과를 살펴보면

 

정확도가 0.9691로 측정된 것을 볼 수 있다.

 

우리의 목표는 정확도 97%를 달성하는 것이 목표이므로, 모델을 개선해야 한다.

 

보통 이러한 상황에서 모델을 개선하기 위해 sklearn.model_selection의 GridSearchCV 메서드를 이용하여 여러 파라미터 값에 대한 그리드 탐색을 시도하는 것이 일반적이지만, 시간이 아주 오래걸리고 (위 코드를 GPU로 실행하는 데에도 10분 정도가 소요되었다) 빠르게 목표를 달성하는 것이 좋으므로 하이퍼파라미터 n_neighbors의 값을 2에서 3으로 조정하여 같은 작업을 반복하기로 하자.

 

 

 

*사실, KNeighborClassifier의 런타임 시간을 줄이기 위해 가장 가시적인 방법은 leaf_size의 파라미터 값을 올리는 것이다. leaf_size 값의 증가와 분류기 정확도 트레이드오프에 대한 다른 개발자들의 생각들이 stackoverflow 에 잘 나타나 있다.

Tuning leaf_size to decrease time consumption in Scikit-Learn KNN

 

Tuning leaf_size to decrease time consumption in Scikit-Learn KNN

I was trying to implement KNN for handwritten character recognition where I found out that the execution of code was taking a lot of time. When added parameter leaf_size with value 400, I observed ...

stackoverflow.com

 

 

 

 

다음은 n_neighbors 파라미터 값만 3으로 변경하고 같은 과정을 실행한 코드와 정확도의 결과값이다.

 

knn_clf_2 = KNeighborsClassifier(n_neighbors=3, weights='distance',n_jobs=-1)
knn_clf_2.fit(X_train, y_train)

"""
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=-1, n_neighbors=3, p=2,
                     weights='distance')
"""

from sklearn.metrics import accuracy_score
y_predict = knn_clf_2.predict(X_test)
accuracy_score(y_test, y_predict)
# 0.9717

이로서 정확도 97%가 넘는 분류기를 만들어냈다. 사실 mnist 손글씨 데이터셋은 워낙 유명하고, 데이터셋의 크기도 크지 않아 97% 정확도를 달성하는 것은 전혀 어렵지 않다(default 값으로만 분류기를 만들어도 97%가 넘는 정확도를 보여준다). 예제의 의의는 그리드 탐색을 시도하는 것에 초점이 맞추어져 있는데, 시간상의 문제로 그리드 탐색을 하지 못한 것은 개인적으로 아쉽기 때문에 적절한 분류기 모델로 그리드 탐색을 중점적으로 진행하는 과정을 포스팅 할 계획이다.

반응형

댓글