Calm Hill My Random Thoughts

Machine Learning from Disaster with Titanic (2)

အရှေ့ကရေးခဲ့တဲ့ Post မှာ Data တွေရဲ့ Structure နဲ့ Overview ကို ကြည့်ခဲ့ကြတယ် Data တွေရဲ့ Overview က လုံတော့ မလုံလောက်သေးဘူး Independent variables တွေနဲ့ အသက်ရှင်တယ်မရှင်ဘူးဆိုတဲ့ Dependent variable ရဲ့ Correlation တွေ Covariance တွေကို အသအေချာ ကြည့်ပြီးတော့မှ မလိုအပ်တဲ့ Independent variable တွေက ဘယ်ဟာတွေ ဖြစ်နိုင်မလဲ ကြိုပြီးတော့ သုံးသပ်လို့ရလိမ့်မယ်။ Independent variable တွေလည်း သိပ်အများကြီးမပါတော့ Computing Power ကို အသုံးချပြီးတော့ နည်းနည်းတော့ ပျင်းလိုက်ဦးမယ် Independent variable အကုန်လုံးကို ယူသုံးကြည့်လိုမှ အဖြေတွေသိပ်ပြီး စုတ်စုတ်ပြတ်ပြတ် ဖြစ်လွန်းရင်တော့ ပြန်ကြည့်ရမှာပေါ့လေ။

Machine Learning ကို အသုံးချဖို့အတွက် အခြေခံပြဿနာတွေမှာ စျေးနှုန်းတွေကို ခန့်မှန်းတာမျိုးဖြစ်တဲ့ ကိန်းဂဏန်းခန့်မှန်းတဲ့ Prediction ကိစ္စမျိုးတွေရှိတယ် စာမေးပွဲ အောင်မှလား ကျမှလား ပစ္စည်းဝယ်မှာလား မဝယ်ဘူးလား စသည်ဖြင့် Classification လုပ်ချင်တာမျိုးတွေရှိမယ် နောက်ပြီးတော့ အမျိုးအစားဆင်တူတဲ့ Data တွေကို အုပ်စုဖွဲချင်တဲ့ Clustering အလုပ်တွေရှိတယ် စသည်ဖြင့် အမျိုးအစားက သိပ်ပြီးတော့မများလှပါဘူး။ Titanic မှာ အသက်ရှင်နိုင်လား မရှင်နိုင်ဘူးလား ခန့်မှန်းချင်တာ ဖြစ်တဲ့အတွက် သူရဲ့ပြဿနာ အမျိုးအစားဟာ Classification အုပ်စုထဲမှာပါတယ် Method တွေအနေနဲ့ Logistic Regression, Decision Tree နဲ့ Random Forest ကိုသုံးပြီးတော့ စမ်းကြည့်မယ်။ Data ကတော့ Missing Data တွေကို Mean နဲ့ အစားထိုးပြီး Clean လုပ်ထားတာကို သုံးကြည့်မယ်။

> ## Load Data
> train = read.csv("train_mean_na.csv")
> test = read.csv("test_mean_na.csv")
> train$Pclass = as.factor(train$Pclass)
> test$Pclass = as.factor(test$Pclass)
>
> ## Write Result
> writeSubmission = function(result, filename) {
>    submission = data.frame(PassengerId = test$PassengerId, Survived = as.numeric(result > 0.5))
>    head(submission)
>    write.csv(submission, file = filename, row.names=FALSE)
> }

