본문 바로가기
카테고리 없음

DS - Evaluation

by 횰임 2023. 1. 10.

- 정확도가 제일 만만한 평가지표이긴 하나, 불균형한 레이블 클래스를 가지는 이진 분류 모델의 경우 e.x.(1000건이 Negative이고 1건이 Postive) Negative로 예측하는 경향이 더 강해진다. 

따라서 이런 경우에 예측 정확도는 높지만 실제로는 틀린 예측일 수 있기에 정확도만으로는 모델의 신뢰도가 떨어질 수 있다.

 

- 따라서 정밀도(Precision), 재현율(Recall), F1-score, ROC 곡선과 AUC socre와 같이 여러가지 평가 지표들을 함께 고려하는 것이 좋다.

 

[정밀도와 재현율]

- 정밀도: 예측을 Positive로 하고, 실제 Postive인 데이터의 비율 (Positive를 잘 맞출수록 정밀도 높아짐)

- 재현율: 실제로 Positive인데 예측과 실제 값이 모두 Positive로 일치하는 데이터의 비율. 

 

- 이 둘은 trade-off 관계로, 어느 한 쪽을 강제로 높이면 다른 하나의 수치는 떨어질 수 있다.

따라서, 분류의 "결정 임계값(threshold)"을 조정해가면서 정밀도, 재현율이 둘 다 좋은 순간을 잡아낼 수 있다.

 

- 일반적으로 이진 분류에서는 임계값을 0.5로 정하고, 예측 확률이 이보다 크면 Positive, 작으면 Negative로 결정한다.

그래서 우리가 지금 필요한 건 개별 데이터별로 예측 확률이 어떤지 보는거 --> sklearn의 predict_proba() 메서드를 사용!

 

<predict_proba()>

입력 파라미터: featrue 데이터셋

리턴: 각 샘플이 0일 확률, 1일 확률을 한 행(column)으로 하는 2차원 배열 (행의 개수는 샘플 수와 같겠지)

pred_proba = lr_clf.predict_proba(X_test) #pred_proba -- 0일 확률, 1일 확률이 리턴됨
pred = lr_clf.predict(X_test)  #predict -- 0이냐, 1이냐가 리턴됨

print('pred_proba() 결과 Shape: {0}'.format(pred_proba.shape))
print('pred_proba 요소 3개만 추출해서 확인: \n', pred_proba[:3])

-> 샘플 개수(179)만큼의 행, 2개의 열을 갖는 2차원 배열이 리턴되었다.

 

- 사이킷런은 분류 결정 임계값(threshold)을 조절해서 정밀도와 재현율이 어떨 때 상호보완적으로 최적인지 조정할 수 있다. --> sklearn의 Binarizer 클래스를 사용!

 

<Binarizer>

객체 생성시 입력 파라미터: threshold 값

fit_transform() 메서드 - 입력 파라미터: 넘파이 ndarray (Positive 칼럼의 예측 확률 배열)

                                     - 리턴: 지정된 threshold 보다 같거나 작으면 0으로, 크면 1값으로 변환해 반환함.

 

<여러 개의 threshold값을 변경하면서 Binarizer를 이용하여 예측값 변환해보기>

thresholds = [0.4, 0.45, 0.50, 0.55, 0.60]

#threshold 바꿔가며 transform 해주는 함수
def get_eval_by_threshold(y_test, pred_proba_c1, thresholds):
	for custom_threshold in thresholds:
    	binarizer = Binarizer(threshold=custom_threshold).fit(pred_proba_c1)
        custom_predict = binarizer.transform(pred_proba_c1)
        
        print('임계값:', custom_predict)
        get_clf_eval(y_test, custom_predict)  #오차행렬, 정확도, 정밀도, 재현율 출력해줌(사용자정의)
        
get_eval_by_threshold(y_test, pred_proba[:, 1].reshape(-1,1), thresholds)

 

*헷갈릴 수 있는 것!

pred_proba[:, 1]이 뭔가?

-> 함수의 입력 파라미터로 pred_proba로 나온 배열을 넣어줘야 하는데, 우리 task에서 필요한 확률은 0일 확률과 1일 확률 중 1일 확률값이 필요하다. 따라서 [[0일 확률, 1일 확률],    에서 [:, 1] 부분이 필요한 것. 

                                  [0일 확률, 1일 확률], 

                                         .....

                                                                     ]] 

나아가서, 이 1일 확률 부분을 y_test랑 비교할 수 있으려면 2차원 배열 형태여야 하므로 reshape 해주는 거다.