🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

모델 평가 지표 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 2. · 12 Views

모델 평가 지표 완벽 가이드

머신러닝 모델의 성능을 측정하는 다양한 평가 지표를 알아봅니다. 정확도부터 ROC 커브까지, 실무에서 반드시 알아야 할 핵심 지표들을 초급자도 이해할 수 있도록 쉽게 설명합니다.


목차

  1. 정확도(Accuracy) 이해
  2. 정밀도와 재현율
  3. F1 Score 계산
  4. 혼동 행렬(Confusion Matrix)
  5. ROC 커브와 AUC
  6. 회귀 평가 지표(MSE, RMSE, R2)

1. 정확도(Accuracy) 이해

김개발 씨는 처음으로 머신러닝 모델을 만들어 보았습니다. 학습을 마친 모델이 정확도 95%를 달성했다는 결과를 보고 뿌듯해하며 팀장님께 보고했습니다.

그런데 팀장님의 반응이 예상과 달랐습니다. "정확도만 보면 안 돼요.

데이터가 불균형하면 정확도는 거짓말을 할 수 있거든요."

**정확도(Accuracy)**는 전체 예측 중에서 맞힌 예측의 비율을 의미합니다. 마치 시험에서 100문제 중 몇 문제를 맞혔는지 계산하는 것과 같습니다.

가장 직관적이고 이해하기 쉬운 지표이지만, 데이터 불균형 상황에서는 함정에 빠질 수 있습니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import accuracy_score
import numpy as np

# 실제 정답과 모델의 예측값
y_true = [1, 0, 1, 1, 0, 1, 0, 0, 1, 1]
y_pred = [1, 0, 1, 0, 0, 1, 0, 1, 1, 1]

# 정확도 계산: 맞힌 개수 / 전체 개수
accuracy = accuracy_score(y_true, y_pred)
print(f"정확도: {accuracy:.2%}")  # 출력: 정확도: 80.00%

# 직접 계산해보기
correct = sum(t == p for t, p in zip(y_true, y_pred))
total = len(y_true)
manual_accuracy = correct / total
print(f"직접 계산: {manual_accuracy:.2%}")

김개발 씨는 신용카드 사기 탐지 모델을 만들고 있었습니다. 데이터를 살펴보니 전체 거래 10만 건 중 사기 거래는 겨우 100건에 불과했습니다.

모델을 학습시키고 정확도를 측정하니 무려 99.9%가 나왔습니다. 김개발 씨는 기뻤지만, 팀장님은 고개를 저었습니다.

"김 개발자, 만약 모델이 모든 거래를 정상이라고 예측하면 어떻게 될까요?" 김개발 씨는 잠시 생각해보았습니다. 10만 건 중 9만 9,900건이 정상이니까, 모두 정상이라고 찍어도 정확도가 99.9%가 됩니다.

하지만 이런 모델은 사기를 단 한 건도 잡아내지 못하는 무용지물입니다. 정확도란 무엇일까요?

쉽게 말해 전체 문제 중에서 맞힌 문제의 비율입니다. 수학 시험에서 100문제 중 80문제를 맞히면 정확도는 80%가 됩니다.

머신러닝에서도 마찬가지입니다. 모델이 100개의 데이터를 예측했을 때, 그중 80개를 정확하게 맞혔다면 정확도는 80%입니다.

수식으로 표현하면 다음과 같습니다. 정확도는 (참 양성 + 참 음성) / 전체 데이터 수입니다.

여기서 **참 양성(True Positive)**은 양성을 양성으로 맞힌 것이고, **참 음성(True Negative)**은 음성을 음성으로 맞힌 것입니다. 위의 코드를 살펴보면, sklearn 라이브러리의 accuracy_score 함수를 사용하여 손쉽게 정확도를 계산할 수 있습니다.

y_true는 실제 정답이고, y_pred는 모델의 예측값입니다. 10개의 데이터 중 8개를 맞혔으니 정확도는 80%가 됩니다.

그렇다면 정확도는 언제 유용할까요? 데이터가 균형 있게 분포되어 있을 때 정확도는 좋은 지표입니다.