Classification လုပ်လို့ ထွက်လာတဲ့ အဖြေတွေကို Submission မလုပ်ခင်မှာ ဘယ်လိုအခြေအနေရှိလဲ Performace Measurement လုပ်ဖို့လည်းလိုသေးတယ် Performance မှာ အလွယ်ဆုံးနည်းဖြစ်တဲ့ မှန်တာကို မှန်တယ်လို့ ခန့်မှန်းနိုင်တဲ့ (True Positive) ရယ် မှားတာကို မှားတယ်လို့ ခန့်မှန်းနိုင်တဲ့ (True Negative) ကနေ Accuracy (ACC) ကို အလွယ်တကူ တိုင်းကြည့်လို့ရတယ်။ နောက်တခုက Logistice Regression မှာ Area Under the Curve (AUC) ကိုလည်း သုံးလေ့ရှိတယ် Titanic ရဲ့ Classification မှာက အသက်ရှင်နိုင်မယ် မရှင်နိုင်ဘူးဆိုတော့ Binary Classification ဖြစ်နေတဲ့အတွက် တခြား Method တွေအတွက်လည်း သုံးမယ်ဆိုရင် သုံးလို့ရတယ်တဲ့အတွက် ACC ရယ် AUC ရယ်သုံးပြီး Performance တိုင်းကြည့်မယ်။

Logistic Regression နဲ့စပြီးတော့ စမ်းကြည့်မယ် ပထမဆုံးအနေနဲ့ စမ်းသပ်တာဖြစ်သလို Correlation တွေလည်း ကြိုပြီးတော့ မစဉ်းစားထားတော့ ရှိသမျှ Independent Variables ကို အကုန်ထည့်သုံးပြီး အခြေအနေ ဘယ်လိုရှိမလဲ အရင်ဆုံးကြည့်ရမယ်။ Logistic Regression အတွက် R မှာ Built-in ပါတဲ့ glm ကို သုံးလို့ရတဲ့အတွက် External Package မလိုအပ်ပါဘူး။ AUC အတွက်ကတော့ ROCR ကိုသုံးထားတယ်။

> library(ROCR)
> model = glm(Survived ~ Pclass + Sex + Age + SibSp + Parch + Ticket + Fare + Cabin + Embarked, data = train, family = binomial)
> summary(model) 
 Call:
 glm(formula = Survived ~ Pclass + Sex + Age + SibSp + Parch + 
     Ticket + Fare + Cabin + Embarked, family = binomial, data = train)

 Deviance Residuals: 
    Min      1Q  Median      3Q     Max  
  -8.49    0.00    0.00    0.00    8.49

 Coefficients: (122 not defined because of singularities)
                            Estimate Std. Error    z value Pr(>|z|)    
 (Intercept)              -6.440e+17  1.305e+10  -49338191   <2e-16 ***
 Pclass2                   5.687e+17  1.147e+10   49589822   <2e-16 ***
 Pclass3                   5.844e+17  1.191e+10   49054826   <2e-16 ***
 Sexmale                  -1.926e+15  1.017e+07 -189303844   <2e-16 ***
 Age                      -5.467e+13  4.731e+05 -115557951   <2e-16 ***
 SibSp                     1.044e+13  1.433e+07     728692   <2e-16 ***
 Parch                     3.631e+14  1.580e+07   22987496   <2e-16 ***
 Ticket110413              5.078e+16  1.038e+09   48905289   <2e-16 ***
 Ticket110465              2.536e+17  5.207e+09   48701283   <2e-16 ***
 ...
 Fare                      7.507e+15  1.509e+08   49752688   <2e-16 ***
 CabinA10                         NA         NA         NA       NA    
 CabinA14                 -9.458e+14  9.526e+07   -9928733   <2e-16 ***
 ...
 EmbarkedC                 7.098e+15  9.545e+07   74358318   <2e-16 ***
 EmbarkedQ                        NA         NA         NA       NA    
 EmbarkedS                        NA         NA         NA       NA    
 ---
 Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

> result = predict(model, type = "response")
> table(train$Survived, result > 0.5)
    FALSE TRUE
  0   545    4
  1     4  338
