[핸즈온 머신러닝 2판] 3장 연습문제 1번
[1번] MNIST 데이터셋으로 분류기를 만들어 테스트 세트에서 97%의 정확도를 달성해보세요.
(힌트 : KNeighborsClassifier 가 이 작업에 아주 잘 맞습니다. 좋은 하이퍼파라미터 값만 찾으면 됩니다. (wieghts와 n_neighbors 하이퍼파라미터로 그리드 탐색을 시도해보세요).)
#사용할 데이터셋과 모델 임포트
from sklearn.datasets import fetch_openml
from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
#넘파이 임포트
import numpy as np
mnist = fetch_openml('mnist_784', version=1, as_frame=False) # as_frame = True 넘파이로 반환
mnist.keys()
fetch_openml 메서드를 이용해 mnist_784 데이터프레임을 넘파이로 변환해 가져온다.
mnist.keys() 를 호출하면 출력값으로
dict_keys(['data', 'target', 'frame', 'categories', 'feature_names', 'target_names', 'DESCR', 'details', 'url'])
가 나오는데, 이 중에 'data', 'target' 만 사용했다.
#데이터와 타겟 레이블을 추출
X, y = mnist["data"], mnist["target"]
#데이터 형태 확인
X.shape
X, y 에 데이터와 타겟 레이블들을 지정 해주고, 데이터의 형태를 확인했다. X.shape 를 호출하면 자동으로 데이터의 쉐입을 출력해 주는데 (70000, 784) 로 이미지가 70000개 있고, 특성이 784개가 있다는 뜻이다. 이때 특성이란 이미지의 가각 한 픽셀을 말한다. 28 * 28 픽셀로 이루어진 이미지이기 때문에, 각 픽셀의 밝기(흑백이기 떄문에 밝기이다.) 가 특성이 된다.
# target 레이블 은 문자열이기 때문에 정수로 변환
y = y.astype(np.uint8)
# 59999번 인덱스를 기준으로 훈련 세트와 테스트 세트를 나눔
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
그리고 y[0] 호출을 통해 타깃 레이블의 첫 번째 원소를 살펴보면 '5' 로 나오기 때문에 문자열을 astype 메서드를 사용해 정수로 변환해준다. 변환 후 70000개의 이미지 중 60000개를 훈련 세트, 10000개를 테스트 세트로 나눈다. 훈련 세트로 모델을 학습한 뒤 정확도 97%를 얻는 것이 우리의 목표이다.
#weigths 에서 uniform : 가중치마다 같은 값을 부여, distance : 거리가 더 가까운 이웃의 영향을 더 많이 받도록 가중치 설정
param_grid = [{'weights': ["uniform", "distance"], 'n_neighbors': [3, 4, 5]}]
knn_clf = KNeighborsClassifier()
grid_search = GridSearchCV(knn_clf, param_grid, cv=5, verbose=3)
grid_search.fit(X_train, y_train)
문제에서 힌트를 준 것을 기억하고 그리드 서치를 이용해 최적의 파라미터 값을 찾아야 한다. weights 는 uniform 과 distance 두 개를 원소로 하는 배열을 넣어준다.
이때 uniform과 distance가 뜻하는 것이 궁금해 공식 문서를 찾아보았다.
weights{‘uniform’, ‘distance’} or callable, default=’uniform’
Weight function used in prediction. Possible values:
- ‘uniform’ : uniform weights. All points in each neighborhood are weighted equally.
- ‘distance’ : weight points by the inverse of their distance. in this case, closer neighbors of a query point will have a greater influence than neighbors which are further away.
sklearn.neighbors.KNeighborsClassifier
Examples using sklearn.neighbors.KNeighborsClassifier: Release Highlights for scikit-learn 0.24 Release Highlights for scikit-learn 0.24 Classifier comparison Classifier comparison Plot the decisio...
scikit-learn.org
uniform 은 가까이 있는 포인트에 같은 가중치를 적용하는 것이고, distance는 거리가 좁을수록 많은 가중치를 부여하는 방식이다. 따라서 가까이 있는 포인트의 영향을 더 받게 된다.
n_neighbors 는 3,4,5 값을 넣어주어 주변의 몇개의 이웃까지 고려할 것인지를 정해준다.
파라미터 설정은 끝났으니 그리드 서치 메서드에 전달해주어 fit 해주면 최적의 파라미터 값을 찾아준다.
#최적의 파라미터 값 확인
grid_search.best_params_
#테스트 세트에서의 최고 성적은 대략 97% 의 정확도.
grid_search.best_score_
각각의 호출은 두 값을 출력한다.
best_params_ : {'n_neighbors': 4, 'weights': 'distance'}
best_score_ : 0.9716166666666666
그리드서치로 최적의 파라미터는 distance 와 4개의 이웃을 살펴보는 것임을 찾아냈고, 최고 성능은 약 97%의 점수가 나왔다.
from sklearn.metrics import accuracy_score
#테스트 세트로 훈련이 아닌 예측을 하자.
y_pred = grid_search.predict(X_test)
accuracy_score(y_test, y_pred)
마지막으로 테스트 세트(아까 뗴어놓았던 10000개의 이미지 샘플) 에서 예측을 해보면 0.9714의 값이 나오는 것을 확인할 수 있다. 따라서 테스트 세트에서 97% 의 정확도를 달성하려는 목표에 도달했다.
전체 코드는 아래를 가면 볼 수 있다.
https://github.com/chataeg/handson-ML/blob/master/jupyter/examples/Hands_On_ch03_1.ipynb
GitHub - chataeg/handson-ML
Contribute to chataeg/handson-ML development by creating an account on GitHub.
github.com