예를 들어 스팸 메일과 일반 메일이 50대 50의 비율로 섞여 있다면, 정확도는 모델의 성능을 잘 반영합니다. 하지만 앞서 김개발 씨가 겪은 것처럼, 데이터가 불균형하면 정확도는 믿을 수 없습니다.

희귀병 진단, 사기 탐지, 이상 감지 등 한쪽 클래스가 극히 적은 경우에는 정확도만으로 모델을 평가하면 큰 오류를 범할 수 있습니다. 실무에서는 정확도를 기본 지표로 확인하되, 반드시 다른 지표들과 함께 살펴봐야 합니다.

특히 비즈니스 관점에서 어떤 오류가 더 치명적인지 고려해야 합니다. 암 진단에서 암 환자를 정상이라고 잘못 판단하는 것과, 정상인을 암 환자라고 잘못 판단하는 것 중 어느 쪽이 더 심각할까요?

박시니어 씨가 김개발 씨에게 조언했습니다. "정확도는 시작점이야.

하지만 진짜 좋은 모델인지 판단하려면 다른 지표들도 알아야 해. 다음으로 정밀도와 재현율을 배워볼까?"

실전 팁

💡 - 데이터 불균형이 심할 때는 정확도만 믿지 말고 다른 지표와 함께 확인하세요

  • accuracy_score 함수 사용 시 normalize=False를 주면 비율 대신 맞힌 개수를 반환합니다

2. 정밀도와 재현율

김개발 씨는 스팸 필터를 개선하는 프로젝트를 맡았습니다. 테스트 결과, 스팸을 잘 걸러내긴 하는데 가끔 중요한 업무 메일까지 스팸함으로 보내버리는 문제가 있었습니다.

반대로 설정을 느슨하게 하면 스팸이 받은편지함으로 들어왔습니다. 박시니어 씨가 말했습니다.

"이건 정밀도와 재현율의 트레이드오프야."

**정밀도(Precision)**는 양성이라고 예측한 것 중 실제로 양성인 비율이고, **재현율(Recall)**은 실제 양성 중에서 양성이라고 예측한 비율입니다. 마치 경찰이 범인을 잡을 때, 정밀도는 체포한 사람 중 진짜 범인의 비율이고, 재현율은 전체 범인 중 체포된 범인의 비율과 같습니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import precision_score, recall_score

# 암 진단 예시: 1은 암 환자, 0은 정상
y_true = [1, 1, 1, 1, 0, 0, 0, 0, 0, 0]  # 실제: 암 4명, 정상 6명
y_pred = [1, 1, 0, 0, 1, 0, 0, 0, 0, 0]  # 예측: 암 3명, 정상 7명

# 정밀도: 암이라고 예측한 것 중 실제 암인 비율
precision = precision_score(y_true, y_pred)
print(f"정밀도: {precision:.2%}")  # 3명 예측 중 2명 정답 = 66.67%

# 재현율: 실제 암 환자 중 암이라고 예측한 비율
recall = recall_score(y_true, y_pred)
print(f"재현율: {recall:.2%}")  # 4명 중 2명 탐지 = 50.00%

김개발 씨가 스팸 필터 문제로 고민하고 있을 때, 박시니어 씨가 쉬운 비유를 들어주었습니다. "그물로 물고기를 잡는다고 생각해봐.

그물코가 촘촘하면 작은 물고기까지 다 잡히지만, 돌멩이나 쓰레기도 같이 잡혀. 그물코가 넓으면 쓰레기는 안 잡히지만, 물고기도 빠져나가고.

정밀도와 재현율이 바로 이런 관계야." 정밀도는 내가 양성이라고 예측한 것들이 얼마나 정확한지를 나타냅니다. 스팸 필터에서 정밀도가 높다는 것은 스팸이라고 분류한 메일이 대부분 진짜 스팸이라는 뜻입니다.

즉, 중요한 메일이 스팸함에 잘못 들어가는 일이 적습니다. 재현율은 실제 양성 중에서 내가 얼마나 빠짐없이 찾아냈는지를 나타냅니다.

스팸 필터에서 재현율이 높다는 것은 실제 스팸 중 대부분을 스팸함으로 보냈다는 뜻입니다. 즉, 스팸이 받은편지함으로 들어오는 일이 적습니다.

