scikit-learn (3) - 선형분류 (결과평가)
1. 예측하기
꽃받침 너비가 4.7이고 꽃받침 길이가 3.1인 새로운 꽃이 있다고 가정하고, 이 꽃의 범주를 예측해보자. 예측 메소드는 인스턴스 배열을 입력받고, 예측 범주의 리스트를 반환한다. 다음과 같다
1 2 | >>> print clf.predict(scaler.transform([4.7, 3.1])) [0] | cs |
분류기가 정확했다면, 이 꽃의 범주는 세토사이다. 앞선 포스팅에서 선형 모델은 두 개의 분류를 나누는 것을 기억했다. 그러므로 예측절차는 세 개 이진 분류기의 결과를 합하고 좀 더 확실한 범주를 선택한다. 이 경우 인스턴스에서 멀리 떨어진 경계선을 선택한다. 분류기의 decision_function 메소드를 사용해 확인할 수 있다.
1 2 3 | >>> print clf.decision_function(scaler.transform([4.7, 3.1])) [[ 24.25497645 -9.30416563 -42.71765579] | cs |
2. 결과평가
1) 성능측정
분류기의 성능은 유효성의 측정이다. 가장 단순한 성능 측정은 정확도다. 분류기와 평가데이터를 고려해, 분류기가 정확하게 분류한 인스턴스의 비율을 측정한다. 먼저 훈련데이터에서 정확도를 측정해보자.
1 2 3 4 | >>> from sklearn import metrics >>> y_train_pred = clf.predict(X_train) >>> print metrics.accuracy_score(y_train, y_train_pred) 0.8125 | cs |
이 수치는 분류기가 데이터 인스턴스의 81.25%만 정확하게 분류했음을 말해준다.
2) 과적합화
훈련데이터의 정확도만을 측정하는 것은 좋지 않다. 훈련데이터를 사용해 모델을 만들었고 모델은 이 데이터에 잘 적응되었지만 미래에 형편없이 예측할 수 있다. 이 현상을 과적합화overfitting 이라고 한다.
훈련데이터를 기반으로 측정한다면 과적합화를 절대 발견할 수 없다. 그래서 훈련데이터를 기반으로 절대 측정하지 않는다. 원본 데이터셋에서 일부를 보관한 이유가 여기에 있다. 이전에 보지 못한 데이터에 대한 성능을 평가하기 위해서이다. 이번에는 평가데이터로 정확도를 다시 측정해보자.
1 2 3 | >>> y_pred = clf.predict(X_test) >>> print metrics.accuracy_score(y_test, y_pred) 0.605263157895 | cs |
테스트데이터에 대해 60%의 정확도를 얻었다. 일반적으로 테스트데이터의 정확도는 훈련데이터보다 낮은 정확도를 보인다. 목표는 훈련데이터로 훈련할 때 과적합화를 피하는 모델을 생성하는 일이다.
3. 평가함수
1) 평가함수
scikit-learn 에는 몇 가지 평가함수가 있다. 이러한 함수 문제는 이진 분류 문제와 두 범주 (긍정과 부정)로 가정한다. 앞의 예를 들자면, 긍정 범주는 아이리스 세토사인 반면, 두 품종은 합해 하나의 부정 범주가 된다.
정밀도 precision |
정확한 긍정으로 예측된 인스턴스의 비율 계산 |
재현율 recall |
정확학게 평가된 긍정 인스턴스의 비율 |
F1-점수 |
정밀도와 재현율의 조화평균 두 수를 결합해 한 자리수로 만든다 |
참과 거짓, 긍정과 부정의 관점으로 이러한 측정을 다음과 같이 정의할 수 있다.
|
예측 : 긍정 |
예측 : 부정 |
목적 경우 : 긍정 |
참 긍정 True Positive (TP) |
거짓 부정 False Negative (FN) |
목적 경우 : 부정 |
거짓 긍정 False Positive (FP) |
참 부정 True Negative (TN) |
2) 평가함수의 수식
표본의 크기 m 과 다음 식을 만든다.
m = TP + FP + FN + TN
정확도 |
(TP + TN ) / m |
정밀도 |
TP / (TP + FP) |
재현율 |
TP / (TP + FN) |
F-1 점수 |
2 * 정밀도 * 재현율 / (정밀도 + 재현율) |
1 2 3 4 5 6 7 8 | >>> print metrics.classification_report(y_test, y_pred, target_names=iris.target_names) precision recall f1-score support setosa 1.00 1.00 1.00 8 versicolor 0.38 0.27 0.32 11 virginica 0.64 0.74 0.68 19 avg / total 0.64 0.66 0.64 38 | cs |
분류기는 세토사 범주에 대해 1.0인 정밀도와 재현율을 얻었다.
정밀도는 세토사로 분류한 인스턴스의 100%가 실제 세토사 인스턴스였고, 재현율은 세토사 인스턴스의 100%가 세토사로서 분류되었음을 뜻한다.
한편 버시칼라 범주에서는 결과가 좋지 않았다. 43%의 정밀도는 단지 버시칼라로 분류된 인스턴스의 43%가 실제 버시칼라 인스턴스로 분류되었다. 또한 0.27%의 재현율은 버시칼라의 27% 인스턴스가 정확하게 분류했다.
3) 혼돈 매트릭스 confusion matrix
다른 유용한 메트릭은 혼돈 매트릭스다. ( i, j ) 칸은 범주 j 로 예측한 반면, 실제 범주가 i 인 인스턴스의 개수를 나타낸다. 좋은 분류기는 정확하게 분류된 혼돈 매트릭스의 대각선에 인스턴스 개수가 많다.
1 2 3 4 | >>> print metrics.confusion_matrix(y_test, y_pred) [[ 8 0 0] [ 0 0 11] [ 0 0 19]] | cs |
분류기는 범주가 0인 꽃을 분류할 때 평가에서 절대 틀리지 않았다. 그러나 범주가 1과 2인 꽃을 직면해서 이 꽃들을 혼동했다. 혼돈 매트릭스는 분류기가 행한 실수의 종류에 대해 유용한 정보를 준다.
4) 교차 검증 cross-validation
데이터의 분할은 훈련하는 인스턴스의 개수와 특정 속성의 분할에 의존적이므로 최종 결과에 영향을 미친다. 교차 검증은 이러한 특정 경우를 피할 수 있게 하며, 결과의 변화를 줄이고 모델에 대해 현실적인 점수를 만든다. k-중첩 교차검증의 일반적인 단계는 다음과 같다.
- k 개의 부분집합으로 나눈다.
- k-1 개 부분집합으로 훈련하고 나머지 부분 집합으로 테스트한 k 개의 모델을 만든다
- k 모델에 대해 성능을 측정하고 평균을 구한다.
먼저 선형 모델과 표준화를 파이프라인으로 합성한 에스터메이터를 만든다. 파이프라인을 사용해 각 반복에서 데이터를 표준화하고, 변환된 데이터로 훈련 및 테스트를 한다. Pipeline 클래스는 변환을 연속적으로 적용해 좀 더 복잡한 모델을 단순하게 생성하는데 사용된다.
k = 5 중첩으로, 매번 데이터의 80%로 훈련하고 남은 20%를 사용하게 한다. 기본적으로 교차검증은 성능 측정으로서 정확도를 사용하지만, 매개변수에 대해 다른 점수 함수를 지정해 측정을 선택할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 | >>> from sklearn.cross_validation import cross_val_score, KFold >>> from sklearn.preprocessing import StandardScaler >>> from sklearn.pipeline import Pipeline >>> clf = Pipeline({ >>> ('scaler', StandardScaler()), >>> ('linear_model', SGDClassifier()) >>> } >>> ) >>> cv = KFold(X.shape[0], 5, shuffle=True, random_state=33) >>> scores = cross_val_score(clf, X, y, cv=cv) >>> print scores | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-14-4c521b642cbf> in <module>() 8 ) 9 cv = KFold(X.shape[0], 5, shuffle=True, random_state=33) ---> 10 scores = cross_val_score(clf, X, y, cv=cv) 11 print scores /root/anaconda/envs/tensorflow/lib/python2.7/site-packages/sklearn/cross_validation.pyc in cross_val_score(estimator, X, y, scoring, cv, n_jobs, verbose, fit_params, pre_dispatch) 1509 1510 cv = check_cv(cv, X, y, classifier=is_classifier(estimator)) -> 1511 scorer = check_scoring(estimator, scoring=scoring) 1512 # We clone the estimator to make sure that all the folds are 1513 # independent, and that it is pickle-able. /root/anaconda/envs/tensorflow/lib/python2.7/site-packages/sklearn/metrics/scorer.pyc in check_scoring(estimator, scoring, allow_none) 271 raise TypeError( 272 "If no scoring is specified, the estimator passed should " --> 273 "have a 'score' method. The estimator %r does not." % estimator) 274 275 TypeError: If no scoring is specified, the estimator passed should have a 'score' method. The estimator Pipeline(steps=[('linear_model', SGDClassifier(alpha=0.0001, average=False, class_weight=None, epsilon=0.1, eta0=0.0, fit_intercept=True, l1_ratio=0.15, learning_rate='optimal', loss='hinge', n_iter=5, n_jobs=1, penalty='l2', power_t=0.5, random_state=None, shuffle=True, verbose=0, warm_start=False)), ('scaler', StandardScaler(copy=True, with_mean=True, with_std=True))]) does not. | cs |
k 개 점수로 배열을 구했다. 최종 수치를 얻기 위해 표준 편차와 평균을 계산한다.
1 2 3 4 | >>> from scipy.stats import sem >>> def mean_score(scores): >>> return ("Mean score: {0:.3f} (+/-{1:.3f})").format(np.mean(scores), sem(scores)) >>> print mean_score(scores) | cs |
'프로그래밍 Programming' 카테고리의 다른 글
서포터 벡터 머신과 이미지 인식 (2) - 이미지 픽셀을 사용한 학습 (0) | 2016.11.06 |
---|---|
서포터 벡터 머신과 이미지 인식 (1) - 정의 및 장점 (0) | 2016.11.06 |
scikit-learn (2) - 선형분류 (훈련데이터 만들기) (0) | 2016.11.06 |
matplotlib - <matplotlib.text.Text at 0x7fc3298533d0> (0) | 2016.11.03 |
Jupyter Notebook 셀 크기 조절하기 How to increase/decrease the cell width of the jupyter notebook in browser (0) | 2016.11.03 |