분류 데이터셋으로 가장 유명한 MNIST 데이터셋을 사용하였습니다.
import numpy as np
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784',version=1)
X, y = mnist["data"], mnist["target"]
위의 코드를 이용하여 사용할 수 있습니다.
문제를 예 / 아니오 로만 구별하는 분류기가 이진 분류기입니다.
SGD(확률적 경사 하강법)Classifier를 사용해보았습니다.
가장 먼저 교차검증이 있습니다.
교차검증은 아래와 같은 kFold를 이용하거나 cross_val_socre()를 이용해서 할 수도 있습니다.
from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone
skfolds = StratifiedKFold(n_splits=3, random_state=42)
for train_index, test_index in skfolds.split(X_train, y_train_5):
clone_clf = clone(sgd_clf)
X_train_folds = X_train[train_index]
y_train_folds = y_train_5[train_index]
X_test_fold = X_train[test_index]
y_test_fold = y_train_5[test_index]
clone_clf.fit(X_train_folds, y_train_folds)
y_pred = clone_clf.predict(X_test_fold)
n_correct = sum(y_pred == y_test_fold)
print(n_correct / len(y_pred))
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train,y_train_5, cv=3, scoring="accuracy")
이때 정확도를 성능기준으로 사용하였는데,
이처럼 불균형한 데이터셋일 때는 성능 측정 지표로 좋지 않습니다.
만약 무조건 5가 아니라는 결과만 내는 분류기의 성능을 정확도를 기준으로 측정한다면
5가 데이터셋에 적게 들어있는 만큼 높은 성능이 나올 것이기 때문입니다.
이로 인해 오차 행렬에 대해 알아보아야 합니다.
confusion matrix를 보여주기 위해 cross_val_predict()를 사용하여
k겹 교차 검증을 수행하지만 평가 점수를 반환하지 않고 각 테스트 폴드에서 얻은 예측을 반환하기 하도록 합니다.
from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_train_5, y_train_pred)
왼쪽부터 차례대로
true Negative, false positive
false Negative, true Positive 입니다.
정밀도와 재현율은 트레이드오프로 둘 중 하나가 올라가면 다른 하나는 내려가기 쉽습니다.
이를 한번에 보기 편하도록 F1 score를 이용할 수도 있습니다.
F1 score는 정밀도와 재현율의 조화 평균을 말합니다.
from sklearn.metrics import f1_score
f1_score(y_train_5, y_train_pred)
먼저 precision_recall_curve로 모든 임계값에 대해 정밀도와 재현율을 계산할 수 있습니다.
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
plt.plot(thresholds, precisions[:-1],"b--",label="precision")
plt.plot(thresholds, recalls[:-1],"g-",label="recall")
plt.legend()
plt.xlabel("threshold")
plt.show()
plot_precision_recall_vs_threshold(precisions, recalls, thresholds)
FPR : 양성으로 잘못 분류된 음성 샘플의 비율, 1-TNR
TNR : 특이도
TPR : 재현율
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, linewidth=2, label=label)
plt.plot([0,1],[0,1],'k--')
plt.xlabel('FPR')
plt.ylabel('TPR')
plot_roc_curve(fpr,tpr)
plt.show()
from sklearn.metrics import roc_auc_score
roc_auc_score(y_train_5, y_scores)
다중분류에는 2가지 전략이 있다.
OvR, OvO
from sklearn.svm import SVC
svm_clf = SVC()
svm_clf.fit(X_train,y_train)
svm_clf.predict([some_digit])
some_digit_scores = svm_clf.decision_function([some_digit])
print(np.argmax(some_digit_scores))
print(svm_clf.classes_)
print(svm_clf.classes_[5])
OvO, OvR를 강제로 사용하게 할 수도 있다.
from sklearn.multiclass import OneVsRestClassifier ovr_clf = OneVsRestClassifier(SVC()) ovr_clf.fit(X_train, y_train) ovr_clf.predict([some_digit])
from sklearn.neighbors import KNeighborsClassifier
y_train_large = (y_train >= 7)
y_train_odd = (y_train %2 == 1)
y_multilabel = np.c_[y_train_large, y_train_odd]
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train, y_multilabel)
knn_clf.predict([some_digit])
y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_multilabel, cv=3)
f1_score(y_multilabel, y_train_knn_pred, average="macro")
average="weighted"