html
혼동 행렬 마스터하기: 머신러닝 실무자를 위한 포괄적 가이드
목차
- 혼동 행렬이란?
- 혼동 행렬의 구성 요소
- 진양성(TP)
- 진음성(TN)
- 위양성(FP)
- 위음성(FN)
- 다중 클래스 혼동 행렬 이해하기
- Scikit-Learn을 사용한 혼동 행렬 구축
- 혼동 행렬 시각화
- 모델 성능 지표 해석
- 정확도
- 정밀도
- 재현율
- F1 점수
- 특이도
- 고급: 다중 클래스 혼동 행렬 처리
- 날씨 예측 데이터셋을 사용한 실용적 구현
- 결론
혼동 행렬이란?
혼동 행렬은 분류 모델의 성능을 표로 나타낸 것입니다. 실제 타겟 값과 모델이 예측한 값을 비교하여 모델의 성능을 시각화할 수 있습니다. 행렬의 각 행은 실제 클래스의 인스턴스를 나타내고, 각 열은 예측된 클래스의 인스턴스를 나타냅니다. 이 구조는 모델이 어떤 종류의 오류를 얼마나 자주 발생시키는지 쉽게 식별할 수 있게 해줍니다.
그림 1: 혼동 행렬의 기본 구조.
혼동 행렬의 구성 요소
혼동 행렬의 개별 구성 요소를 이해하는 것은 결과를 효과적으로 해석하는 데 중요합니다. 행렬은 네 가지 주요 지표로 구성됩니다:
진양성(TP)
- 정의: 긍정적으로 정확하게 분류된 인스턴스의 수.
- 예시: 모델이 내일 비가 올 것으로 예측했고 실제로 비가 올 경우, 이는 진양성입니다.
진음성(TN)
- 정의: 부정적으로 정확하게 분류된 인스턴스의 수.
- 예시: 모델이 내일 비가 오지 않을 것으로 예측했고 실제로 비가 오지 않을 경우, 이는 진음성입니다.
위양성(FP)
- 정의: 긍정적으로 잘못 분류된 인스턴스의 수.
- 예시: 모델이 내일 비가 올 것으로 예측했지만 실제로는 비가 오지 않을 경우, 이는 위양성입니다. 이는 제1종 오류라고도 합니다.
위음성(FN)
- 정의: 부정적으로 잘못 분류된 인스턴스의 수.
- 예시: 모델이 내일 비가 오지 않을 것으로 예측했지만 실제로는 비가 올 경우, 이는 위음성입니다. 이는 제2종 오류라고도 합니다.
그림 2: 혼동 행렬 내 TP, TN, FP, FN의 분류.
다중 클래스 혼동 행렬 이해하기
이진 분류는 두 개의 클래스(긍정과 부정)를 포함하지만, 다중 클래스 분류는 더 많은 클래스를 수용하기 위해 혼동 행렬을 확장합니다. 예를 들어, 세 개의 클래스—setosa, versicolor, virginica—를 포함하는 데이터셋에서는 혼동 행렬이 3x3 그리드가 됩니다. 각 행은 실제 클래스를 나타내고, 각 열은 예측된 클래스를 나타냅니다. 대각선 요소는 여전히 정확한 예측을 나타내며, 비대각선 요소는 다양한 유형의 오분류를 나타냅니다.
그림 3: 다중 클래스 혼동 행렬의 예.
Scikit-Learn을 사용한 혼동 행렬 구축
파이썬의 scikit-learn 라이브러리는 혼동 행렬을 생성하고 분석하는 데 강력한 도구를 제공합니다. 아래는 scikit-learn을 사용하여 혼동 행렬을 구축하는 단계별 가이드와 실용적인 예제입니다.
1단계: 필요한 라이브러리 가져오기
123456
import pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder, StandardScalerfrom sklearn.metrics import confusion_matrix, plot_confusion_matrix, accuracy_scorefrom sklearn.linear_model import LogisticRegressionimport matplotlib.pyplot as plt
2단계: 데이터셋 로드 및 준비
데모를 위해 Weather Australia 데이터셋을 사용합니다.
123456789101112131415161718192021222324252627
# 데이터셋 로드data = pd.read_csv('weatherAUS.csv') # 특징과 타겟 변수 정의X = data.iloc[:, :-1]y = data.iloc[:, -1] # 결측치 처리from sklearn.impute import SimpleImputerimport numpy as np # 숫자형 특징numerical_cols = X.select_dtypes(include=['int64', 'float64']).columnsimp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')X[numerical_cols] = imp_mean.fit_transform(X[numerical_cols]) # 범주형 특징string_cols = X.select_dtypes(include=['object']).columnsimp_mode = SimpleImputer(missing_values=np.nan, strategy='most_frequent')X[string_cols] = imp_mode.fit_transform(X[string_cols]) # 범주형 변수 인코딩X = pd.get_dummies(X, drop_first=True) # 타겟 변수 인코딩le = LabelEncoder()y = le.fit_transform(y)
3단계: 데이터셋 분할
1234
# 훈련 및 테스트 세트로 분할X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.20, random_state=1)
4단계: 특징 스케일링
1234
# 특징 표준화scaler = StandardScaler()X_train = scaler.fit_transform(X_train)X_test = scaler.transform(X_test)
5단계: 분류 모델 훈련
이번 예제에서는 로지스틱 회귀를 사용합니다.
123456
# 모델 초기화 및 훈련model = LogisticRegression(random_state=0, max_iter=200)model.fit(X_train, y_train) # 예측 수행y_pred = model.predict(X_test)
6단계: 혼동 행렬 생성
12345678
# 정확도 계산accuracy = accuracy_score(y_pred, y_test)print(f'Accuracy: {accuracy:.4f}') # 혼동 행렬 생성cm = confusion_matrix(y_test, y_pred)print('Confusion Matrix:')print(cm)
출력:
1234
Accuracy: 0.8297Confusion Matrix:[[21087 1058] [ 3786 2508]]
혼동 행렬 시각화
시각화는 모델 성능을 직관적으로 이해하는 데 도움이 됩니다. Scikit-learn은 혼동 행렬을 손쉽게 플로팅할 수 있는 내장 함수를 제공합니다.
1234
# 혼동 행렬 플롯plot_confusion_matrix(model, X_test, y_test, display_labels=le.classes_)plt.title('Confusion Matrix')plt.show()
그림 4: scikit-learn을 사용한 혼동 행렬 시각화.
모델 성능 지표 해석
정확도 외에도 혼동 행렬을 통해 여러 다른 성능 지표를 계산할 수 있습니다:
정확도
- 정의: 전체 인스턴스 중 올바르게 분류된 인스턴스의 비율.
- 공식:
\[
\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}
\]
- 해석: 유용하지만, 특히 불균형 데이터셋에서는 오해의 소지가 있을 수 있습니다.
정밀도
- 정의: 총 예측된 긍정 중에서 올바르게 예측된 긍정의 비율.
- 공식:
\[
\text{Precision} = \frac{TP}{TP + FP}
\]
- 해석: 높은 정밀도는 알고리즘이 관련 없는 결과보다 관련 있는 결과를 훨씬 더 많이 반환했음을 나타냅니다.
재현율 (민감도)
- 정의: 실제 클래스의 모든 인스턴스 중에서 올바르게 예측된 긍정의 비율.
- 공식:
\[
\text{Recall} = \frac{TP}{TP + FN}
\]
- 해석: 높은 재현율은 알고리즘이 대부분의 관련 결과를 반환했음을 나타냅니다.
F1 점수
- 정의: 정밀도와 재현율의 가중 평균.
- 공식:
\[
F1 = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}
\]
- 해석: F1 점수는 정밀도와 재현율 사이의 균형을 전달합니다.
특이도
- 정의: 실제 부정 클래스의 모든 인스턴스 중에서 올바르게 예측된 부정의 비율.
- 공식:
\[
\text{Specificity} = \frac{TN}{TN + FP}
\]
- 해석: 높은 특이도는 모델이 부정 사례를 효과적으로 식별함을 나타냅니다.
고급: 다중 클래스 혼동 행렬 처리
두 개 이상의 클래스가 있는 시나리오에서는 혼동 행렬이 다차원 그리드로 확장됩니다. 각 대각선 요소는 각 클래스에 대해 올바르게 분류된 인스턴스를 나타내며, 비대각선 요소는 다양한 오분류를 나타냅니다.
예시: 클래스 A, B, C가 있는 3클래스 분류 문제를 고려해 보겠습니다.
12345
Predicted A B CActual A 50 2 3 B 5 45 5 C 2 3 48
- 클래스 A의 진양성: 50
- 클래스 A의 위양성: 5 (B로부터) + 2 (C로부터) = 7
- 클래스 A의 위음성: 2 (B로) + 3 (C로) = 5
- 클래스 A의 진음성: 총 - (TP + FP + FN) = 100 - (50 + 7 + 5) = 38
Scikit-learn의 confusion_matrix
함수는 다중 클래스 시나리오를 원활하게 처리하여 상세한 성능 분석을 용이하게 하는 명확한 행렬을 제공합니다.
날씨 예측 데이터셋을 사용한 실용적 구현
개념을 확고히 하기 위해 Weather Australia 데이터셋을 사용한 실용적인 예제를 살펴보겠습니다. 이 데이터셋은 다양한 기상 속성을 기반으로 다음 날 비가 올지를 예측하는 것을 포함합니다.
단계별 구현
- 데이터 전처리:
SimpleImputer
을 사용하여 결측값 처리.
- 원-핫 인코딩을 사용하여 범주형 변수 인코딩.
LabelEncoder
을 사용하여 타겟 변수 인코딩.
- 특징 스케일링:
- 각 특징이 모델 성능에 동등하게 기여하도록 표준화.
- 모델 훈련:
- K-최근접 이웃, 로지스틱 회귀, 가우시안 나이브 베이즈, 서포트 벡터 머신, 결정 트리, 랜덤 포레스트, AdaBoost, XGBoost와 같은 여러 분류 모델 훈련.
- 평가:
- 각 모델의 정확도 점수 계산.
- 예측 분포를 이해하기 위해 혼동 행렬 생성 및 시각화.
샘플 코드 스니펫
로지스틱 회귀 모델 훈련:
12345678910111213
from sklearn.linear_model import LogisticRegression # 모델 초기화LRM = LogisticRegression(random_state=0, max_iter=200) # 모델 훈련LRM.fit(X_train, y_train) # 테스트 데이터 예측y_pred = LRM.predict(X_test) # 정확도 평가print(accuracy_score(y_pred, y_test))
출력:
1
0.8296705228735187
혼동 행렬 생성:
12345678910
from sklearn.metrics import confusion_matrix, plot_confusion_matrix # 혼동 행렬 계산cm = confusion_matrix(y_test, y_pred)print(cm) # 혼동 행렬 플롯plot_confusion_matrix(LRM, X_test, y_test, display_labels=le.classes_)plt.title('Logistic Regression Confusion Matrix')plt.show()
출력:
12
[[21087 1058] [ 3786 2508]]
그림 5: 로지스틱 회귀 모델의 혼동 행렬.
여러 모델의 비교 정확도:
12345678910111213141516171819202122232425
from sklearn.neighbors import KNeighborsClassifierfrom sklearn.naive_bayes import GaussianNBfrom sklearn.svm import SVCfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.ensemble import RandomForestClassifier, AdaBoostClassifierimport xgboost as xgb # 모델 초기화models = { 'KNN': KNeighborsClassifier(n_neighbors=3), 'Logistic Regression': LogisticRegression(random_state=0, max_iter=200), 'GaussianNB': GaussianNB(), 'SVC': SVC(), 'Decision Tree': DecisionTreeClassifier(), 'Random Forest': RandomForestClassifier(n_estimators=500, max_depth=5), 'AdaBoost': AdaBoostClassifier(), 'XGBoost': xgb.XGBClassifier(use_label_encoder=False, eval_metric='mlogloss')} # 모델 훈련 및 평가for name, model in models.items(): model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracy = accuracy_score(y_pred, y_test) print(f'{name} Accuracy: {accuracy:.4f}')
샘플 출력:
12345678
KNN Accuracy: 0.8003Logistic Regression Accuracy: 0.8297GaussianNB Accuracy: 0.7960SVC Accuracy: 0.8282Decision Tree Accuracy: 0.8302Random Forest Accuracy: 0.8302AdaBoost Accuracy: 0.8299XGBoost Accuracy: 0.8302
출력에서 알 수 있듯이, 결정 트리, 랜덤 포레스트, 그리고 XGBoost 모델이 가장 높은 정확도를 보이며, 로지스틱 회귀와 AdaBoost가 그 뒤를 이었습니다.
결론
혼동 행렬은 분류 모델의 성능을 평가하는 데 필수적입니다. 이는 다양한 클래스에 걸쳐 모델이 어떻게 성능을 발휘하는지 세밀하게 보여주며, 강점과 개선이 필요한 영역을 강조합니다. 혼동 행렬의 구축과 해석, 그리고 정밀도, 재현율, F1 점수와 같은 보조 지표를 마스터함으로써, 머신러닝 실무자는 보다 견고하고 신뢰할 수 있는 모델을 개발할 수 있습니다. scikit-learn과 같은 도구를 활용하면 이 과정을 간소화하여 효율적인 모델 평가와 반복적인 개선이 가능합니다. 머신러닝 모델을 계속 탐색하고 구현하면서, 평가 파이프라인에 혼동 행렬을 통합하면 분석 능력과 모델의 효능을 확실히 향상시킬 수 있습니다.
더 자세한 예제와 고급 기술에 대해서는 scikit-learn의 혼동 행렬 문서를 참조하세요.