Case

Case yang dipilih adalah:

library(dplyr)
library(ggplot2)
library(knitr)
library(plotly)
library(caret)
library(lime)
library(rsample)
library(cmplot)
library(e1071)
library(GGally)
library(leaflet)
library(lmtest)
library(lubridate)
library(randomForest)
library(readr)
library(rmarkdown)
library(rsample)
library(scales)
library(tidyverse)

Data Wrangling

Dalam proses Data Wrangling kita akan menggabungkan kedua dataset yaitu dataset data-train-flight.csv dan dataset data-train-weather.csv yang telah disimpan kedalam flight dan weather, pertama kita akan melakukan read data terlebih dahulu.

Import Data

Melakukan proses read data csv :

flight <- read.csv("data_input/data-train-flight.csv")
weather <- read.csv("data_input/data-train-weather.csv")
data_test <- read.csv("data_input/flight-data-test.csv")

Kita akan mengecek tipe data dan jumlah kolum yang terdapat di dalam masing masing data set, terutama data set flight dan weather, dan akan kita cek apakah variabel variabel didalam dataset tersebut sama dengan data_test yang akan kita gunakan nanti.

str(flight)
## 'data.frame':    4614 obs. of  17 variables:
##  $ year          : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month         : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day           : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ dep_time      : int  629 643 811 1010 1211 1314 1457 1513 1725 1825 ...
##  $ sched_dep_time: int  630 645 815 1015 1215 1315 1500 1505 1730 1829 ...
##  $ dep_delay     : int  -1 -2 -4 -5 -4 -1 -3 8 -5 -4 ...
##  $ sched_arr_time: int  833 848 1016 1210 1413 1505 1656 1703 1926 2032 ...
##  $ arr_delay     : chr  "Not Delay" "Not Delay" "Delay" "Not Delay" ...
##  $ carrier       : chr  "US" "US" "US" "US" ...
##  $ flight        : int  1019 926 675 1103 4135 1615 720 4223 449 1973 ...
##  $ tailnum       : chr  "N426US" "N178US" "N654AW" "N162UW" ...
##  $ origin        : chr  "EWR" "EWR" "EWR" "EWR" ...
##  $ dest          : chr  "CLT" "CLT" "CLT" "CLT" ...
##  $ distance      : int  529 529 529 529 529 529 529 529 529 529 ...
##  $ hour          : int  6 6 8 10 12 13 15 15 17 18 ...
##  $ minute        : int  30 45 15 15 15 15 0 5 30 29 ...
##  $ time_hour     : chr  "2013-01-01 06:00:00" "2013-01-01 06:00:00" "2013-01-01 08:00:00" "2013-01-01 10:00:00" ...
str(weather)
## 'data.frame':    7989 obs. of  14 variables:
##  $ year      : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ month     : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ day       : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ hour      : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ temp      : num  39 39 39 39.9 39 ...
##  $ dewp      : num  26.1 27 28 28 28 ...
##  $ humid     : num  59.4 61.6 64.4 62.2 64.4 ...
##  $ wind_dir  : int  270 250 240 250 260 240 240 250 260 260 ...
##  $ wind_speed: num  10.36 8.06 11.51 12.66 12.66 ...
##  $ wind_gust : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ precip    : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ pressure  : num  1012 1012 1012 1012 1012 ...
##  $ visib     : num  10 10 10 10 10 10 10 10 10 10 ...
##  $ time_hour : chr  "2013-01-01 01:00:00" "2013-01-01 02:00:00" "2013-01-01 03:00:00" "2013-01-01 04:00:00" ...
str(data_test)
## 'data.frame':    399 obs. of  16 variables:
##  $ id              : chr  "F1" "F2" "F3" "F4" ...
##  $ month           : int  12 12 12 12 12 12 12 12 12 12 ...
##  $ day             : chr  "Sun" "Sun" "Sun" "Sun" ...
##  $ dep_delay       : int  -7 -7 6 -4 -3 -7 -8 49 -6 -7 ...
##  $ sched_arr_hour  : int  6 8 8 8 10 12 15 14 16 17 ...
##  $ sched_arr_minute: int  51 11 17 35 21 18 6 30 56 21 ...
##  $ sched_dep_hour  : int  5 6 6 6 8 10 13 12 15 15 ...
##  $ sched_dep_minute: int  0 1 15 30 20 23 15 29 0 20 ...
##  $ temp            : num  35.1 33.8 33.8 33.8 39 ...
##  $ dewp            : num  28 26.6 26.6 26.6 30.9 ...
##  $ humid           : num  75.3 78.5 78.5 78.5 72.5 ...
##  $ wind_dir        : int  10 40 40 40 30 0 210 230 210 210 ...
##  $ wind_speed      : num  4.6 5.75 5.75 5.75 3.45 ...
##  $ precip          : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ visib           : num  10 10 10 10 10 10 10 10 10 10 ...
##  $ arr_status      : logi  NA NA NA NA NA NA ...