위의 코드는 암 진단 시나리오를 다루고 있습니다. 실제 암 환자 4명 중 모델은 2명만 암이라고 예측했습니다.

그리고 암이라고 예측한 3명 중 실제 암 환자는 2명입니다. 따라서 정밀도는 2/3인 약 66.67%이고, 재현율은 2/4인 50%입니다.

정밀도와 재현율 중 무엇이 더 중요할까요? 이것은 비즈니스 상황에 따라 다릅니다.

암 진단에서는 재현율이 더 중요합니다. 암 환자를 정상이라고 놓치면 치료 시기를 놓쳐 생명이 위험해질 수 있습니다.

정상인을 암 환자로 잘못 진단해도 추가 검사로 확인할 수 있지만, 암 환자를 놓치는 것은 돌이킬 수 없습니다. 반면 스팸 필터에서는 정밀도가 더 중요할 수 있습니다.

중요한 업무 메일이 스팸함으로 가면 큰 문제가 생길 수 있습니다. 스팸이 몇 개 들어오는 것은 사용자가 직접 삭제하면 되지만, 중요한 메일을 놓치는 것은 비즈니스에 치명적입니다.

이 두 지표는 서로 트레이드오프 관계에 있습니다. 정밀도를 높이면 재현율이 떨어지고, 재현율을 높이면 정밀도가 떨어지는 경향이 있습니다.

마치 시소의 양쪽 끝처럼, 한쪽을 올리면 다른 쪽이 내려갑니다. 실무에서는 비즈니스 요구사항에 맞게 적절한 균형점을 찾아야 합니다.

그리고 이 균형점을 찾는 데 도움을 주는 것이 바로 다음에 배울 F1 Score입니다.

실전 팁

💡 - 양성 클래스를 놓치면 안 되는 경우(암 진단, 사기 탐지)는 재현율을 중시하세요

  • 오탐이 비용을 발생시키는 경우(스팸 필터, 추천 시스템)는 정밀도를 중시하세요

3. F1 Score 계산

김개발 씨는 정밀도와 재현율 사이에서 고민에 빠졌습니다. 어떤 모델은 정밀도가 높고 재현율이 낮았고, 어떤 모델은 그 반대였습니다.

도대체 어떤 모델을 선택해야 할까요? 박시니어 씨가 답을 알려주었습니다.

"두 지표를 하나로 합친 F1 Score를 보면 돼."

F1 Score는 정밀도와 재현율의 조화평균입니다. 마치 학교에서 국어 점수와 수학 점수를 합쳐서 종합 성적을 매기는 것처럼, 두 지표의 균형 잡힌 성능을 하나의 숫자로 표현합니다.

둘 중 하나라도 낮으면 F1 Score도 낮아지므로, 균형 잡힌 모델을 찾는 데 유용합니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import f1_score, precision_score, recall_score

# 두 모델의 예측 결과 비교
y_true = [1, 1, 1, 1, 0, 0, 0, 0]

# 모델 A: 정밀도 높고 재현율 낮음
y_pred_a = [1, 1, 0, 0, 0, 0, 0, 0]  # 조심스럽게 예측

# 모델 B: 재현율 높고 정밀도 낮음
y_pred_b = [1, 1, 1, 1, 1, 1, 0, 0]  # 공격적으로 예측

for name, pred in [("모델 A", y_pred_a), ("모델 B", y_pred_b)]:
    p = precision_score(y_true, pred)
    r = recall_score(y_true, pred)
    f1 = f1_score(y_true, pred)
    print(f"{name} - 정밀도: {p:.2f}, 재현율: {r:.2f}, F1: {f1:.2f}")

김개발 씨 앞에는 두 개의 모델이 있었습니다. 모델 A는 정밀도 90%, 재현율 40%였고, 모델 B는 정밀도 60%, 재현율 80%였습니다.

단순히 평균을 내면 둘 다 65%로 같습니다. 하지만 정말 두 모델의 성능이 같다고 할 수 있을까요?

박시니어 씨가 설명을 이어갔습니다. "산술평균은 극단적인 값을 가려주는 문제가 있어.

