- 공유 링크 만들기
- 이메일
- 기타 앱
이진분류(Binary Classification): SGDClassifier
내용
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns sns.set_style("darkgrid")
SGDClassifier
다음은 make_classification()
함수를 사용하여 2개의 특징과 2개의 클래스로 구성된 라벨인 데이터를 생성한것입니다.
from sklearn.datasets import make_classification
X,y=make_classification(n_samples=1000, n_features=2,n_informative=1,n_redundant=0, n_clusters_per_class=1, random_state=1) X.shape, y.shape
((1000, 2), (1000,))
ytr[:10]
array([0, 0, 0, 0, 1, 0, 1, 0, 0, 0])
위 데이터를 모델 생성을 위한 훈련데이터와 모델 검정을 위한 검정데이터로 구분하였습니다.
from sklearn.model_selection import train_test_split
Xtr, Xte, ytr, yte=train_test_split(X, y, test_size=0.3, random_state=2)
이진 분류기를 생성하기 위해 SGDClassifier()
클래스를 사용합니다.
- 확률적 경사하강법(Stochastic Gradient Descent)을 적용한 정규화된 선형 분류모델(경사하강법참조)
- 계산값 < 0 &rightarr; 0(Negative)
- 계산값 > 0 &rightarr; 1(Positive)
from sklearn.linear_model import SGDClassifier
sgd_clf=SGDClassifier(random_state=2) sgd_clf.fit(Xtr, ytr) sgd_clf
SGDClassifier SGDClassifier(random_state=2)
이 분류기는 식 1과 같은 선형 모델을 생성합니다. .codf_, .intercept_
속성으로 계수(가중치, W)와 편차(b)를 확인할 수 있습니다.
$$\tag{식 1}\hat{y}=WX^T+b$$
cf, inter=sgd_clf.coef_, sgd_clf.intercept_ cf, inter
(array([[ 2.5322399, -0.0756492]]), array([-0.86262289]))
식 1과 같은 선형모델에 의한 예측값은 메소드 .decision_function()
에 의해 계산됩니다. 예를 들어 특징 X[0, :]에 대한 결정함수를 식 1과 이 메소드를 사용하여 계산해보면 다음과 같습니다.
decision-function: SGDClassifier는 선형모형이므로 이 함수는 분리된 초평면(hyperplane)에 대한 부호 거리를 반환합니다. 단순히 선형모형에서의 예측지를 나타냅니다. 예를 들어 Xtr의 첫번째 데이터에 대해 다음 식과 같이 모델을 적용한 결과가 결정함수의 결과가 됩니다.
cf@Xtr[0,:].reshape(1,-1).T+inter
array([[-3.50941501]])
sgd_clf.decision_function(Xtr[0,:].reshape(1,-1))
array([-3.50941501])
라벨과 같은 0 또는 1과 같은 최종 예측값은 .predict()
메소드로 확인 할 수 있습니다. 이 결과와
pre_tr=sgd_clf.predict(Xtr) pre_tr[:10]
array([0, 0, 0, 0, 1, 0, 1, 0, 0, 0])
모델의 정확도는 라벨과 위의 예측치와의 일치정도로 파악할 수 있습니다. 훈련데이터와 검정데이터의 정확도는 다음과 같이 계산됩니다.
np.mean(pre_tr == ytr)
0.9914285714285714
pre_te=sgd_clf.predict(Xte) np.mean(pre_te == yte)
1.0
.score(X, y)
메소드를 사용하여 정확도를 계산할 수 있습니다.
sgd_clf.score(Xtr, ytr)
0.9914285714285714
sgd_clf.score(Xte, yte)
1.0
모형평가:교차검증(Cross-Validation)
SGDClassifier 모델의 평가하기 위해 3개의 폴드를 사용하여 교차검증을 실시하는 sklearn.model_selection.cross_val_score(estimator, X, y, cv, scoring, …)
함수를 사용합니다. 이 함수의 주요 인수들의 내용은 다음과 같습니다.
- cv: 는 교차평가의 분류 mechanism을 지정
- 정수: starified KFold 교차평가를 사용하여 분류하는 그룹수
- None: 5-Fold cross validation을 지정한 것과 같음
- scoring: 평가방식으로 지정하는 것으로 score(estimator, X, y) 또는 "accuracy"와 같이 단일한 metric이 될 수도 있습니다.
from sklearn.model_selection import cross_val_score, cross_val_predict
cross_val_score(sgd_clf, Xtr, ytr, cv=3, scoring="accuracy")
array([0.98717949, 0.99141631, 0.99570815])
위 결과는 교차검증을 위해 구분된 각 데이터들의 정확도를 나타냅니다.
다음 어떤 기능도 없는 추정기에 의한 결과를 평가해 봅니다. 이러한 추정기는 다음과 같이 BaseEstimator()
를 상속한 클래스를 적용합니다.
BaseEstimator는 sklearn의 모든 추정기가 상속하는 기본적인 추정기입니다. 다음에서 작성한 추정기는 fit() 메소드에 어떤 기능도 부여하지 않았습니다. 이 데이터의 라벨(반응변수)은 0과 1 두개의 클래스로 구성되므로 예측치와 관측치의 일치율이 50%가 될 것으로 예상되며 이와 유사한 결과가 반환됩니다. 이에 비해 위의 평가결과는 높은 것이라 할 수 있습니다.
from sklearn.base import BaseEstimator
class NeverClassifier(BaseEstimator): def fit(self, X, y=None): pass def predict(self, X): return np.zeros((len(X), 1))
nofit=NeverClassifier() nofitEst=cross_val_score(nofit, Xtr, ytr, cv=3, scoring="accuracy") nofitEst
array([0.43589744, 0.53648069, 0.51072961])
혼동 행렬(Confusion Matrix)
분류기의 성능을 평가하는 훨씬 더 나은 방법은 혼동 행렬을 보는 것입니다. 일반적인 아이디어는 클래스 A의 인스턴스가 클래스 B로 분류되는 횟수를 세는 것입니다.
혼동 행렬을 계산하려면 먼저 예측 세트가 있어야 실제 대상과 비교할 수 있습니다. 이 비교에 대한 교차검증을 위해 cross_val_predict()
함수를 사용할 수 있습니다.
다음 코드에 사용하는 cross_val_predict() 함수는 cross_val_score()와 같이 k-flod 검증을 수행하지만 평가점수 대신 예측을 반환합니다. 혼동행렬은 sklearn.metrics.confusion_matrix(y_ture, y_predict)
함수를 적용할 수 있습니다.
ytrpred=cross_val_predict(sgd_clf, Xtr, ytr, cv=3) ytrpred[:10]
array([0, 0, 0, 0, 1, 0, 1, 0, 0, 0])
from sklearn.metrics import confusion_matrix, classification_report
confusion_matrix(ytr,ytrpred)
array([[343, 3], [ 3, 351]], dtype=int64)
위 결과는 다음과 같습니다.
predicted class | |||
0(P) | 1(N) | ||
actual class | 0(P) | 343(TP) | 3(FP) |
1(N) | 3(FN) | 351(TN) |
클래스 0, 1을 각각 P, N으로 간주하고 actual과 predicted가 같은 경우 T, 다른 경우 F로 표현하면 위표는 다음과 같이 나타낼 수 있습니다.
- TP=343
- TN=351
- FP=3
- FN=3
위 항목으로부터 이 결과의 평가를 위해 정확도(Accuracy), 정밀도(Precision), 재현율(Recall), 그리고 F1-score를 식 2와 같이 계산할 수 있습니다.
- 정확도(Accuracy): 전체 중에 올바른 분류의 정도
- 정밀도(Precision): 긍정값(목표값)을 올바르게 분류하는 정도(실제 목표값 중에 예측한 목표값) 직관적으로 분류자가 음성(목표가 아닌 값)인 샘플을 양성(목표값)으로 분류하지 않는 성능을 나타냄
- 재현율(Recall): 긍정값(목표값)을 올바르게 분류하는 정도(예측한 목표값 중에 실제 목표값) 직관적으로 양성(목표값)을 찾는 성능을 나타냄
- F1-score: 재현율과 정밀도의 조화평균입니다.
\begin{align}\text{Accuracy}&=\frac{\text{TP + TN}}{\text{TP + FP +TN + FN}}\\&=\frac{343+351}{700}\\&=0.99\\ \tag{식 2}\text{Precision}&=\frac{\text{TP}}{\text{TP + FP}}\\&=\frac{343}{346}\\&=0.99\\ \text{Recall}&=\frac{\text{TP}}{\text{TP + FN}}\\&=\frac{343}{346}\\&=0.99\\ \text{F1-score}&=\frac{2\cdot\text{Precsion}\cdot\text{Recall}}{\text{Precsion}+\text{Recall}}\\&=\frac{2\cdot 0.99 \cdot 0.99}{0.99+0.99}\\&=0.99\end{align}
조화평균(harmonic mean)은 각 값의 역수에 대한 산술평균입니다. 예를 들어 두 수 a,b의 조화평균은 식 3과 같이 계산됩니다.
$$\tag{식 3}\text{조화평균}=\frac{2}{\frac{1}{a} + \frac{1}{b}}=\frac{2ab}{a+b}$$
위 결과는 sklearn.metrics.classificaion_report(y_true, y_predict)
함수에 의해 확인할 수 있습니다. sklearn.metrics 클래스에서 각각의 값을 계산하는 함수들을 사용할 수 있습니다.
cm_re=classification_report(ytr, ytrpred) print(cm_re)
precision recall f1-score support 0 0.99 0.99 0.99 346 1 0.99 0.99 0.99 354 accuracy 0.99 700 macro avg 0.99 0.99 0.99 700 weighted avg 0.99 0.99 0.99 700
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
acc=accuracy_score(ytr, ytrpred) prec=precision_score(ytr, ytrpred) rec=recall_score(ytr, ytrpred) f1sc=f1_score(ytr, ytrpred) print(f"accuracy:%.2f\nprecision:%.2f\nrecall:%.2f\nf1-score:%.2f" %(acc, prec, rec, f1sc))
accuracy:0.99 precision:0.99 recall:0.99 f1-score:0.99
교차검증의 함수 cross_val_predict(method="decision_function")
의 mehod 인수를 결정함수로 지정함으로서 그 결과를 확인할 수 있습니다. 이 결과에 대한 kde 그래프는 다음과 같습니다.
y_score=cross_val_predict(sgd_clf, Xtr, ytr, cv=3, method="decision_function")
plt.figure(figsize=(4,3)) sns.kdeplot(x=y_score) plt.xlabel("decision function of y") plt.ylabel("KDE") plt.show()
위 결과에 의하면 결정함수 0을 기준으로 명확히 분리된 형태를 보입니다.
실제 양성(목표값)에서 양성의 비율인 정밀도와 예측 양성중 실제 양성의 비율인 재현율은 분류의 기준에 따라 중요도가 달라질 수 있습니다. 그 기준을 생성된 선형모델에서의 예측치 즉, 결정함수(decision function)를 한 지점으로 지정할 수 있습니다. sklarn.metrics.precision_recall_curve(y_true, y_score)
함수를 사용하여 모델에 적용된 특성들로부터 예측된 각 값에 따라 정밀도와 재현율의 변화 경향을 파악할 수 있습니다. 이 함수의 인수 y_score는 모델에 의한 결정함수값입니다.
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds=precision_recall_curve(ytr, y_score)
f, (ax1, ax2)=plt.subplots(1, 2, figsize=(7, 3)) ax1.plot(thresholds,precisions[1:], color="b", label="precision") ax1.plot(thresholds,recalls[1:], color="r", label="recall") ax1.set_xlabel("threshold") ax1.set_ylabel("ratio") ax1.legend(loc="best") ax2.plot(recalls, precisions) ax2.set_xlabel("recall") ax2.set_ylabel("precision") plt.show()
위의 왼쪽 그래프는 threshold가 0 부근을 기준으로 정밀도와 재현율의 경향이 전환됨을 보입니다. 즉, 이 지점에서 정밀도와 재현율의 최대를 나타냅니다. 이것은 위의 결정함수에 대한 kde 그래프와 같은 결과를 나타냅니다.
댓글
댓글 쓰기