Sebelum kita menjoin data flight dan weather terlebih dahulu kita akan mngecek apakah ada variabel variebl yang memiliki tipe yang berbeda dengan data test dan apakah ada data variabel yang memiliki missing value, dan kita akan membuang beberapa kolom yang tidak sama dengan yang ada didalam dataset atau data yang memiliki pengaruk kecil terhadap hasil prediksi. Seperti ketidaksamaan isi kolom day, variabel tahun karena data ini hanya mengandung data dalam satu tahun yaitu 2013, dan pada variabel target di dalam data test target variabel bernama arr_status sedangkan dalam flight bernama arr_delay kita akan mengganti nama variabel target di data test menjadi arr_delay dan lain-lain, Kolom yang akan di hilangkan akan dijelaskan dibawah.

Explanatory Data Analysis

plot1 <- ggplot(data = flight, aes(x=arr_delay, fill = arr_delay)) +
  geom_bar()+
  facet_wrap(~carrier) +
  labs(title = "Fligth Delay for each Airlines", x = NULL, y = NULL)
plot1

Dapat dilihat bahwa maksapai EV dan US memiliki penerbangan yang delay terbanyak dalam satu tahun, tapi kalau kita lihat pada maskpaia EV jumlah penerbangan delay dan not delay hampir memiliki jumlah yang sama, sedangkan maskapai US memliki tingkat performansi yang lebih baik dikarenakan jumlah proporsi penerbangan not delay lebih tinggi dari delay dan cocok dapat digunakan sebagai calon penumpang untuk memprediksi penerbangan delay atau not delay

Model Fiting and Evaluation

Sebelum menjoin data kita dean melakukan pemodelan kita akan melihat variabel di masing masing data dan mentransofrm data tresebut agar varibal variebel didalam data memiliki type data yang sama dengan data test. Kita lihat terlebih dahulu pada varibel day dalam data flight, dalam data flight variabel day memiliki tipe hari yang dilambangkan dengan tanggal sedangkan didalam data test variabel day memiliki tipe hari dalam bahasa inggris yang diskingkat. Kita akan merubah isi variabel day terlebeih dahulu.

flight$day <- wday(flight$time_hour, 
     label = T)

Setelah mengganti nama hari kita akan apakah ada data yang memilki missing values atau NA dalam data flight

colSums(is.na(flight))
##           year          month            day       dep_time sched_dep_time 
##              0              0              0            111              0 
##      dep_delay sched_arr_time      arr_delay        carrier         flight 
##            111              0            120              0              0 
##        tailnum         origin           dest       distance           hour 
##             48              0              0              0              0 
##         minute      time_hour 
##              0              0

Terdapat 4 (empat) field yang memiliki missing values, yaitu field: dep_time, dep_delay, arr_delay, dan tail_num. Dan kita lihat variabel arr_delay memilki missing values terbanyak. Semua missing values yang terdapat pada baris di mana variabel arr_delay memiliki NA. Variabel arr_delay berisi data kategorikal, kita tidak memiliki cukup informasi untuk melakukan imputasi, maka kita akan menghapus NA tersebut dengan menggunakan fungsi na.omit :

flight <- na.omit(flight)
colSums(is.na(flight))
##           year          month            day       dep_time sched_dep_time 
##              0              0              0              0              0 
##      dep_delay sched_arr_time      arr_delay        carrier         flight 
##              0              0              0              0              0 
##        tailnum         origin           dest       distance           hour 
##              0              0              0              0              0 
##         minute      time_hour 
##              0              0

Setelah kita menghilangkan NA didalam data flight kita terlebih dahulu akan merubah nama variabel target dalam data test dari arr_status menjadi arr_delay, dan mernghilangkan varibel id.

data_test2 <- rename(data_test, arr_delay = arr_status)
data_test2 <- data_test2 %>% 
   select(-c(id))

Sekarang kita akan melihat variabel-variabel didalam data weather.