정밀도가 100%이고 재현율이 0%인 모델이 있다고 생각해봐. 산술평균은 50%인데, 이 모델이 쓸모 있을까?" 당연히 아닙니다.

재현율이 0%라는 것은 양성을 하나도 찾지 못했다는 뜻이니까요. 이런 문제를 해결하기 위해 조화평균을 사용합니다.

조화평균의 특징은 두 값 중 작은 값에 더 큰 영향을 받는다는 것입니다. 정밀도가 아무리 높아도 재현율이 낮으면 F1 Score가 확 떨어집니다.

반대도 마찬가지입니다. 따라서 F1 Score가 높다는 것은 정밀도와 재현율이 둘 다 적절히 높다는 의미입니다.

F1 Score의 수식은 2 곱하기 (정밀도 곱하기 재현율) 나누기 (정밀도 더하기 재현율)입니다. 위 코드의 결과를 보면, 모델 A는 정밀도 1.00, 재현율 0.50, F1 Score 0.67입니다.

모델 B는 정밀도 0.67, 재현율 1.00, F1 Score 0.80입니다. 모델 B가 F1 Score가 더 높습니다.

이는 모델 B가 정밀도와 재현율 사이에서 더 나은 균형을 이루고 있다는 뜻입니다. 하지만 F1 Score가 항상 정답은 아닙니다.

앞서 말했듯이 비즈니스 상황에 따라 정밀도나 재현율 중 하나가 더 중요할 수 있습니다. F1 Score는 두 지표가 비슷하게 중요할 때 유용한 지표입니다.

sklearn에서는 f1_score 함수로 간단히 계산할 수 있습니다. 다중 클래스 분류에서는 average 파라미터를 통해 macro, micro, weighted 등 다양한 방식으로 F1 Score를 계산할 수 있습니다.

김개발 씨는 고개를 끄덕였습니다. "이제 모델을 비교할 때 어떤 지표를 봐야 할지 감이 잡히네요.

그런데 이 모든 걸 한눈에 볼 수 있는 방법은 없을까요?" 박시니어 씨가 미소 지었습니다. "있지.

바로 혼동 행렬이야."

실전 팁

💡 - F1 Score는 정밀도와 재현율이 비슷하게 중요할 때 사용하세요

  • 다중 클래스에서는 average='macro'는 클래스별 평균, average='weighted'는 클래스 크기 가중 평균을 계산합니다

4. 혼동 행렬(Confusion Matrix)

김개발 씨는 모델의 예측 결과를 분석하다가 답답함을 느꼈습니다. 정밀도, 재현율, F1 Score 숫자만 보니 모델이 어디서 실수하는지 구체적으로 파악하기 어려웠습니다.

박시니어 씨가 다가와 화면에 뭔가를 띄웠습니다. "혼동 행렬을 그려보면 한눈에 보여."

**혼동 행렬(Confusion Matrix)**은 모델의 예측 결과를 표 형태로 정리한 것입니다. 실제 값과 예측 값의 조합을 보여주어, 모델이 어떤 유형의 오류를 범하는지 한눈에 파악할 수 있습니다.

마치 시험 후 오답 노트를 정리하는 것처럼, 모델의 약점을 진단하는 도구입니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import confusion_matrix, classification_report
import numpy as np

# 스팸 메일 분류 예시: 1은 스팸, 0은 정상
y_true = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
y_pred = [0, 0, 0, 1, 1, 1, 1, 0, 0, 1]

# 혼동 행렬 생성
cm = confusion_matrix(y_true, y_pred)
print("혼동 행렬:")
print(cm)
# [[TN, FP],    [[3, 1],
#  [FN, TP]]     [2, 4]]

# TN=3: 정상을 정상으로 (정답)
# FP=1: 정상을 스팸으로 (오탐)
# FN=2: 스팸을 정상으로 (미탐)
# TP=4: 스팸을 스팸으로 (정답)

print("\n상세 리포트:")
print(classification_report(y_true, y_pred, target_names=['정상', '스팸']))

혼동 행렬이라는 이름이 왜 붙었을까요? 모델이 혼동하는 부분을 보여주기 때문입니다.

