
머신러닝 분류 모델을 만들고 나면 가장 먼저 확인하게 되는 것이 성능 평가 지표입니다.
그중에서도 가장 직관적이고 많이 사용되는 지표가 바로 **정확도(Accuracy)**입니다.
정확도는 “얼마나 많이 맞췄는가?”를 수치로 보여주기 때문에 이해하기 쉽습니다.
하지만 이진 분류(Binary Classification) 문제에서는 데이터의 분포에 따라
정확도가 모델 성능을 심각하게 왜곡할 수 있는 지표가 되기도 합니다.
이번 1편에서는
- 분류 성능 평가 지표 전체 개요
- 정확도(Accuracy)의 정의
- 정확도가 왜 이진 분류에서 ‘양날의 검’이 되는지
- 타이타닉 데이터와 숫자 이미지 데이터를 활용한 예제
를 통해 정확도의 한계를 직관적으로 이해하는 것을 목표로 합니다.
분류 성능 평가지표 전체 개요
회귀(Regression)는 보통 실제 값과 예측 값의 차이를 기준으로 성능을 평가합니다.
하지만 분류(Classification), 특히 이진 분류에서는 상황이 다릅니다.
분류 문제에서는 다음과 같은 여러 지표를 함께 고려합니다.
- 정확도 (Accuracy)
- 오차 행렬 (Confusion Matrix)
- 정밀도 (Precision)
- 재현율 (Recall)
- F1 Score
- ROC-AUC
이번 1편에서는 이 중 **정확도(Accuracy)**에만 집중합니다.
나머지 지표들은 2~4편에서 순차적으로 다룹니다.
1. 정확도(Accuracy)란 무엇인가
정의
**정확도(Accuracy)**는 전체 예측 중에서 정답을 맞힌 비율을 의미합니다.
수식으로 표현하면 다음과 같습니다.
정확도 = (정확히 예측한 데이터 수) / (전체 데이터 수)
즉,
- 100개 중 90개를 맞히면 정확도는 0.9
- 10개 중 9개를 맞히면 역시 정확도는 0.9
이처럼 계산 방식이 매우 단순하고 직관적입니다.
2. 정확도의 문제점: 이진 분류에서 왜 위험한가
이진 분류에서는 보통 다음과 같은 상황이 많습니다.
- 정상 vs 이상
- 생존 vs 사망
- 스팸 vs 정상 메일
이때 한쪽 클래스가 압도적으로 많은 불균형 데이터가 자주 등장합니다.
이런 경우, 모델이 “아무 생각 없이 다수 클래스만 예측해도”
정확도가 높게 나오는 문제가 발생합니다.
이제 코드로 직접 확인해보겠습니다.
3. 타이타닉 데이터로 보는 정확도의 함정
3-1. 의미 없는 더미 분류기(Dummy Classifier) 생성
아래 클래스는 전혀 학습을 하지 않는 가짜 분류기입니다.
오직 Sex 컬럼만 보고, 매우 단순한 규칙으로 생존 여부를 예측합니다.
import numpy as np
from sklearn.base import BaseEstimator
class MyDummyClassifier(BaseEstimator):
"""
매우 단순한 규칙 기반 분류기
- Sex 값이 1이면 무조건 사망(0)
- Sex 값이 0이면 무조건 생존(1)
실제 학습은 전혀 하지 않음
"""
def fit(self, X, y=None):
# 학습 과정이 전혀 없음
pass
def predict(self, X):
# 예측 결과를 담을 배열 생성
pred = np.zeros((X.shape[0], 1))
for i in range(X.shape[0]):
# 성별이 남자(1)면 사망(0)
if X['Sex'].iloc[i] == 1:
pred[i] = 0
# 여자면 생존(1)
else:
pred[i] = 1
return pred
3-2. 타이타닉 데이터 로딩 및 전처리
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 타이타닉 데이터 로딩
titanic_df = pd.read_csv('./titanic/titanic_train.csv')
# 타깃(레이블): 생존 여부
y_titanic_df = titanic_df['Survived']
# 입력 피처
X_titanic_df = titanic_df.drop("Survived", axis=1)
# 이전 편에서 정의한 전처리 함수 적용
X_titanic_df = transform_features(X_titanic_df)
# 학습/테스트 데이터 분리
X_train, X_test, y_train, y_test = train_test_split(
X_titanic_df,
y_titanic_df,
test_size=0.2,
random_state=0
)
3-3. 더미 분류기의 정확도 확인
# 더미 분류기 생성
myclf = MyDummyClassifier()
# 학습 (실제로는 아무 것도 하지 않음)
myclf.fit(X_train, y_train)
# 예측 수행
mypredictions = myclf.predict(X_test)
# 정확도 계산
print(f"정확도 : {accuracy_score(y_test, mypredictions)}")