colSums(is.na(weather))
##       year      month        day       hour       temp       dewp      humid 
##          0          0          0          0          1          1          1 
##   wind_dir wind_speed  wind_gust     precip   pressure      visib  time_hour 
##        247          1       6270          0        827          0          0

Kita lihat ada 3 variabek didalam data weather yang tidak digunakan didalam variabel data test yaitu : wind_gust, pressure. Wind gust juga memiliki missing values yang cukup banyak dan kita tidak akan menggunakan variabel tersebut, sedangkan disini saya akan membuat variabel day dikarenakan variabel day yang dimilik data weather sama dengan yang dimilik oleh data flight dan agar kita tidak perlu merubah isi variabel day menjadi nama hari yang disingkat.

weather <- weather %>% 
   select(-c("wind_gust", "day", "pressure"))

Setalah membuang ketiga varibel didalam data weather kita akan menggabungkan kedua data yang kita miliki yaitu data flight dan data weather

flight_weather <- flight %>% 
  left_join(weather) 
## Joining, by = c("year", "month", "hour", "time_hour")
colSums(is.na(flight_weather))
##           year          month            day       dep_time sched_dep_time 
##              0              0              0              0              0 
##      dep_delay sched_arr_time      arr_delay        carrier         flight 
##              0              0              0              0              0 
##        tailnum         origin           dest       distance           hour 
##              0              0              0              0              0 
##         minute      time_hour           temp           dewp          humid 
##              0              0             13             13             13 
##       wind_dir     wind_speed         precip          visib 
##            183             13             12             12

Setelah kita menggabungkan kedua data kita akan melihat data - data yang memiliki missing values, Terdapat 7 (lima) varibel dengan missing value, yaitu: temp, dewp, humid, wind_dir, dan wind_speed, precip, dan visib. Variabel win_dir memiliki banyak missing value sehingga tidak dapat menggunakan metode imputasi, kita akan menghapus barus yang mengandung missing values pada variabel wind_dir. Sedangkan untuk variabel yang lain kita lakukan pengecekan apakah terdapat outlier.

flight_weather %>%
  select(temp, dewp, humid, wind_speed) %>%
  boxplot()

Berdasarkkan boxplot di atas terlihat bahwa wind_speed memiliki outlier, sehingga kita lakukan imputasi dengan menggunakan median, sedangkan ketiga field lainnya kita imputasi dengan menggunakan mean dan median. Setelah itu kita hapus baris yang mengandung issing value pada field wind_dir. Sedangkan outlier pada variabel visib tidak akan kita buang.

flight_weather <- flight_weather %>%
  mutate(temp = replace_na(temp, mean(temp)),
         dewp = replace_na(dewp, mean(dewp)),
         humid = replace_na(humid, mean(humid)),
         wind_speed = replace_na(wind_speed, median(wind_speed))) %>%
  na.omit()

Lalu kita akan merubah beberapa nama varibel didalam data flight weather agar sama dengan data test, pertama variabel minute hour yang melambangkan sched_dep_minute dan sched_dep_hour dalam data test.

flight_weather <- rename(flight_weather, sched_dep_minute = minute)
flight_weather <- rename(flight_weather, sched_dep_hour = hour)

Dan kita akan memisahkan variebl shed_arr_time yang mengandung jam dan menit waktu sampai agar lebih mudah kita lihat dan diubah menjadi sched_arr_hour dan sched_arr_minute seperti di dalam data test

flight_weather <- flight_weather %>% 
   separate(sched_arr_time, c("sched_arr_hour", "sched_arr_minute"), sep = "(?=\\d{2}$)")

Setalaj itu kita akan mengahilang beberapa variabel didalam data flight_weather, yaitu variabel time_hour,sched_dep_time, tailnum,year,dep_time,year, origin,dest, carrier,flight, distance. Variebel time_hour dan sched_dep_time sudah di wakilkan oleh variabel sched_dep_minute dan sched_dep_hour, dan variabel yang lain tidak berpengaruh dalam pengujian data test karen tidak terdapat di dalam data test yang akan kita uji nanti.

flight2 <- flight_weather %>% 
   select(-c(time_hour,sched_dep_time, tailnum,year,dep_time,year, origin,dest, carrier,flight, distance))
colSums(is.na(flight2))
##            month              day        dep_delay   sched_arr_hour 
##                0                0                0                0 
## sched_arr_minute        arr_delay   sched_dep_hour sched_dep_minute 
##                0                0                0                0 
##             temp             dewp            humid         wind_dir 
##                0                0                0                0 
##       wind_speed           precip            visib 
##                0                0                0

