Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

천선생의 삶

[Kaggle] 타이타닉 생존자 예측 3부 - Modeling 본문

Kaggle/Titanic

[Kaggle] 타이타닉 생존자 예측 3부 - Modeling

천선생 2019. 7. 30. 16:02

안녕하세요. 천선생입니다.

 

 1부와 2부를 순서대로 따라오셨다면 이제 이런 생각이 강하게 들 것이라고 생각합니다.

'그래서 예측은 언제하는 데?'

이번 포스트는 바로 최종아닌 최종단계, Modeling에 대해 다루도록 하겠습니다.

 

- Modeling?

 Modeling이란, 말그대로 정제한 데이터를 예측모형에 학습시켜 원하는 결과를 찾아내는 것을 의미합니다.

이번 데이터에서 진행하게 될 학습은 지도학습의 일종인 로지스틱 회귀모형입니다.

용어들이 난무하기 이전에 간단히 코드를 통하여 이해해보도록 하겠습니다.

# 학습과정 이해하기
# Feature Engineering을 완료한 데이터의 모습 확인
str(data)
# 'data.frame':	1309 obs. of  13 variables:
# $ PassengerId: int  1 2 3 4 5 6 7 8 9 10 ...
# $ Pclass     : Ord.factor w/ 3 levels "1"<"2"<"3": 3 1 3 1 3 3 1 3 3 2 ...
# $ Sex        : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
# $ Age        : num  22 38 26 35 35 ...
# $ SibSp      : int  1 1 0 1 0 0 0 3 0 1 ...
# $ Parch      : int  0 0 0 0 0 0 0 1 2 0 ...
# $ Fare       : num  2.11 4.28 2.19 3.99 2.2 ...
# $ Embarked   : Factor w/ 3 levels "C","Q","S": 3 1 3 3 3 2 3 3 3 1 ...
# $ Survived   : Factor w/ 2 levels "No","Yes": 1 2 2 2 1 1 1 1 2 2 ...
# $ Baby       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 2 1 1 ...
# $ Group_size : Factor w/ 3 levels "Single","Small",..: 2 2 1 2 1 1 1 3 2 2 ...
# $ T_Group    : Factor w/ 3 levels "Single_T","Couple_T",..: 1 2 1 2 1 1 2 3 3 2 ...
# $ Crew       : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...

#PassengerId 변수는 삭제하겠습니다.
data$PassengerId <- NULL

#전처리가 끝난것 같아 보입니다. 모형학습을 위한 데이터셋을 나누겠습니다.
train <- data[1:split_num, ]
test <- data[-(1:split_num), ]
# 동일한 데이터를 분할한 것이기 때문에 다를 것이 없어보입니다. head로 세부적인 확인을 해보겠습니다.

head(train)
#   Pclass    Sex      Age SibSp Parch     Fare Embarked Survived Baby Group_size  T_Group Crew
# 1      3   male 22.00000     1     0 2.110213        S       No    0      Small Single_T    0
# 2      1 female 38.00000     1     0 4.280593        C      Yes    0      Small Couple_T    0
# 3      3 female 26.00000     0     0 2.188856        S      Yes    0     Single Single_T    0
# 4      1 female 35.00000     1     0 3.990834        S      Yes    0      Small Couple_T    0
# 5      3   male 35.00000     0     0 2.202765        S       No    0     Single Single_T    0
# 6      3   male 32.28028     0     0 2.246893        Q       No    0     Single Single_T    0

head(test)
#     Pclass    Sex  Age SibSp Parch     Fare Embarked Survived Baby Group_size  T_Group Crew
# 892      3   male 34.5     0     0 2.178064        Q       NA    0     Single Single_T    0
# 893      3 female 47.0     1     0 2.079442        S       NA    0      Small Single_T    0
# 894      2   male 62.0     0     0 2.369075        Q       NA    0     Single Single_T    0
# 895      3   male 27.0     0     0 2.268252        S       NA    0     Single Single_T    0
# 896      3 female 22.0     1     1 2.586824        S       NA    0      Small Couple_T    0
# 897      3   male 14.0     0     0 2.324836        S       NA    0     Single Single_T    0

  TrainTest의 형태 차이를 확인하셨나요?

맞습니다. TrainSurvived 는 Test에서 모두 NA의 값을 갖습니다.

즉 최종 목표는, Train의 데이터로 모형을 적합시켜 TestSurvived를 예측하는 것입니다.

그렇다면, 적합된 모형이 잘 적합되었는지 어떻게 확인할 수 있을까요?

이때 Validation set을 만듦으로써 이러한 문제를 극복할 수 있습니다.

 

- Validation set?

 

 Validation set 이란, 검증 셋이라는 의미를 갖고있습니다.

우리가 확인할 수 있는 실제 생존여부는 Train에만 존재합니다.

즉, 모형을 만들어서 Test에 존재하는 생존여부를 예측한다고 해도 얼마나 정확한지 알아낼 수 없다는 것이죠!

물론 Test의 생존여부는 존재합니다. 단 그 정답Kaggle(주최)만 알고 있지요.

 

 따라서 스스로 모형을 평가할 수 있는 지표, 즉 내부의 정답이 필요합니다.

이를 의도적으로 만든 것이 Validation set입니다.

Validation setTrain set을 설정하기 위하여, Caret 패키지의 createDataPartition함수를 활용하겠습니다.