> (545+338)/891
[1] 0.9910213
> ROCRpred = prediction(result, train$Survived)
> as.numeric(performance(ROCRpred, "auc")@y.values)
[1] 0.9905091
> ### Prediction
> model$xlevels[["Ticket"]] = union(model$xlevels[["Ticket"]], levels(test$Ticket))
> model$xlevels[["Cabin"]] = union(model$xlevels[["Cabin"]], levels(test$Cabin))
> result = predict(model, type="response",  newdata = test)
> writeSubmission(result, "submission_logistics_regression1.csv")

ထွက်လာတဲ့ Model မှာကြည့်ရင် Independent Variable တွေရဲ့ Significant level တွေဟာ အားလုံးနီးနီး အမြင့်အဆုံး 3 Stars ဖြစ်နေသလို Training data ပေါ်မှာ တွက်ထားတဲ့ Performance အဖြေတွေအရဆိုရင် Performance ဟာ ကြောက်စရာ ကောင်းလောက်တဲ့ အခြေအနေမှာရှိတယ် ACC ဟာ 0.9910213 ရှိပြီးတော့ AUC ဟာ 0.9905091 ရှိနေတယ်။ ဒါပေမယ့် testing data ပေါ်မှာ ခန့်မှန်းပြီးတော့ Submit လုပ်ကြည့်တော့ Performance ဟာ 0.62679 ပဲရှိပါတယ်။ ပြဿနာက Overfitting ဖြစ်နေတာ ထွက်လာတဲ့ Model ဟာ Training Data မှာ Performance အရမ်းကောင်းပြီး Testing Data မှာ တကယ်သုံးလို့ မရပဲဖြစ်နေတာ။ အခြေခံဘယ်လို အလုပ်လဲမသိပဲ ရှိသမျှ Data ကို အကုန်လုံး စုပုံထည့်လိုက်ရင် Method တွေ ဘယ်လောက်ပဲ ကောင်းတယ်ပြောပြော သုံးလို့ရတဲ့အဖြေ မထွက်ဘူးလို့ ဆိုလိုပါတယ်။

> model = glm(Survived ~ Pclass + Sex + Age + SibSp + Parch + Ticket + Fare + Cabin + Embarked, data = train, family = binomial)
> summary(model)
>
> model = glm(Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked, data = train, family = binomial)
> summary(model)

Significant level တွေ မှားနေတာမှာ Independent variable အချင်းချင်း မှီခိုမှုတွေရှိတာကြောင့် အများဆုံးအနေနဲ့ ဖြစ်နိုင်တဲ့အတွက် ပြဿနာလုပ်နေတဲ့ Variable ကို ဖယ်ထုတ်ဖို့ လိုအပ်တယ်။ ကနဦးယူဆချက်မှာ Ticket လို Independent Variable ဟာ အသက်ရှင်နိုင်တယ် မရှင်နိုင်ဘူးနဲ့ တိုက်ရိုက်တော့ မသက်ဆိုင်ဘူးလို့ ယူဆခဲ့တယ် Quantative မဟုတ်ပေမယ့် ယုတ္တိတန်တဲ့အတွက် စမ်းကြည့်လို့ရတယ် Ticket မပါပဲ Model ပြန်လုပ်ကြည့်တဲ့အခါ significant level တွေမှာ အတော်လေး အပြောင်းအလဲတွေ ရှိတာတွေ့ရတယ် Cabin နဲ့ Embarked ဆိုရင် significant မဖြစ်တော့တဲ့ အခြေအနေရှိလာတော့ Cabin ကိုပါ ထပ်ပြီးတော့ ဖယ်ကြည့်လို့ရတယ်။ Performance တွေက 0.9046246 နဲ့ 0.8575214 ဆိုပြီး AUC အသီးသီးရှိတယ်။ Ticket နဲ့ Cabin ၂ခုကို ဖယ်ထားတာကို Testing Data နဲ့ Predict လုပ်ပြီး Submit လုပ်ကြည့်တော့ Performance က 0.76555 အထိ တက်လာတယ်။

> model = glm(Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare, data = train, family = binomial)
> summary(model)