Setlah itu kita akan merubah tipe data dari empat variabel yaitu arr_delay, sched_arr_minute, sched_dep_hour, day agar sesuai dengan tipe data didalam data test

flight2 <- flight2 %>% 
   mutate(arr_delay = as.factor(arr_delay)) %>% 
   mutate(sched_arr_minute = as.integer(sched_arr_minute)) %>% 
   mutate(sched_arr_hour = as.integer(sched_dep_hour)) %>% 
   mutate(day = as.character(day))

Pemodelan Random Forest

Model pertama yang akan kita buat adalah Random Forest, sebelum membuat model terlebih dahulu kita melakukan cross-validation terhadap data dengan mengambil proporsi 80% sebagai data training dan 20% sebagai data validation. Pembentukan sampel dengan menggunakan random sample.

RNGkind(sample.kind = "Rounding")
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(100)
intrain <- sample(nrow(flight2), nrow(flight2)*0.8)
flight_train <- flight2[intrain,]
flight_test <- flight2[-intrain,]

Selanjutnya kita melakukan pengecekan apakah terdapat class imbalance pada dataset flight_train:

prop.table(table(flight_train$arr_delay))
## 
##     Delay Not Delay 
## 0.3312065 0.6687935

Data variabel target pada dataset flight_train cukup balance : Delay : Not Delay = 0.34 : 0.66, tetapi untuk hasil yang lebih baik disini kita akan melakukan balancing menggunakan metode downsample.

flight_train_down <- downSample(x = flight_train %>% select(-arr_delay),
                         y = as.factor(flight_train$arr_delay),
                         yname = "arr_delay")
predictor <- flight_train %>% select(-arr_delay)
target <- flight_train$arr_delay
diab_train_down <- downSample(x = predictor, y = target, 
                              yname = "arr_delay")
prop.table(table(diab_train_down$arr_delay))
## 
##     Delay Not Delay 
##       0.5       0.5

Selanjutnya kita model Random Forest dengan k-fold cross validation (k=10) dan pembuatan set k-fold tersebut dilakukan sebanyak 6 kali: Model telah di run dan disimpan kedalam flight_forest12.RDS

#set.seed(128)

#control <- trainControl(method="repeatedcv", number = 10, repeats = 6)

#flight_model13 <- train(arr_delay ~ ., data = flight_train_down, method = "rf", trControl = control)

#saveRDS(flight_model13, "flight_forest13.RDS") # simpan model
#flight_model13

Read model random forest dengan blancing downsample yang telah kita simpan

flight_forest_down <- readRDS("flight_forest13.RDS")
flight_forest_down
## Random Forest 
## 
## 2284 samples
##   14 predictor
##    2 classes: 'Delay', 'Not Delay' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 6 times) 
## Summary of sample sizes: 2056, 2055, 2056, 2056, 2056, 2056, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##    2    0.7977936  0.5955981
##   10    0.7926137  0.5852399
##   19    0.7842970  0.5686064
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 2.

Untuk melihat akurasi model, kita dapat melihat melalui nilai Out of Bag Error

flight_forest_down$finalModel
## 
## Call:
##  randomForest(x = x, y = y, mtry = param$mtry) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 2
## 
##         OOB estimate of  error rate: 19.92%
## Confusion matrix:
##           Delay Not Delay class.error
## Delay       845       297   0.2600701
## Not Delay   158       984   0.1383538

Pada model di atas nilai Out of Bag Error sebesar 19.12%. Berarti akurasi model pada datatest (out of bag data) adalah 80,88%

Prediksi pada data validation:

flight_pred_down <- predict(flight_forest_down, newdata = flight_test)
confusionMatrix(flight_pred_down , flight_test$arr_delay, positive = "Delay")
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  Delay Not Delay
##   Delay       229        71
##   Not Delay    78       484
##                                           
##                Accuracy : 0.8271          
##                  95% CI : (0.8002, 0.8518)
##     No Information Rate : 0.6439          
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.6212          
##                                           
##  Mcnemar's Test P-Value : 0.623           
##                                           
##             Sensitivity : 0.7459          
##             Specificity : 0.8721          
##          Pos Pred Value : 0.7633          
##          Neg Pred Value : 0.8612          
##              Prevalence : 0.3561          
##          Detection Rate : 0.2657          
##    Detection Prevalence : 0.3480          
##       Balanced Accuracy : 0.8090          
##                                           
##        'Positive' Class : Delay           
## 

