YOGYUI

R caret::confusionMatrix - 혼동행렬 작성 및 metric 추출 본문

Software/R

R caret::confusionMatrix - 혼동행렬 작성 및 metric 추출

요겨 2021. 6. 17. 14:54
반응형

분류분석 시 혼동행렬(Confusion Matrix)은 모델의 Accuracy, Sensitivity, Specificity 등 성능 지표를 계산하기 위해 기본적으로 작성하는 테이블이다
(참고: 링크)

이진분류 문제의 혼동행렬 작성요령

 표를 통해 정확도, 민감도, 특이도, 재현율, F1-Score 등을 계산할 수 있는데, 이를 한번에 해결해줄 수 있는 툴이 바로 caret 패키지의 confusionMatrix 함수다

confusionMatrix {caret}
Create a confusion matrix

Description

Calculates a cross-tabulation of observed and predicted classes with associated statistics.

Usage

confusionMatrix(data, ...)

## Default S3 method:
confusionMatrix(
  data,
  reference,
  positive = NULL,
  dnn = c("Prediction", "Reference"),
  prevalence = NULL,
  mode = "sens_spec",
  ...
)

 

사용예시

mlbench 패키지의 존스홉킨스 전리층 (Ionosphere) 데이터로 이진분류 모델링 후 혼동행렬 작성

(메타데이터 링크)

library(mlbench)
data(Ionosphere)

set.seed(210617)
# Hold-Out
library(caret)
idx <- caret::createDataPartition(Ionosphere$Class, p = 0.7)
df_train <- Ionosphere[idx$Resample1, ]
df_test <- Ionosphere[-idx$Resample1, ]

# logistic regression model
model_glm <- glm(Class ~ . , data = subset(df_train, select = c(-V1, -V2)), family="binomial")
pred_glm_test <- predict(model_glm, newdata = df_test, type="response")

훈련데이터:테스트데이터 7:3 비율로 홀드아웃 후 훈련데이터로 피팅한 모델 model_glm에 테스트 데이터의 예측 결과 pred_glm_test를 추출했다

head(pred_glm_test)
>
           6            7           11           16           17           22 
8.014344e-03 9.972758e-01 9.984261e-01 1.943454e-03 9.958211e-01 2.220446e-16 

caret의 confusionMatrix를 사용하기 위해 위 예측 결과를 factor형으로 변환해줘야 한다

(로지스틱 회귀분석의 예측 결과는 0 ~ 1 사이의 값, 임의로 클래스 분기점을 0.5로 지정)

pred_glm_test_class <- factor(ifelse(pred_glm_test >= 0.5, 1, 0))
levels(pred_glm_test_class) <- c("bad", "good")
head(pred_glm_test_class)
>
   6    7   11   16   17   22 
 bad good good  bad good  bad 
Levels: bad good

 

confusionMatrix 함수의 첫번째 인자(data)는 예측클래스, 두번째 인자(reference)는 실제클래스

cfm_glm <- caret::confusionMatrix(pred_glm_test_class, df_test$Class)
cfm_glm
>
Confusion Matrix and Statistics

          Reference
Prediction bad good
      bad   29    7
      good   8   60
                                         
               Accuracy : 0.8558         
                 95% CI : (0.7733, 0.917)
    No Information Rate : 0.6442         
    P-Value [Acc > NIR] : 1.262e-06      
                                         
                  Kappa : 0.6834         
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.7838         
            Specificity : 0.8955         
         Pos Pred Value : 0.8056         
         Neg Pred Value : 0.8824         
             Prevalence : 0.3558         
         Detection Rate : 0.2788         
   Detection Prevalence : 0.3462         
      Balanced Accuracy : 0.8397         
                                         
       'Positive' Class : bad   

혼동행렬 뿐만 아니라 여러 metric들도 함께 계산되어 출력되어 상당히 편리하다

 

랜덤포레스트 분류모델도 작성해보자

library(randomForest)
model_rf <- randomForest(Class ~ ., data = subset(df_train, select = -c(V1, V2)))
pred_rf_test <- predict(model_rf, newdata = df_test, type='response')
cfm_rf <- caret::confusionMatrix(pred_rf_test, df_test$Class)

랜덤포레스트 모델은 predict의 type 인자로 "response" 지정하면 별다른 처리 없이 class 분류 결과가 반환된다

head(pred_rf_test)
>
   6    7   11   16   17   22 
 bad good good  bad good  bad 
Levels: bad good
cfm_rf
>
Confusion Matrix and Statistics

          Reference
Prediction bad good
      bad   33    4
      good   4   63
                                         
               Accuracy : 0.9231         
                 95% CI : (0.854, 0.9662)
    No Information Rate : 0.6442         
    P-Value [Acc > NIR] : 3.604e-11      
                                         
                  Kappa : 0.8322         
                                         
 Mcnemar's Test P-Value : 1              
                                         
            Sensitivity : 0.8919         
            Specificity : 0.9403         
         Pos Pred Value : 0.8919         
         Neg Pred Value : 0.9403         
             Prevalence : 0.3558         
         Detection Rate : 0.3173         
   Detection Prevalence : 0.3558         
      Balanced Accuracy : 0.9161         
                                         
       'Positive' Class : bad    

훈련되지 않은 테스트 데이터에서의 분류 정확도는 random Forest(0.9231)가 로지스틱 회귀모델(0.8558)보다 우수한 것을 알 수 있다

 

(보너스) ROC Curve + AUC

위에서 구현한 모델들의 ROC 커브 그리기 및 AUC 계산도 해보자

(ROCR 패키지 사용 vs. pROC 패키지 사용)

library(ROCR)
roc_pred_glm <- ROCR::prediction(pred_glm_test, df_test$Class)
roc_perf_glm <- ROCR::performance(roc_pred_glm, measure = "tpr", x.measure = "fpr")
pred_rf_test <- predict(model_rf, newdata = df_test, type='prob')[,'good']
roc_pred_rf <- ROCR::prediction(pred_rf_test, df_test$Class)
roc_perf_rf <- ROCR::performance(roc_pred_rf, measure = "tpr", x.measure = "fpr")

plot(roc_perf_glm)
plot(roc_perf_rf, add = TRUE, col = "red")
abline(0, 1)

ROCR 패키지 사용

ROCR::performance(roc_pred_glm, measure = "auc")@y.values[[1]]
> [1] 0.8741428

ROCR::performance(roc_pred_rf, measure = "auc")@y.values[[1]]
> [1] 0.9753933

 

library(pROC)
roc_glm <- pROC::roc(df_test$Class, pred_glm_test)
roc_rf <- pROC::roc(df_test$Class, pred_rf_test)
plot(roc_glm, legacy.axes = TRUE)
plot(roc_rf, add = TRUE, col = "red")

pROC 패키지 사용

roc_glm$auc
> Area under the curve: 0.8741

roc_rf$auc
> Area under the curve: 0.9754

 

반응형