티스토리 뷰
머신러닝 모델은 여러 가지 지표로 예측 성능을 평가할 수 있습니다. 성능 평가 지표(Evaluation Metric)은 일반적으로 분류 모델이냐 회귀 모델이냐에 따라 달라집니다.
회귀의 경우 대부분 실제값과 예측값의 오차 평균값에 기반합니다. 회귀의 평가 지표는 복잡하지 않으므로 추후에 알아보겠습니다.
분류 모델의 평가 방법도 일반적으로 정답 레이블과 예측 레이블이 얼마나 정확하고 오류가 적은지에 기반하지만, 단순히 이러한 정확도만 가지고 판단하면 잘못된 평가를 초래할 수 있습니다. 이제부터 분류 모델을 위한 성능 평가 지표를 알아보되, 이진 분류에 포커스를 맞추겠습니다. 이진 분류 모델을 평가할 때는 정확도보다 더 중요시 되는 평가 지표들이 존재합니다.
분류의 평가 지표로는 정확도(Accuracy), 오차행렬(Confusion Matrix), 정밀도(Precision), 재현율(Recall), F1 스코어, ROC AUC 등이 있고, 이들은 특히 이진 분류에서 중요합니다.
정확도(Accuracy)는 정답과 예측이 얼마나 같은지를 판단하는 지표입니다. 모델의 예측 성능을 평가할 때 가장 직관적으로 생각할 수 있는 지표입니다. 하지만 이진 분류의 경우 데이터의 구성에 따라 모델의 성능이 왜곡될 수 있기 때문에 정확도 지표만으로 모델의 성능을 평가하지 않습니다.
예를들어, 타이타닉 데이터 세트에서 무조건 성별이 남성인 경우 사망으로, 여성인 경우 생존으로 예측을 하는 모델이 있다고 합시다. 해당 모델의 정확도는 꽤 높을 것으로 예상됩니다.
사이킷런의 BaseEstimator 클래스를 상속받아, 학습을 진행하는 fit() 메서드를 구현하지 않고, predict() 메서드에선 그저 데이터의 성별만을 가지고 예측을 수행하는 모델을 정의했습니다. 이처럼 사이킷런에선 BaseEstimator를 상속받으면 커스터마이즈 된 estimator를 생성할 수 있습니다.
해당 모델을 정확도 지표만으로 평가할 경우, 무려 약 0.78이라는 높은 수치를 얻을 수 있습니다. 이처럼 타이타닉 데이터 자체의 구성(남성 사망자가 여성 사망자보다 더 많다) 때문에 모델의 성능이 과대평가(왜곡)된 것을 볼 수 있습니다.
특히 불균형한 레이블 값 분포를 가진 데이터 세트를 대상으로 한 모델을 평가할 때 정확도는 적합한 평가 지표가 아닙니다. 예를들어 100개의 데이터 중에서 90개의 데이터의 레이블이 0이고, 단 10개의 데이터만 레이블이 1이라고 하면, 무조건 0으로 예측하는 모델일지라도 정확도는 90%로 매우 높기 때문입니다.
분류 모델의 평가 지표로서 정확도가 가지는 이러한 한계점을 보완하기 위해, 다른 평가 지표를 함께 사용합니다. 먼저 True/False, Positive/Negative의 4분면으로 구성된 오차 행렬(Confusion Matrix)를 알아봅시다.
이진 분류에서 성능 평가 지표로 자주 활용되는 오차 행렬은 분류 모델이 예측을 수행하면서 어떤 부분을 얼마나 헷갈리고 있는지를 보여줍니다. 즉, 모델의 예측 오류가 얼마인지와 더불어 어떤 유형의 예측 오류가 얼마나 발생하는 지를 확인할 수 있습니다.
TN, TP, FN, TP 기호에서, 앞 문자 True/False는 예측값과 실제값이 같은가/다른가를 의미합니다. 뒤의 문자 Negative/Positive는 예측 결과 값 부정(0)/긍정(1)을 나타냅니다. 이때 False Positive를 Type 1 error, False Negative를 Type 2 error라고 부릅니다.
사이킷런은 오차 행렬을 구하는 confusion_marix() 메서드를 제공합니다. 인자로 예측 결과와 정답 레이블을 제공하면 오차 행렬을 ndarray 타입으로 반환합니다. TP, TN, FP, FN 값을 조합하여 모델의 성능을 측정할 수 있는 주요 지표인 정확도(Accuracy), 정밀도(Precision), 재현율(Recall) 값을 계산할 수 있습니다.
정확도 앞서 설명했듯이, 예측값과 실제값과 얼마나 동일한가에 대한 비율이므로 TP, TN 값에 따라 좌우됩니다.
일반적으로 불균형한 레이블 분포를 가진 데이터 세트를 대상으로 하는 이진 분류 태스크에서, 중점적으로 찾아야 하는 매우 적은 수의 데이터의 레이블이 Positive(1)이고, 그렇지 않은 경우 Negative(0)을 부여하는 경우가 많습니다. 예를들어 환자의 여러 피처를 바탕으로 암에 걸렸는지 걸리지 않았는지를 판단하는 태스크에서, 암에 걸렸다는 레이블이 Positive(1)입니다.
이러한 데이터는 애초에 Positive 데이터 건수가 적기 때문에, 학습된 머신러닝 알고리즘은 임의의 데이터에 대해 Positive보다는 Negative로 더 많이 예측하는 경향이 있습니다. 애초에 Negative 레이블이 많고, 모델도 Negative로 예측하는 경향이 크므로 TN은 매우 높아집니다. 동일한 이유로 TP는 매우 작아집니다. FN과 FP 역시 작아집니다.
결과적으로 이러한 모델의 예측 성능을 정확도로 측정한다면, Positive 데이터에 대한 예측 정확도는 거의 무시된 채 Negative에 대한 예측 정확도가 큰 비중을 차지하게 되어, 전체적인 정확도가 매우 높아질 것입니다.
불균형한 데이터 세트에서 선호되는 평가 지표인 정밀도(Precision)와 재현율(Recall)에 대해 알아봅시다.
정밀도와 재현율은 Positive 데이터 예측 성능에 좀 더 초점을 맞춘 평가 지표입니다.
정밀도는 예측을 Positive로 한 모든 대상에 대해 예측이 정답 레이블과 일치한 데이터의 비율입니다. 분모인 TP + FN은 모델이 Positive로 예측한 모든 데이터의 건수입니다. 정밀도는 양성 예측도라고 불리기도 합니다.
재현율은 정답 레이블이 Positive인 모든 대상 중에서 예측이 정답 레이블과 일치한 데이터의 비율입니다. 분모인 TP + FN는 정답 레이블이 Positive인 모든 데이터의 건수입니다. 재현율은 민감도(Sensitivity) 또는 TPR(True Positive Rate)라고도 불립니다.
이진 분류 태스크의 특성에 따라 정밀도와 재현율 중 특정 지표가 더 중요할 수 있습니다. 재현율이 더 중요하게 간주되는 경우는 Positive 데이터를 Negative로 잘못 판단하면 큰 리스크가 발생하는 태스크입니다. 환자가 암에 걸렸는지를 판단하는 태스크의 경우가 그렇습니다.
보통 재현율이 정밀도보다 중요한 태스크가 많은 편이지만, 정밀도가 더 중요한 태스크도 있습니다. 스팸 메일을 분류하는 태스크에서 Positive가 스팸을 뜻하는 레이블이라고 합시다. 스팸 메일을 일반 메일로 예측하더라도 사용자의 입장에선 그저 불편함을 느끼는 정도이지만, 일반 메일을 스팸 메일로 예측한다면 메일이 아예 사용자의 메일함에서 차단되어 중요한 메일을 받지 못하는 일이 생길 수 있습니다.
요약하자면 재현율이 더 중요한 경우는 Positive를 Negative로 예측하면 리스크가 클 때이고, 정밀도가 더 중요한 경우는 Negative를 Positive로 예측하면 리스크가 클 때입니다. 보통 재현율과 정밀도는 서로 보완적인 지표로 사용됩니다. 물론 두 지표 모두 높다면 좋은 모델이겠지만, 한 수치만 높고 다른 수치는 매우 낮은 모델은 바람직하지 않습니다.
사이킷런은 정밀도 계산을 위해 precision_score(), 재현율 계산을 위해 recall_score() 메서드를 제공합니다. 평가를 간편하게 수행하기 위해 지금까지 배운 모든 평가 지표를 한 번에 계산하는 메서드를 정의했습니다.
전처리가 이미 완료된 타이타닉 데이터 세트를 불러와 로지스틱 회귀 모델로 학습한 뒤 정확도, 오차 행렬, 정밀도, 재현율을 계산했습니다.
분류 태스크의 특성상 정밀도 또는 재현율을 특별히 높이고 싶을 경우 분류의 결정 임곗값(Threshold)를 조정해 실현할 수 있습니다. 앞서 말했듯, 정밀도와 재현율을 상호 보완적인 지표이기 때문에 어느 한 쪽을 강제로 높이면 다른 한 쪽은 떨어지는 것이 일반적입니다. 이를 정밀도/재현율 트레이드 오프(Trade-Off)라고 합니다.
사이킷런의 분류 알고리즘은 예측을 수행할 때, 모든 레이블 별로 분류 결정 확률을 먼저 구합니다. 그리고 그 확률이 가장 높은 레이블로 실제 예측을 수행합니다. 이진 분류에서는 일반적으로 임곗값을 0.5, 즉 50%로 정하고 이 기준값보다 확률이 크면 Positive로, 작으면 Negative로 예측을 수행합니다.
사이킷런은 개별 데이터의 예측 확률을 반환하는 predict_proba() 메서드를 제공합니다. 해당 메서드는 학습이 완료된 Classifier 객체에서 호출이 가능하며 테스트 피처 데이터를 인자로 제공하면 각 레코드 별로 클래스 예측 확률을 반환합니다. predict() 메서드와 유사하지만, 반환 결과가 예측 클래스가 아닌 예측 확률일 뿐입니다.
타이타닉 데이터 세트의 테스트 피처 데이터 세트를 predict_proba() 메서드에 제공했습니다. 반환된 행렬의 첫 번째 칼럼은 각 레코드가 레이블 0이 될 확률이며, 두 번째 칼럼은 레이블 1이 될 확률입니다.
사실 predict() 메서드는 predict_proba() 메서드의 반환값을 바탕으로, 개별 레코드에 대해 확률이 0.5(임곗값)를 넘는 칼럼을 뽑아서 최종 예측 레이블을 결정하는 식으로 동작합니다. 그렇다면, 임곗값을 0.5가 아닌 다른 값으로 조정한 뒤에 최종 예측 레이블을 결정하게 조작할 수도 있을 것입니다. 이를 수행하기 위해 먼저 Binarizer 클래스를 살펴봅시다.
먼저 Binarizer 객체에 threshold 값을 지정합시다. 그 후 fit_transform() 메서드의 인자로 넘파이 ndarray 객체를 입력하면, 입력된 ndarry의 threshold보다 같거나 작은 요소를 0으로, 큰 요소를 1로 변환한 결괏값을 반환합니다.
Binarizer API를 이용하여 predict() 메서드를 구현할 수 있습니다. pred_proba() 메서드의 반환값에서 레이블 1의 예측 확률 칼럼만 가져와서, threshold=0.5로 설정한 Binarizer 객체에 fit_transform 시키면 됩니다. 해당 결과 바탕으로 분류 성능을 평가한 결과는 predict() 메서드의 결과를 평가한 분류 성능과 완전히 동일한 것을 확인할 수 있습니다.
분류 임곗값을 0.4로 낮춘다면 어떤 결과가 일어날까요? 확률이 0.4만 넘어도 레이블 1로 예측을 수행하기 때문에 더 많은 레코드가 레이블 1로 예측될 것입니다. Positive로 예측한 데이터 건수가 많아지니 재현율은 올랐지만, 정밀도는 내려갔습니다.
재현율과 정밀도 모두 만족할 만한 값이 도출되는 임곗값을 찾기위해, 0.4 ~ 0.6까지 0.05 단위로 임곗값을 변경해가며 분류 모델의 평가 지표를 확인해봅시다.
이처럼 다양한 임곗값에 대해 정확도, 정밀도, 재현율, 오차 행렬을 확인해가며 최적의 임곗값을 탐색할 수 있습니다.
사이킷런은 이와 유사한 API인 precision_recall_curve() 메서드를 제공합니다. 입력 파라미터는 정답 레이블 배열, 모델의 Positive 예측 확률 배열이며, 반환값은 임곗값 배열과, 임곗값별 정밀도와 재현율 배열입니다. 일반적으로 0.11 ~ 0.95 정도의 임곗값에 대한 정밀도와 재현율을 계산해줍니다.
주의해야 할 점은, 반환되는 임곗값 배열의 크기는 항상 정밀도/재현율 배열의 크기보다 1이 작다는 점입니다. 이 때문에 정밀도/재현율 배열의 마지막 원소는 무시해야 합니다. 임곗값 별 정밀도와 재현율 값의 변화를 확인함으로써 정밀도/재현율 트레이드 오프를 확인할 수 있습니다.
반환된 임곗값, 정밀도, 재현율 배열은 시각화에 활용할 수 있습니다.
임곗값을 증가시킬수록 재현율은 작아지며 정밀도는 높아지는 경향이 보입니다. 또한 임곗값 0.48 부근에서 재현율과 정밀도가 같아지고 있습니다.
정밀도나 재현율 중 하나의 수치를 극단적으로 높이는 것은 사실상 의미가 업습니다. 정밀도를 매우 높이고 싶다면 정말 확실한 경우에만 Positive로 예측을 하고 나머지는 Negative로 예측하면 됩니다. 정밀도는 TP / (TP + FP)이므로, TP = 1, FP = 0이 되면 1이 나옵니다.
재현율을 100%로 달성하고 싶다면 그냥 모든 데이터를 Positive로 예측하면 됩니다. 재현율은 TP / (TP + NF)이므로, NF = 0으로 만들면 되기 때문입니다.
정밀도와 재현율 수치가 적절하게 조합돼 분류의 종합적인 성능 평가에 사용될 수 있는 평가 지표가 필요해 보입니다. F1 스코어는 정밀도와 재현율을 결합한 지표입니다. 정밀도와 재현율이 어느 한 쪽으로 치우치지 않는 수치를 나타낼 때 상대적으로 높은 값을 가집니다.
F1 스코어의 공식은 위와 같습니다.
사이킷런은 F1 스코어를 구하기 위해 f1_score() 메서드를 제공합니다.
ROC 곡선과 이에 기반한 AUC 스코어는 이진 분류의 예측 성능 측정에서 중요하게 사용되는 지표입니다. ROC(Receiver Operation Characteristic Curve)은 우리말도 수신자 판단 곡선이라고 해석됩니다. 일반적으로 의학 분야에서 많이 사용되지만, 머신러닝의 이진 분류 모델의 예측 성능을 판단하는 중요한 평가 지표이기도 합니다.
ROC 곡선은 FPR(False Positive Rate)이 변할 때 TPR(True Positive Rate, 재현율)이 어떻게 변하는 지를 나타내는 곡선입니다. TPR은 재현율(민감도)이며, 이에 대응되는 지표로 TNR(True Negative Rate, 특이성)가 있습니다. 특이성은 실제 Negative가 정확히 예측돼야 하는 수준을 나타내며, 실제 Positive가 정확히 예측돼야 하는 수준인 재현율과 비슷합니다. TNR = TN / (FP + TN) 이고, ROC 곡선의 X축인 FPR은 FP / (FP + TN) 이므로, 1- TNR으로 표현됩니다.
ROC 곡선의 일반적인 개형은 위와 같습니다. 가운데 직선은 ROC 곡선의 최저 값입니다. 해당 직선은 동전을 무작위 던져 앞/뒤를 맞추는 랜덤 수준의 이진 분류의 ROC 직선입나다(AUC=0.5). ROC 곡선이 가운데 직선에 가까울수록 성능이 떨어지는 것이며, 멀어질수록 성능이 뛰어남을 뜻합니다. FPR은 레이블이 음성인데 모델이 양성으로 잘못 예측한 데이터의 비율이므로 이를 0으로 만들기 위해선 임곗값을 1.0으로 설정하면 되고, 반대로 1로 만들기 위해선 임곗값을 0.0으로 설정하면 됩니다.
사이킷런은 ROC 곡선을 구하는 roc_curve() 메서드를 제공합니다. 사용법은 precision_recall_curve() API와 유사하며, 단지 반환값이 FPR, TPR, 임곗값 배열일 뿐입니다.
ROC 곡선 자체는 FPR과 TPR의 변화 양상을 보기 위해 사용되며, 이진 분류의 성능 지표로 ROC 곡선의 아래 면적 크기를 나타내는 AUC 값을 사용합니다. AUC가 1에 가까울수록 좋은 모델이라고 할 수 있으며, 이를 위해선 FPR이 작은 상태에서 얼마나 큰 TPR을 얻을 수 있냐가 관건입니다.
사이킷런은 AUC 값을 구하는 roc_acu_score() 메서드를 제공합니다.
'파이썬 머신러닝 완벽 가이드' 카테고리의 다른 글
파이썬 머신러닝 완벽 가이드 : 분류(Classfication)와 결정 트리 (0) | 2023.05.01 |
---|---|
파이썬 머신러닝 완벽 가이드 : 피마 인디언 당뇨병 예측(Classification) (0) | 2023.04.30 |
파이썬 머신러닝 완벽 가이드 : 사이킷런으로 해보는 타이타닉 생존자 예측 (0) | 2023.04.29 |
파이썬 머신러닝 완벽 가이드 : 데이터 전처리 (0) | 2023.04.29 |
파이썬 머신러닝 완벽 가이드 : 사이킷런 Model Selection 모듈 (0) | 2023.04.28 |