2x2 표 형태로, 실제 값(행)과 예측 값(열)의 모든 조합을 나타냅니다. 네 가지 칸의 의미를 하나씩 살펴보겠습니다.

True Negative (TN): 실제 음성을 음성으로 정확히 예측한 경우입니다. 스팸 필터에서는 정상 메일을 정상으로 분류한 것입니다.

좋은 결과입니다. False Positive (FP): 실제 음성을 양성으로 잘못 예측한 경우입니다.

스팸 필터에서는 정상 메일을 스팸으로 잘못 분류한 것입니다. 이를 오탐(False Alarm) 또는 1종 오류라고 부릅니다.

False Negative (FN): 실제 양성을 음성으로 잘못 예측한 경우입니다. 스팸 필터에서는 스팸을 정상으로 잘못 분류한 것입니다.

이를 미탐(Miss) 또는 2종 오류라고 부릅니다. True Positive (TP): 실제 양성을 양성으로 정확히 예측한 경우입니다.

스팸 필터에서는 스팸을 스팸으로 정확히 분류한 것입니다. 좋은 결과입니다.

위 코드의 결과를 보면, TN은 3, FP는 1, FN은 2, TP는 4입니다. 즉, 정상 메일 4개 중 3개를 맞히고 1개를 스팸으로 오탐했습니다.

스팸 6개 중 4개를 맞히고 2개를 정상으로 미탐했습니다. 앞서 배운 지표들은 모두 혼동 행렬에서 계산됩니다.

정확도는 (TP + TN) / 전체, 정밀도는 TP / (TP + FP), 재현율은 TP / (TP + FN)입니다. classification_report 함수를 사용하면 정밀도, 재현율, F1 Score를 클래스별로 한 번에 확인할 수 있습니다.

실무에서 모델을 분석할 때 가장 먼저 확인하는 리포트입니다. 혼동 행렬은 다중 클래스 분류에서 더욱 유용합니다.

3개 이상의 클래스가 있을 때, 어떤 클래스를 어떤 클래스로 자주 혼동하는지 패턴을 파악할 수 있습니다. 예를 들어 손글씨 숫자 인식에서 3과 8을 자주 혼동한다면, 이 두 숫자를 구분하는 특징을 강화해야 한다는 인사이트를 얻을 수 있습니다.

김개발 씨가 혼동 행렬을 그려보니, 모델이 어디서 실수하는지 명확해졌습니다. "이제 어떤 부분을 개선해야 할지 알겠어요!"

실전 팁

💡 - 혼동 행렬은 시각화하면 더 직관적입니다. seaborn의 heatmap을 활용해보세요

  • 다중 클래스에서는 대각선이 높고 나머지가 낮을수록 좋은 모델입니다

5. ROC 커브와 AUC

김개발 씨는 모델의 임계값을 조정하면서 실험하고 있었습니다. 임계값을 0.5로 두니 재현율이 낮았고, 0.3으로 낮추니 정밀도가 떨어졌습니다.

박시니어 씨가 제안했습니다. "모든 임계값에서의 성능을 한 번에 보고 싶다면 ROC 커브를 그려봐."

ROC 커브는 임계값을 변화시키면서 참양성률(TPR)과 거짓양성률(FPR)의 관계를 그린 곡선입니다. AUC는 이 곡선 아래 면적으로, 1에 가까울수록 좋은 모델입니다.

마치 학생의 성적표가 한 과목이 아닌 전체 성적 분포를 보여주는 것처럼, 모델의 전반적인 분류 능력을 평가합니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import roc_curve, roc_auc_score
import numpy as np

# 모델의 예측 확률 (0~1 사이 값)
y_true = [0, 0, 0, 0, 1, 1, 1, 1]
y_scores = [0.1, 0.2, 0.4, 0.6, 0.5, 0.7, 0.8, 0.9]

# ROC 커브 계산
fpr, tpr, thresholds = roc_curve(y_true, y_scores)
print(f"FPR: {fpr}")  # 거짓양성률
print(f"TPR: {tpr}")  # 참양성률 (= 재현율)
print(f"임계값: {thresholds}")