Model yang ingin dicapai adalah dengan metriks sebagai berikut: - Accuracy > 75% - Sensitifity/Recall > 73% - Specificity > 75% - Precision > 70%, dalam pengujian data menggunakan model rf kedalam data validation atau flight_test metriks yang di inginkan sudah terpenuhi, dan kita akan membandingkan dengan data balncing yang menggunakan upsmaple

Menggunakan Upsampling

flight_train_up <- upSample(x = flight_train %>% select(-arr_delay),
                         y = as.factor(flight_train$arr_delay),
                         yname = "arr_delay")
#set.seed(128)

#control <- trainControl(method="repeatedcv", number = 5, repeats = 3)

#flight_model14 <- train(arr_delay ~ ., data = flight_train_up, method = "rf", trControl = control)

#saveRDS(flight_model14, "flight_forest14.RDS") # simpan model
#flight_model14
flight_forest_up <- readRDS("flight_forest14.RDS")
flight_forest_up
## Random Forest 
## 
## 4612 samples
##   14 predictor
##    2 classes: 'Delay', 'Not Delay' 
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 6 times) 
## Summary of sample sizes: 4150, 4150, 4150, 4152, 4152, 4151, ... 
## Resampling results across tuning parameters:
## 
##   mtry  Accuracy   Kappa    
##    2    0.9172479  0.8344950
##   10    0.9230304  0.8460608
##   19    0.9208974  0.8417940
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was mtry = 10.
flight_forest_up$finalModel
## 
## Call:
##  randomForest(x = x, y = y, mtry = param$mtry) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 10
## 
##         OOB estimate of  error rate: 6.94%
## Confusion matrix:
##           Delay Not Delay class.error
## Delay      2161       145  0.06287944
## Not Delay   175      2131  0.07588899
flight_pred_up <- predict(flight_forest_up, newdata = flight_test)
confusionMatrix(flight_pred_up , flight_test$arr_delay, positive = "Delay")
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  Delay Not Delay
##   Delay       198        26
##   Not Delay   109       529
##                                          
##                Accuracy : 0.8434         
##                  95% CI : (0.8174, 0.867)
##     No Information Rate : 0.6439         
##     P-Value [Acc > NIR] : < 2.2e-16      
##                                          
##                   Kappa : 0.6366         
##                                          
##  Mcnemar's Test P-Value : 1.696e-12      
##                                          
##             Sensitivity : 0.6450         
##             Specificity : 0.9532         
##          Pos Pred Value : 0.8839         
##          Neg Pred Value : 0.8292         
##              Prevalence : 0.3561         
##          Detection Rate : 0.2297         
##    Detection Prevalence : 0.2599         
##       Balanced Accuracy : 0.7991         
##                                          
##        'Positive' Class : Delay          
## 

Dari hasil test model random forest di atas dapat dilihat penggunaan balancing menggunakan upsampling dan nilai k dalam k-fold CV atau number = 5 dan pengulangan dalam melakukan k-fold CV sebanyak 3 menghasilkan nilai accuracy, recall, precision, specificity yang kurang baik di bandingkan model downsample dengan number kfold 10 dan repeat = 6

Seandainya sebuah persuhaan penerbang ingin melihat model mana yang cocok, saya akan memilih model dengan precision tinggi, karena model dengan precision tinggi dapat mengidentifikasi apakah sebuah penerbangan akan mengalami Delay dengan lebih akurat, sehingga maskapai dapat mempersiapkan hal-hal yang diperlukan oleh pelanggan atau dapat mengantisipasi keterlamabatan tersbut demi kenyamanan pelanggan.

Selanjutnya kita akan memprediksi dataset data_test2 dengan menggunakan kedua model untuk melihat model mana yang paling baik dalam memprediksi data_test2.

Model Random Forest Downsampling

sub_pred_down <- predict(flight_forest_down, newdata = data_test2)
submission_rf_down <- data.frame(
  id = data_test$id,
  arr_status = sub_pred_down
)
write.csv(submission_rf_down, "submission_rf_down.csv", row.names = F)

# Model Random Forest Upsampling

sub_pred_up <- predict(flight_forest_up, newdata = data_test2)
submission_rf_up <- data.frame(
  id = data_test$id,
  arr_status = sub_pred_up
)
write.csv(submission_rf_up, "submission_rf_up.csv", row.names = F)