Ticket နဲ့ Cabin ၂ခုကို ဖယ်ထားတဲ့ Model အရဆိုရင် Embarked ကိုပါ ထပ်ပြီးဖယ်လို့ရမယ်လို့ စဉ်းစားလို့ရတဲ့အတွက် Embarked ကို ထပ်ပြီးတော့ ဖယ်ကြည့်လိုက်တော့ AUC ဟာ 0.8550688 ဆိုတော့ Ticket နဲ့ Cabin ၂ခုပဲ ဖယ်ထုတ်ထားတာထက် နည်းနည်းကျသွားတယ် အဲဒီတော့တကယ်တမ်း Performance ကျသွားလား သိဖို့အတွက် Testing Data နဲ့ Predict လုပ်ပြီး Submit လုပ်လိုက်တော့ Performance ဟာ 0.74641 ဖြစ်တဲ့အတွက် တကယ်တမ်းလည်း Performance ကျသွားတာတွေ့ရတော့ Ticket နဲ့ Cabin ၂ခုကိုပဲ ဖယ်ထုတ်ထားဖို့ ယာယီယူဆထားပြီး တခြား Method တွေကို ပြောင်းပြီးတော့ Apply လုပ်ပြီး Performance ကိုကြည့်ရမယ်။

> library(rpart)
> library(rpart.plot)
> model = rpart(Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked, data = train)
> prp(model)
> result = predict(model)
> table(train$Survived, result > 0.5)
    FALSE TRUE
  0   492   57
  1    97  245
> (492+245)/891
[1] 0.8271605
> ROCRpred = prediction(result, train$Survived)
> as.numeric(performance(ROCRpred, "auc")@y.values)
[1] 0.864107
> ### Prediction
> result = predict(model, newdata = test)
> writeSubmission(result, "submission_rpart.csv")

နောက် Method တခု အနေနဲ့ Decision Tree နဲ့ Model လုပ်ပြီးတော့ Performance တွေကို စမ်းကြည့်လိုက်တော့ ACC ဟာ 0.8271605 ရှိပြီးတော့ AUC က 0.864107 ရှိတဲ့အတွက် Logistic Regression ရဲ့ 0.8575214 ထက်ပိုကောင်းတာ သတိထားမိတယ် တကယ် Performance တက်လာလား စမ်းကြည့်ဖို့အတွက် Test Data နဲ့ Predict လုပ်ပြီး Submit လုပ်ကြည့်တော့လည်း 0.78469 ရှိတဲ့အတွက် Logistics Regression ထက် Performance ပိုကောင်းတာသေချာသွားတယ်။ Decision Tree မှာလည်း Embarked ကိုဖယ်ထုတ်ပြီး စမ်းကြည့်မယ်ဆိုရင် Logistic Regression လိုပဲ Performance ကျသွားတာကို တွေ့ရပါလိမ့်မယ်။

> library(randomForest)
> set.seed(100)
> model = randomForest(Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked, data = train)
  The response has five or fewer unique values.  Are you sure you want to do regression?
> result = predict(model)
> table(train$Survived, result > 0.5)
    FALSE TRUE
  0   499   50
  1   101  241
> (499+241)/891
[1] 0.8305275
> ROCRpred = prediction(result, train$Survived)
> as.numeric(performance(ROCRpred, "auc")@y.values)
[1] 0.8741359
> ### Prediction
> result = predict(model, newdata = test)
> writeSubmission(result, "submission_random_forest.csv")