👉 놀랍게도, 학습도 안 한 모델이 꽤 그럴듯한 정확도를 보여줍니다.
이 모델은
- 패턴을 학습하지도 않았고
- 머신러닝이라고 부르기도 민망한 규칙 기반 코드
임에도 불구하고 **정확도만 보면 “괜찮아 보이는 모델”**이 됩니다.
4. 극단적인 예: 모든 값을 0으로 예측해도 높은 정확도?
이번에는 숫자 이미지 데이터셋(digits)을 사용합니다.
4-1. 숫자 7만 찾는 이진 분류 문제
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.base import BaseEstimator
from sklearn.metrics import accuracy_score
import numpy as np
import pandas as pd
class MyFakeClassifier(BaseEstimator):
"""
어떤 입력이 들어와도 무조건 0만 예측하는 분류기
"""
def fit(self, X, y):
pass
def predict(self, X):
return np.zeros((len(X), 1), dtype=bool)
# 숫자 이미지 데이터 로딩
digits = load_digits()
# 타깃: 숫자 7이면 1, 아니면 0
y = (digits.target == 7).astype(int)
# 학습/테스트 분리
X_train, X_test, y_train, y_test = train_test_split(
digits.data,
y,
random_state=11
)
print(f"테스트 레이블 분포:\n{pd.Series(y_test).value_counts()}")
4-2. 모든 값을 0으로 예측한 결과
fakeclf = MyFakeClassifier()
fakeclf.fit(X_train, y_train)
fakepred = fakeclf.predict(X_test)
print(f"모든 예측을 0으로 했을 때 정확도 : {accuracy_score(y_test, fakepred)}")

👉 숫자 7을 하나도 맞히지 못했음에도 불구하고, 정확도는 매우 높게 나옵니다.
이유는 간단합니다.
- 숫자 7은 전체 데이터에서 매우 적음
- 전부 0으로 예측해도 대부분은 “맞은 것”으로 계산됨
즉, 정확도는 다수 클래스에만 유리한 지표입니다.
5. 정확도는 왜 ‘양날의 검’인가
정리하면 다음과 같습니다.
- 정확도는 직관적이고 이해하기 쉬움
- 하지만 불균형 데이터에서는 모델의 실제 성능을 숨길 수 있음
- “아무 것도 안 하는 모델”도 높은 정확도를 얻을 수 있음
그래서 이진 분류에서는
👉 정확도 하나만으로 모델을 평가하지 않습니다.
이번 1편에서는 분류 성능 평가지표 중 **정확도(Accuracy)**를 집중적으로 살펴봤습니다.
핵심 정리입니다.
- 정확도는 가장 기본적이지만 가장 위험한 지표일 수 있습니다.
- 특히 이진 분류 + 불균형 데이터에서는 성능을 왜곡합니다.
- 따라서 정확도는 다른 지표들과 함께 반드시 보완적으로 사용해야 합니다.
다음 2편에서는
- 오차 행렬(Confusion Matrix)
- 정밀도(Precision)
- 재현율(Recall)
- 그리고 두 지표 사이의 트레이드오프 관계
를 그림과 예제를 통해 훨씬 더 직관적으로 설명하겠습니다.
'Programming' 카테고리의 다른 글
| [분류 성능 평가지표 3편] F1 Score·ROC-AUC로 이진 분류 성능 완성하기 (0) | 2025.12.13 |
|---|---|
| [분류 성능 평가지표 2편] 오차행렬·정밀도·재현율 그리고 트레이드오프 (0) | 2025.12.13 |
| ChromeDriver 버전 불일치로 발생하는 SessionNotCreatedException 해결 방법(undetected-chromedriver 기준) (0) | 2025.12.10 |
| [6편] 타이타닉 생존 예측 풀 파이프라인: 전처리부터 교차검증·튜닝까지 한 번에 정리하기 (0) | 2025.12.10 |
| [5편] 머신러닝 데이터 전처리 기본기: 인코딩·스케일링 실습 정리개요 (0) | 2025.12.10 |