다중클래스 분류기 예측 평가 및 분류기 성능 시각화
1. 두 개 이상의 클래스 : 평가지표 교차검증
# 라이브러리 임포트
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
# 특성 행렬과 타깃 벡터를 만든다
features, target = make_classification(n_samples=10000,
n_features=3,
n_informative=3,
n_redundant=0,
n_classes=3, # 클래스가 3인 다중분류
random_state=1)
# 로지스틱 회귀 모델
logit = LogisticRegression()
# 정확도 사용하여 교차검증 수행
cross_val_score(logit, features, target, scoring='accuracy')
array([0.841 , 0.829 , 0.8265, 0.8155, 0.82 ])
클래스가 균형 잡혀있을때(타깃 벡터의 클래스에 속한 샘플 개수가 거의 동일할 때 ) 이진 클래스의 경우와 같이 정확도는 간단하고 해석이 용이한 평가 지표이다.
정확도는 올바르게 예측한 수를 전체 샘플 수로 나눈것이고 이진 분류에서처럼 다중 클래스에서도 잘 맞는다.
2. 불균형한 다중 클래스 환경에 정밀도, 재현율, F₁점수 적용
불균형한 클래스에서는 다른 평가 지표를 사용하는 것이 좋다.
사이킷런에 포함된 지표 중 다수는 이진 분류기를 평가하는 용도이다. 하지만 이런 지표를 클래스가 두 개 이상일 때로 확장할 수 있다. 정밀도, 재현율, F₁점수는 이진 분류 평가 때 처럼 사용하면 된다. 이것들은 원래 이진 분류기를 위해 고안되었지만 훈련 데이터를 이진 클래스처럼 취급하는 방식으로 다중 클래스 환경에도 적용할 수 있다. 데이터에 하나의 클래스만 있는 것처럼 각 클래스에서 측정한 값을 수집하여 평균함으로써 전체 클래스에 대한 평가 점수를 얻을 수 있다.
# 마크로 평균 F1점수를 사용해 교차검증 수행
cross_val_score(logit, features, target, scoring='f1_macro')
array([0.84061272, 0.82895312, 0.82625661, 0.81515121, 0.81992692])
_macro는 클래스별 평가 점수를 평균하는 방법이다.
- macro : 각 클래스를 동등한 가중치로 클래스별 측정 점수를 평균한다.
- weighted : 샘플 개수에 비례하여 각 클래스별 측정 점수 평균를 평균한다.
- micro : 클래스별로 TP, TN, FP, FN을 모두 더하여 계산한다.
3. 분류기 성능 시각화 : 다중 클래스도 오차행렬로 나타낼 수 있다.
테스트 데이터의 예측 클래스와 진짜 클래스를 바탕으로 모델의 품질을 시각적으로 비교할 수 있다. 이때 오차 행렬(confusion matrix)을 사용해 예측 클래스와 진짜 클래스를 비교한다.
# 라이브러리 임포트
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
# 데이터 로드
iris = datasets.load_iris()
# 특성 행렬
features = iris.data
# 타깃 벡터 생성
target = iris.target
# 클래스 이름의 리스트 생성
class_names = iris.target_names
# 데이터 프레임화해서 데이터 확인해보기
# iris의 data는 배열, 칼럼명은 feature_names로 확인
df = pd.DataFrame(iris.data, columns=iris.feature_names)
# data에 종(species)의 이름이 없기 때문에 target 데이터를 이용해서 생성
df['species'] = [iris.target_names[i] for i in iris.target]
df
sepal length (cm) | sepal width (cm) | petal length (cm) | petal width (cm) | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
... | ... | ... | ... | ... | ... |
145 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
146 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
147 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
148 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
149 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
150 rows × 5 columns
# 훈련셋과 데이터 셋 나눔
features_train, features_test, target_train, target_test = train_test_split(features, target, random_state=1)
# 로지스틱 회귀 모델 생성
classifier = LogisticRegression()
# 모델 훈련하고 예측결과 계산
target_predicted = classifier.fit(features_train, target_train).predict(features_test)
# 오차행렬 생성
matrix = confusion_matrix(target_test, target_predicted)
# 판다스 데이터프레임 생성
dataframe = pd.DataFrame(matrix, index=class_names, columns=class_names)
dataframe
setosa | versicolor | virginica | |
---|---|---|---|
setosa | 13 | 0 | 0 |
versicolor | 0 | 15 | 1 |
virginica | 0 | 0 | 9 |
df['species'].value_counts()
setosa 50
versicolor 50
virginica 50
Name: species, dtype: int64
# 히트맵 생성
sns.heatmap(dataframe, annot=True, cbar=None, cmap="Blues")
plt.title("Confusion Matrix"), plt.tight_layout()
plt.ylabel("True Class"), plt.xlabel("Predicted Class")
plt.show()
그래프 해석
이 행렬의 열(Predicted)은 예측 클래스를 나타내고 행은 진짜 클래스(True Class)를 나타낸다.
각 셀은 예측과 진짜의 가능한 조합 중 하나가 된다. 해왼쪽 맨 위의 셀은 Iris setosa(열)로 예측한 것 중에서 실제로 Iris setosa(행)인 샘플 개수이다. 여기서 모든 setosa 꽃을 올바르게 예측된것이다. 이 모델에서 virginica는 9개의 샘플을 올바르게 예측했지만, 위의 1개는 versicolor로 예측했다.
오차 행렬에 대해
오차 행렬은 분류기의 성능을 쉽고 효과적으로 보여주는 도구이다. 오차 행렬의 핵심 장점 중 하나는 해석이 용이하다.
- 완벽한 모델은 대각선에만 값이 있고 나머지는 모두 0이다. 나쁜 모델은 모든 셀에 고르게 샘플들이 퍼져있다.
- 오차 행렬은 모델이 나쁘다는 것뿐만 아니라 어떻게 나쁜지도 알려준다. 잘못 분류된 패턴을 확인해볼 수 있다.
- 오차행렬은 다중 클래스 환경에도 잘 동작한다.(타깃 벡터에 백만 개의 클래스가 있다면 이때는 오차 행렬을 그래프로 나타내기 어렵다.)
# 사이킷런의 confusion_matrix 함수로 오차행렬 계산
# 이 행렬의 행과 열은 해결에 나온 오차 행렬의 그래프의 행과 열과 같다.
from sklearn.metrics import confusion_matrix
confusion_matrix(target_test, target_predicted)
array([[13, 0, 0],
[ 0, 15, 1],
[ 0, 0, 9]])
'파이썬 > 머신러닝' 카테고리의 다른 글
머신러닝 이진 분류모델의 예측 평가와 임곗값 평가 (0) | 2022.11.24 |
---|---|
머신러닝 기본 회귀 모델과 기본 분류 모델의 평가방법 - score(), predict() (0) | 2022.11.23 |
모델 평가란? 로지스틱회귀에서 KFold 교차검증 사용해보기 (0) | 2022.11.21 |
넘파이numpy 와 서킷런sklearn을 활용한 데이터 이상치 확인 및 해결 (0) | 2022.11.17 |
서킷런 sklearn으로 수치형 데이터 전처리 [스케일링 - 표준화, 로버스트, MinMax, 정규화] (1) | 2022.11.16 |
댓글