Dapat dilihat overall model up samplign memiliki akurasi presisi dan specifity yang jauh lebih baik sedangkan model upsampling memiliki recall yang lebih baik.

Interpretasi

Jika hal ini terjadi pada kasus di kehidupan nyata di mana kita hanya memiliki train dataset yang berasal dari histori transaksi dan test dataset adalah data terkini yang harus kita prediksi, maka tentu kita akan memilih model flight_forest_down yang memiliki performa lebih baik (dalam hal ini precision dan accuracy) dari model flight_forest_up pada prediksi data validation.

Berdasarkan kondisi tersebut, maka kita akan melakukan interpretasi model flight_forest_down dengan menggunakan LIME

set.seed(123)
explainer <- lime(x = flight_train_down %>% select(-arr_delay), 
                  model = flight_forest_down)
## Warning: precip does not contain enough variance to use quantile binning. Using
## standard binning instead.
## Warning: visib does not contain enough variance to use quantile binning. Using
## standard binning instead.

Kemudian kita akan memilih case yang ingin kita interpretasikan, dalam code dibawah kita akan meilhat data 5 samapai ke 8 data data_test2 dengan jumlah features 10 dan menggunakan manhattan sebagai distance function. Dan kita akan menampilan penjelasan dari model menggunakan plot yang kita tampilkan dibawah:

explanation_rf <- explain(data_test2 %>% select(-arr_delay) %>% slice(5:8), 
                       labels = "Delay",
                       n_permutations = 500,
                       dist_fun = "manhattan",
                       explainer = explainer, 
                       kernel_width = 3,
                       n_features = 10)
plot_features(explanation_rf)

Dari plot di atas kita dapat melihat case 1 dengan label: delay merupakan variabel target yang ingin kita jelaskan. pada case 1, case 2, dan case 3 dapat dilihat bahwa case tersebut memiliki elemen probability yang menunjukan nilai yang sangat rendah yaitu 0.22. 0.20. 0.26, sehingga dapat dikatakan bahwa prediksi yang benar adalah Not Delay dan bukan Delay atau pada case tersebut diprekdiksi tidak terjadinya keterlambatan pesawat ke bandara tujuan padahal terjadi keterlambatan. Sedangkan pada case 4 memiliki elemen probability yang meolnajk tinggi yaitu 0.81, sehingga dapat dikatakan pada case tersebut terprediksi terjadinya delay pesawat ke bandara tujuan.

Pada plot diatas terdapat bar berwarna bitu dan merah yang menunjukan apakan features yang ditampilkan mendukung (Supports) atau berlawanan (Contradicts) jika sebuah data di beri label delay. Explanation Fit menunjukkan seberapa baik LIME dapat menjelaskan model tersebut, hal ini seperti R-squared pada linear regression. Pada grafik di atas terlihat bahwa LIME cukup baik dalam menjelaskan model, hal ini ditunjukkan oleh EXplanation Fit yang cukup signifikan (> 0.53).

Jika kita bandingkan dengan interpretable machine learning seperti logistic regression dan decision tree, di mana setiap features di dalam semua cases memiliki nilai koefisien yang sama, jadi jika ada case yang mendapatkan prediksi positif atau dalam kasus ini DELAY dapat dengan mudah dipahami features-features mana yang memiliki pengaruh yang cukup besar terhadap suatu prediksi. Pada Random Forest juga dapat menggunakan variable importance yangmerupakan bagian dari perhitungan gini importance. Angka tersebut berupa persentase yang menunjukkan besarnya pengaruh features (dalam persentase) terhadap hasil prediksi.Sedangkan pada LIME, interpretasi diberikan kepada setiap case yang ada dengan cara menunjukkan bobot atau weight pada setiap features berserta pengaruhnya terhadap suatu prediksi apakah mendukung (supports) atau berlawanan (contradicts).

Kesimpulan

Berdasarkan 2 model yang telah dibuat yaitu model flight_forest_up dan flight_forest_down, dapat dikatakan bahwa suatu masalah keterlambatan yang dimiliki oleh suatu maskapai dapat diselesaikan dengan menggunakan machine learning.. Model yang digunakan dalam kasus ini adalah random forest dimana model random forest cukup baik dalam memprediksi data train yang di bagi dari data utama, dan model random forest juga memenuhi metrik accuracy, precision dan specificity yang ditentukan di dalam data test. Namun dalam kasus ini hasil model lebih baik jika kita melakukan balancing dengan metode downsample sehingga menghasilkan hasil yang lebih baik.