# AUC 계산: 곡선 아래 면적 (1에 가까울수록 좋음)
auc = roc_auc_score(y_true, y_scores)
print(f"\nAUC: {auc:.4f}")  # 0.5면 랜덤, 1.0이면 완벽

분류 모델은 보통 0과 1 사이의 확률값을 출력합니다. 스팸 필터라면 이 메일이 스팸일 확률이 0.7이라고 예측하는 식입니다.

이때 몇 이상을 스팸으로 분류할지 정하는 것이 **임계값(threshold)**입니다. 임계값을 0.5로 정하면 확률 0.5 이상인 메일만 스팸으로 분류합니다.

임계값을 0.3으로 낮추면 더 많은 메일이 스팸으로 분류됩니다. 임계값을 0.8로 높이면 확실한 것만 스팸으로 분류합니다.

임계값을 바꾸면 정밀도와 재현율이 함께 변합니다. 임계값을 낮추면 재현율은 올라가지만 정밀도는 떨어집니다.

임계값을 높이면 정밀도는 올라가지만 재현율은 떨어집니다. ROC 커브는 이 모든 임계값에서의 성능을 하나의 그래프로 보여줍니다.

X축은 **거짓양성률(FPR)**로, 실제 음성 중 양성으로 잘못 예측한 비율입니다. Y축은 **참양성률(TPR)**로, 이는 재현율과 같습니다.

이상적인 모델은 어떤 모양일까요? 왼쪽 위 모서리를 향하는 커브입니다.

이는 거짓양성률은 낮고 참양성률은 높다는 뜻입니다. 반면 랜덤으로 찍는 모델은 대각선 형태가 됩니다.

**AUC(Area Under Curve)**는 ROC 커브 아래의 면적입니다. 1에 가까울수록 좋은 모델이고, 0.5면 랜덤과 다를 바 없는 모델입니다.

실무에서는 AUC 0.7 이상이면 쓸만하고, 0.8 이상이면 좋은 모델, 0.9 이상이면 훌륭한 모델로 평가합니다. AUC의 장점은 임계값에 독립적이라는 것입니다.

모델 자체의 분류 능력을 평가하므로, 서로 다른 모델을 공정하게 비교할 수 있습니다. 또한 데이터 불균형에도 비교적 강건한 지표입니다.

코드를 보면 roc_curve 함수는 FPR, TPR, 그리고 각 지점의 임계값을 반환합니다. 이 값들로 그래프를 그리면 ROC 커브가 됩니다.

roc_auc_score 함수는 AUC 값을 직접 계산해줍니다. 김개발 씨가 여러 모델의 ROC 커브를 그려보니, 어떤 모델이 전반적으로 더 좋은 성능을 내는지 한눈에 비교할 수 있었습니다.

실전 팁

💡 - AUC는 0.5보다 낮으면 레이블을 뒤집어서 확인해보세요. 음성과 양성이 바뀌었을 수 있습니다

  • 다중 클래스에서는 One-vs-Rest 방식으로 각 클래스별 ROC 커브를 그릴 수 있습니다

6. 회귀 평가 지표(MSE, RMSE, R2)

김개발 씨가 다음으로 맡은 프로젝트는 집값 예측 모델이었습니다. 분류와 달리 회귀는 연속적인 숫자를 예측합니다.

정확도나 F1 Score는 사용할 수 없었습니다. 박시니어 씨가 새로운 지표들을 소개해주었습니다.

"회귀에서는 MSE, RMSE, R2를 봐야 해."

회귀 모델은 연속적인 값을 예측하므로 분류와 다른 평가 지표가 필요합니다. MSE는 오차의 제곱 평균, RMSE는 MSE의 제곱근으로 원래 단위로 해석이 가능합니다.

R2는 모델이 데이터 변동을 얼마나 설명하는지를 0과 1 사이로 나타냅니다.

다음 코드를 살펴봅시다.

from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import numpy as np

# 실제 집값(억 원)과 예측 집값
y_true = [3.0, 4.5, 5.0, 6.2, 7.1, 8.0]
y_pred = [3.2, 4.3, 5.5, 5.8, 7.0, 8.3]