# Caret::createDataPartition을 통한 validation set 분할
#분할을 위한 인덱스를 지정합니다.
set.seed(1)
# createDataPartition은 난수를 통하여 분할을 진행합니다. 복원가능성을 위하여 시드를 설정합니다.
# 7:3의 비율로 분할하며, 생존여부의 비율을 맞추어 자동으로 분할합니다.
train_idx <- createDataPartition(train$Survived, p = 0.7, list = F)

#train_M 데이터와 val_M 데이터를 설정하겠습니다.
train_M <- train[train_idx, ]
val_M <- train[-train_idx, ]

 

- 1차 모형 적합 및 자체 평가

이제 준비된 데이터로 내부적인 모형 적합 및 평가를 진행하겠습니다.

# glm함수를 사용하여 로지스틱 회귀모형 적합하기.
fit_Logistic <- glm(Survived~., 
                    data = train_M,
                   family = 'binomial')

# predict 함수를 활용하여, validation의 경우 예측값을 출력
pred_Logistic <- predict(fit_Logistic, newdata = val_M, type = 'response')

# response 타입으로 입력하면, 확룰로 출력됩니다. ifelse를 활용하여 변환합니다.
Logistic_val <- ifelse(pred_Logistic > 0.5, 1, 0)
Logistic_val <- factor(Logistic_val, levels = c(0, 1), labels = c('No', 'Yes'))

# 예측 정확도를 내부의 정보(Val, Train)으로 확인합니다.
confusionMatrix(Logistic_val, val_M$Survived)
# Confusion Matrix and Statistics
# 
# Reference
# Prediction  No Yes
# No         133  24
# Yes         31  78
# 
# Accuracy : 0.7932           <- 정확도(Accuracy)입니다.
# 다른 값들은 추후 포스트에서 다루겠습니다.
# 95% CI : (0.7395, 0.8403)
# No Information Rate : 0.6165          
# P-Value [Acc > NIR] : 4.694e-10       
# 
# Kappa : 0.5683          
# 
# Mcnemar's Test P-Value : 0.4185          
#                                           
#             Sensitivity : 0.8110          
#             Specificity : 0.7647          
#          Pos Pred Value : 0.8471          
#          Neg Pred Value : 0.7156          
#              Prevalence : 0.6165          
#          Detection Rate : 0.5000          
#    Detection Prevalence : 0.5902          
#       Balanced Accuracy : 0.7878          
#                                           
#        'Positive' Class : No              

  예측정확도(Accuracy)Caret 패키지의 confusionMatrix함수를 통해서 확인했습니다.

내부적으로 약 79%의 정확도를 갖는 것을 확인할 수 있습니다.

우리는 여기서 만족하고 최종 모형을 train 전체를 사용하여 적합시키겠습니다.

 

- 최종 모형 적합 및 제출

# 최종 모형 학습
fit_final <- glm(Survived~., 
                    data = train,
                   family = 'binomial')

pred_final <- predict(fit_final, newdata = test, type = 'response')

final_val <- ifelse(pred_final > 0.5, 1, 0)
final_val <- factor(final_val, levels = c(0, 1), labels = c('No', 'Yes'))

# 주최측에서 제공한 제출파일 형식입니다.
submission <- read.csv('gender_submission.csv')

submission$Survived <- (as.integer(final_val) - 1)

# 제출파일을 생성합니다.
write.csv(submission, 'submission.csv', row.names = F)

 이제 작업디렉토리를 확인해보면, submission.csv 라는 파일을 확인할 수 있습니다.

생성된 파일을 Kaggle에 제출해보면, 0.75598의 정확도를 확인할 수 있습니다.

Kaggle에서 제공받은 정확도.

 

- 제출 결과

  Validation의 정확도는 약 79%였던 반면에, 실제 Test에서의 정확도는 75.5%에 그쳤습니다.

즉, 우리는 모형이 Train에 과적합 되었다는 것을 알 수 있습니다.

이러한 경우 Trian만을 통하여 Test'적당히 잘 설명하는' 모형을 찾기 위해 다시 이전작업으로 돌아가야 할 것입니다.

 

 그렇다면 실제 Test에서의 정확도가 매우 높은것이 항상 좋은것을 뜻할까요?

실제 Titanic Competition에서 100%의 정확도를 기록한 상위 대부분 분석가들

 일반적으로는 Test에서의 정확도가 높다면, 예측을 잘했다고 말할 수 있지만

이러한 경우에는 Test에 과적합을 시킨 경우라고 볼 수 있습니다.

분류에서의 과적합(녹색선)과 적절한 분류선(검정선)

 과적합이란, 위의 그림에서 녹색선을 의미합니다.

이러한 분류선이 적합된 경우, 새로운 데이터에 대응하는 능력이 떨어지는 단점이 존재하게 될 것입니다.

 

- 마치며

 이렇게 Titanic data를 통하여 변수탐색부터 제출까지 진행해보았습니다.

최적의 모형을 찾기위해서는 처음으로 돌아가 다시 하나하나 확인해보고, 데이터를 괴롭히는 노력이 필요할것입니다!!

이번 시리즈에서는 최적의 모형이 아닌 제출에 의미를 두었기 때문에, 부족한 모습이 보였을 것이라고 생각합니다.

 

이후 시리즈에서는 조금 더 완성된 모습으로 다시 찾아오도록 하겠습니다.

Comments