Decision Tree ဟာလည်း တခါတရံမှာ Overfitting ဖြစ်တတ်တယ် အဲဒီအခါမျိုးမှာ Random Forest က ပိုပြီးတော့ အဆင်ပြေတတ်တယ် အခုကိစ္စမှာတော့ Data တွေလည်း သိပ်ပြိးတော့ များတယ်မဟုတ်သလို Independent variable တွေလည်း သိပ်များတော့ ပြဿနာသိပ်မရှိနိုင်ပေမယ့် Random Forest နဲ့လည်း စမ်းကြည့်တာ မှားတော့မမှားပါဘူး။ Random Forest မှာ နည်းနည်း အခက်အခဲရှိတာက Model တခုလုပ်ရင် နောက်တခါနဲ့ ထပ်တူမတူညီတာရှိတော့ ထွက်လာတဲ့အဖြေလည်း မတူညီတာရှိတော့ set.seed(100) လိုထည့်ထားမှပဲ Reproducible ဖြစ်လိမ့်မယ်။ Random Forest မှာ Submission Performance ဟာ 0.77033 ရှိတဲ့အတွက် Decision Tree ထက် နည်းနည်းလောက် နိမ့်ပေမယ့်လို့ Logistic Regression ထက်တော့ ပိုကောင်းတာတွေ့ရတယ်။

Performance Measurement အတွက်က Data များတယ်ဆိုရင် Training Data ထဲမှာ 80% လောက်ကိုပဲ Train အတွက်သုံးပြီး ချန်ထားတဲ့ 20% ကို Testing အဖြစ်သုံးပြီး Model ကို စိတ်ကြိုက်အနေနဲ့ စမ်းသပ်နေလို့ရတယ် Submit လုပ်ကြည့်တာက Kaggle က ၁ ရက်မှာ ၁၀ ခါပဲ ခွင့်ပြုတော့ တခုလောက်ပြောင်းကြည့် တင်ကြည့်လိုက်ဆိုပြီး လုပ်နေလို့မရဘူးပေါ့။ Performance အတော်လေး ကောင်းလာပြီလို့ ယုံကြည်ရပြီဆိုမှ Submit လုပ်ပေါ့ မမေ့ဖို့လိုတာက ပေးထားတဲ့ Testing Data ကို မသုံးခင်မှာ Training Data အားလုံးကိုသုံးထားတဲ့ Model တော့ ပြန်ပြီးတော့ Train လုပ်ရလိမ့်မယ်။ အခုကတော့ Training Data က ၈၉၁ ပဲရှိတော့ အဲလိုခွဲပြီးတော့ စမ်းသပ်တာက Training Data သိပ်နည်းသွားပြီးတော့ ပြဿနာတက်လာနိုင်တော့ နည်းနည်းပြောရခက်တယ်။

အခုအထိက Initially Clean လုပ်ထားတဲ့ Data တွေကိုမူတည်ပြီးတော့ Method တွေပြောင်းကြည့်လိုက် မလိုအပ်ပဲနဲ့ အနှောက်အယှက်ဖြစ်နေတဲ့ Independent variable တွေကို ဖယ်ထုတ်လိုက်နဲ့ စမ်းသပ်ကြည့်ပြီး Performance ကို Submit လုပ်ပြီးတော့ စမ်းကြည့်နေတာပဲ ရှိပါသေးတယ် မလိုအပ်တဲ့ Independent variable တွေကို ဖယ်ထုတ်တာမှာလည်း variable အရေအတွက်နည်းလို့သာ မှန်းပြီးတော့ ရမ်းပြီးဖယ်လို့ရနေတာပါ variable ၁ ထောင် ၂ ထောင်ဆိုရင်တော့ စနစ်တကျလုပ်မှ ရပါလိမ့်မယ်။ Initial ပဲ ရှိသေးပေမယ့် Performance က 0.78469 အထိ အမြင့်ဆုံးရတယ်ဆိုတော့ အခြေအနေက မဆိုးဘူးလို့ ပြောလို့ရပါတယ် ရေးထားတာလည်း အတော်လေးလည်း စာတွေရှည်နေပြီ ဖြစ်တဲ့အတွက် ဒီမှာပဲရပ်လိုက်ပြီး နောက်ထပ်ဆက်ပြီးတော့ Improvement ဘယ်လိုကြံဖန်ကြည့်မလဲ နောက်တပိုင်းမှပဲ ဆက်ရေးတော့မယ်။