# MAE: 평균 절대 오차 (직관적)
mae = mean_absolute_error(y_true, y_pred)
print(f"MAE: {mae:.4f}억 원")  # 평균적으로 얼마나 틀렸는가

# MSE: 평균 제곱 오차 (큰 오차에 페널티)
mse = mean_squared_error(y_true, y_pred)
print(f"MSE: {mse:.4f}")

# RMSE: MSE의 제곱근 (원래 단위로 해석)
rmse = np.sqrt(mse)
print(f"RMSE: {rmse:.4f}억 원")

# R2: 결정계수 (1에 가까울수록 좋음)
r2 = r2_score(y_true, y_pred)
print(f"R2 Score: {r2:.4f}")  # 변동의 몇 %를 설명하는가

집값을 예측하는 모델이 있다고 합시다. 실제 집값이 5억인데 모델이 4억이라고 예측했다면, 오차는 1억입니다.

실제가 3억인데 4억이라고 예측했다면, 오차는 마이너스 1억입니다. 이런 오차들을 어떻게 종합해서 모델의 성능을 평가할까요?

가장 단순한 방법은 오차의 절대값 평균을 구하는 것입니다. 이것이 **MAE(Mean Absolute Error)**입니다.

"평균적으로 얼마나 틀렸는가"를 직관적으로 보여줍니다. 위 코드에서 MAE가 0.25억이라면, 평균적으로 2,500만 원 정도 오차가 있다는 뜻입니다.

**MSE(Mean Squared Error)**는 오차를 제곱해서 평균을 냅니다. 왜 제곱할까요?

두 가지 이유가 있습니다. 첫째, 양수와 음수 오차가 상쇄되지 않습니다.

둘째, 큰 오차에 더 큰 페널티를 줍니다. 1억 오차 2개보다 2억 오차 1개가 더 나쁘게 평가됩니다.

하지만 MSE는 제곱 단위이므로 해석이 어렵습니다. 집값이 억 단위인데 MSE가 0.1이라면, 이게 좋은 건지 나쁜 건지 직관적으로 알기 어렵습니다.

그래서 **RMSE(Root Mean Squared Error)**를 사용합니다. MSE에 제곱근을 씌워서 원래 단위로 돌려놓는 것입니다.

RMSE가 0.3억이라면, 대략 3,000만 원 정도의 오차가 있다고 직관적으로 이해할 수 있습니다. **R2 Score(결정계수)**는 조금 다른 관점의 지표입니다.

모델이 데이터의 변동을 얼마나 잘 설명하는지를 나타냅니다. 1에 가까우면 모델이 데이터를 거의 완벽하게 설명한다는 뜻이고, 0이면 평균값으로 예측하는 것과 다를 바 없다는 뜻입니다.

R2가 0.85라면, 데이터 변동의 85%를 모델이 설명한다는 의미입니다. 나머지 15%는 모델이 포착하지 못한 다른 요인들 때문입니다.

실무에서 R2가 0.7 이상이면 괜찮은 모델, 0.9 이상이면 좋은 모델로 평가합니다. 각 지표는 상황에 따라 선택합니다.

이상치에 민감하지 않게 평가하고 싶다면 MAE를, 큰 오차를 피하고 싶다면 MSE나 RMSE를, 모델의 설명력을 보고 싶다면 R2를 사용합니다. 김개발 씨는 집값 예측 모델의 RMSE가 약 3,000만 원, R2가 0.92라는 결과를 얻었습니다.

평균적으로 3,000만 원 정도 오차가 있지만, 집값 변동의 92%를 설명하는 꽤 괜찮은 모델이었습니다. 박시니어 씨가 정리해주었습니다.

"이제 분류든 회귀든 모델 성능을 제대로 평가할 수 있겠네. 기억해, 숫자 하나만 보지 말고 여러 지표를 종합적으로 봐야 해."

실전 팁

💡 - RMSE는 이상치에 민감하므로, 이상치가 많다면 MAE를 함께 확인하세요

  • R2가 음수가 나오면 모델이 평균보다 못하다는 뜻입니다. 모델을 재검토하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#MachineLearning#ModelEvaluation#Metrics#sklearn#Machine Learning,Python

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.