library(keras)
## Warning: package 'keras' was built under R version 3.6.3
library(caret)
## Warning: package 'caret' was built under R version 3.6.2
## Loading required package: lattice
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 3.6.2
library(dplyr)
## Warning: package 'dplyr' was built under R version 3.6.3
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(readr)
## Warning: package 'readr' was built under R version 3.6.2
library(GGally)
## Warning: package 'GGally' was built under R version 3.6.2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## 
## Attaching package: 'GGally'
## The following object is masked from 'package:dplyr':
## 
##     nasa
library(rsample)
## Warning: package 'rsample' was built under R version 3.6.2
## Loading required package: tidyr
## Warning: package 'tidyr' was built under R version 3.6.2

1.Model Deep Learning

Data Preprocess and Exploratory Data Analysis

  1. Read Data
concrete_nn<- read.csv("data/data-train.csv")
  1. Menghapus variabel yang tidak diperlukan
concrete_nn_cl <- concrete_nn[,-1]
  1. Deteksi/ remove outlier
boxplot(concrete_nn_cl)

b <- data.frame(concrete_nn_cl,plot=FALSE)
c <- boxplot(b$cement,plot=FALSE)$out
d<- boxplot(b$slag,plot=FALSE)$out
e<- boxplot(b$flyash,plot=FALSE)$out
f <- boxplot(b$water,plot=FALSE)$out
g<- boxplot(b$super_plast,plot=FALSE)$out
h<- boxplot(b$coarse_agg,plot=FALSE)$out
i<- boxplot(b$fine_agg,plot=FALSE)$out
j<- boxplot(b$age,plot=FALSE)$out

k<- b %>%
  filter(!slag==d) %>%
  filter(!water==f) %>%
  filter(!super_plast==g) 
## Warning in slag == d: longer object length is not a multiple of shorter object
## length
## Warning in water == f: longer object length is not a multiple of shorter object
## length
## Warning in super_plast == g: longer object length is not a multiple of shorter
## object length
k <- k[,-10]

Melihat korelasi antar variabel

ggcorr(concrete_nn_cl,label=T,label_size = 3)

Berdasarkan plot hasil korelasi diatas dapat disimpulkan bahwa: - ‘strength’ memliki korelasi positif dengan ‘age’ - ‘strength’ memliki korelasi positif yang cukup kuat dengan ‘cement’ yaitu sebesar 0.5 - ‘super_plast’ berkorelasi linear dengan ‘strength’

Model Fitting and Evaluation

Cross Validation

# Jumlah proporsi yang digunakan adalah sebesar 90% untuk data train
set.seed(100)
idx <- initial_split(k, prop = 0.9)
concrete_train <- training(idx)
concrete_val <- testing(idx)

Ubah data menjadi matrix

mtrain <- data.matrix(concrete_train)
mval<- data.matrix(concrete_val)

Memisahkan data prediktor dan data target

train_x <- mtrain[,-9]
val_x <- mval[,-9]

train_y <- mtrain[,9]
val_y <- mval[,9]

Ubah data prediktor menjadi array

train_x_array<- array_reshape(train_x,dim(train_x))
val_x_array<- array_reshape(val_x,dim(val_x))

Melakukan Scalling pada prediktor

# Scalling pada data prediktor.
train_x_keras<- scale(train_x_array,scale=T)
val_x_keras <- scale(val_x_array, scale=T)

Membuat Architecture dan Model fitting Deep Learning

set.seed(100)
initializer <- initializer_random_normal(seed = 100)
  1. Model awal dengan tuning; activation(hidden layer): relu,dan optimizer = sgd
model_sgd <- keras_model_sequential() %>% 
  layer_dense(units = 256, activation = "relu",input_shape = 8,
              kernel_initializer = initializer, bias_initializer = initializer) %>%
    layer_dense(units = 1,activation = "linear",
              kernel_initializer = initializer, bias_initializer = initializer)
model_sgd%>% 
  compile(loss = "mean_absolute_error", 
          optimizer = optimizer_sgd(lr = 0.001),
          metrics="mean_absolute_error")
  1. Model setelah tuning
set.seed(123)
initializer <- initializer_random_normal(seed = 123)
model_adam <- keras_model_sequential() %>% 
  layer_dense(units = 256, activation = "tanh",input_shape = 8,
              kernel_initializer = initializer, bias_initializer = initializer) %>%
  layer_dense(units = 1,activation = "linear",
              kernel_initializer = initializer, bias_initializer = initializer)
model_adam%>% 
  compile(loss = "mean_absolute_error", 
          optimizer = optimizer_adam(lr = 0.001),
          metrics="mean_absolute_error")

Model Fitting

history_sgd <- model_sgd %>%
  fit(train_x_keras, train_y, epoch = 70, batch_size = 1) 

history_adam <- model_adam %>%
  fit(train_x_keras, train_y, epoch = 70, batch_size = 1) 

Prediction Performance

Membuat prediksi

pred_sgd <- predict(model_sgd,val_x_keras)
pred_adam <- predict(model_adam,val_x_keras)

Melakukan evaluasi pada data validasi

evaluation_sgd <- caret::postResample(pred_sgd,val_y)
evaluation_sgd
##      RMSE  Rsquared       MAE 
## 7.4702353 0.8113981 5.5800289
evaluation_adam <- caret::postResample(pred_adam,val_y)
evaluation_adam
##      RMSE  Rsquared       MAE 
## 6.6320764 0.8587906 4.8375245

Berdasarkan penjabaran di atas dapat dilihat bahwa Rsquared dan MAE yang lebih baik dihasilkan oleh model yang sudah dituning menggunakan activation function pada hidden layer = “tanh” dengan optimizer adam.

Berikutnya adalah step untuk mengetahui apakah model Neural Network terbaik secara MAE dan Rquared (yaitu model_adam) overfit atau tidak

# Rsquared dan MAE pada data train
history_adam
## Trained on 739 samples (batch_size=1, epochs=70)
## Final epoch (plot to see history):
##                loss: 4.102
## mean_absolute_error: 4.102
fit_adam <- predict(model_adam,train_x_keras)
evaluation_fit_adam <- caret::postResample(fit_adam,train_y)
evaluation_fit_adam
##      RMSE  Rsquared       MAE 
## 5.7312280 0.8839779 4.1968297

Berdasarkan Jabaran diatas dapat dilihat bahwa Rsquared pada data train dengan model_adam= 88.37% sementara MAE berkisar antara 4.125 sampai 4.298. Jika dibandingkan dengan data val dimana Rsquared hanya 85.6 persen dan MAE yang lebih besar yaitu 4.839, dapatdisimpulkan bahwa model terbaik neural network ini (model Adam) Overfit

Kesimpulan: model_adam ini masih belum memberikan Rsquared dan MAE yang memuaskan ketika dicobakan ke data validasi dimana Rquared = 0.8565853 (masih dibawah 90%) dan MAE = 4.8394606 (Masih lebih besar dari 4). Oleh karena itu model ini tidak direkomendasikan sebagai model FINAL

2 Model: Random Forest

Data Preprocess and Exploratory Data Analysis

  1. Membaca data
concrete<- read.csv("data/data-train.csv")
glimpse(concrete)
## Observations: 825
## Variables: 10
## $ id          <fct> S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13,...
## $ cement      <dbl> 540.0, 540.0, 332.5, 332.5, 198.6, 380.0, 380.0, 475.0,...
## $ slag        <dbl> 0.0, 0.0, 142.5, 142.5, 132.4, 95.0, 95.0, 0.0, 132.4, ...
## $ flyash      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ water       <dbl> 162, 162, 228, 228, 192, 228, 228, 228, 192, 192, 228, ...
## $ super_plast <dbl> 2.5, 2.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...
## $ coarse_agg  <dbl> 1040.0, 1055.0, 932.0, 932.0, 978.4, 932.0, 932.0, 932....
## $ fine_agg    <dbl> 676.0, 676.0, 594.0, 594.0, 825.5, 594.0, 594.0, 594.0,...
## $ age         <int> 28, 28, 270, 365, 360, 365, 28, 28, 90, 28, 28, 90, 90,...
## $ strength    <dbl> 79.99, 61.89, 40.27, 41.05, 44.30, 43.70, 36.45, 39.29,...
  1. Buang data yang tidak diperlukan dalam modelling
concrete_clean<- concrete[,-1]
  1. Visualisasi Outlier
#melihat outlier dengan menggunaan argument 'boxplot' terhadap data 'concrete'
boxplot(concrete_clean)

# Remove Outlier

b <- data.frame(concrete_clean)
c <- boxplot(b$cement,plot = FALSE)$out
d<- boxplot(b$slag,plot = FALSE)$out
e<- boxplot(b$flyash,plot = FALSE)$out
f <- boxplot(b$water,plot = FALSE)$out
g<- boxplot(b$super_plast,plot = FALSE)$out
h<- boxplot(b$coarse_agg,plot = FALSE)$out
i<- boxplot(b$fine_agg,plot = FALSE)$out
j<- boxplot(b$age,plot = FALSE)$out

k<- b %>%
  filter(!slag==d) %>%
  filter(!water==f) %>%
  filter(!super_plast==g) 
## Warning in slag == d: longer object length is not a multiple of shorter object
## length
## Warning in water == f: longer object length is not a multiple of shorter object
## length
## Warning in super_plast == g: longer object length is not a multiple of shorter
## object length
boxplot(k)

Terdapat outlier pada variabel ‘slag’, ‘water’,‘super_plast’,‘fine_agg’ dan ‘age’. SElanjutnya outlier ‘slag’, ‘water’,‘super_plast’ dibuang untuk meningkatkan performance pada model nantinya. Selain itu pada data ini scalling jug tidak dilakukan karena 2 hal:

  1. Model yang digunakan adalah random forest, dimana random forest tidak membutuhkan proses scalling

  2. Hasil scalling juga tidak memberikan dampak yang signifikan terhadap keakuratan model maupun hasil prediksi

  3. Melihat korelasi antar variabel

ggcorr(concrete_clean,label=T,label_size = 3)

Berdasarkan plot hasil korelasi diatas dapat disimpulkan bahwa: - ‘strength’ memliki korelasi positif dengan ‘age’ - ‘strength’ memliki korelasi positif yang cukup kuat dengan ‘cement’ yaitu sebesar 0.5 - ‘super_plast’ berkorelasi linear dengan ‘strength’

Model Fitting and Evaluation

  1. Cross Validation
# Berikut adalah proses cross validation dengan proporsi data train sebesar 90 persen 
library(rsample)
set.seed(100)

idx <- initial_split(k, prop = 0.90)
concrete_train <- training(idx)
concrete_val <- testing(idx)
  1. Membuat model random forest menggunakan data train dengan menerapkan k-fold cross validation
set.seed(100)
# Model tanpa tuning ;"number" dan "repeats"

notune <- trainControl(method = "repeatedcv")
forest_notune <- train(strength ~.,data=concrete_train,method = "rf", trControl= notune)

forest_notune 
## Random Forest 
## 
## 739 samples
##   8 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 1 times) 
## Summary of sample sizes: 666, 665, 665, 666, 666, 664, ... 
## Resampling results across tuning parameters:
## 
##   mtry  RMSE      Rsquared   MAE     
##   2     5.831381  0.8980418  4.384775
##   5     5.123437  0.9096274  3.749203
##   8     5.166639  0.9069800  3.723833
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was mtry = 5.
# Model dengan menggunakan tuning;"number" = 10 dan "repeats" = 1

tune <- trainControl(method = "repeatedcv",number = 10,repeats = 1)
forest_tune <- train(strength ~.,data=concrete_train,method = "rf", trControl= tune)

forest_tune
## Random Forest 
## 
## 739 samples
##   8 predictor
## 
## No pre-processing
## Resampling: Cross-Validated (10 fold, repeated 1 times) 
## Summary of sample sizes: 664, 666, 666, 665, 665, 666, ... 
## Resampling results across tuning parameters:
## 
##   mtry  RMSE      Rsquared   MAE     
##   2     5.941214  0.8937821  4.415363
##   5     5.277163  0.9037886  3.817438
##   8     5.331403  0.8999934  3.785199
## 
## RMSE was used to select the optimal model using the smallest value.
## The final value used for the model was mtry = 5.
# fb_forest
# # saveRDS(fb_forest, file = "concrete_model.rds")
# 
# concrete_model <- readRDS("concrete_model.rds")
# concrete_model
# concrete_model$finalModel

Berdasarkan jaaran di atas dapat dilihat hasil evaluasi error MAE dan Rsquared cukup tinggi yaitu 90.6 dan 3.72 untuk model forest_notune dan Rsquared= 0.89, MAE=3.78 namun masih harus dibandingkan dengan prediksi pada data validasi (val) untuk membandingkan model terbaik. Untuk model Random Forest, normalisasi atau scale tidak berpengaruh sgnifikan. Olehkarena itu normalisasi tidak dilakukan. Begitu juga dengan transformasi data seperti log-transform juga tidak dibutuhkan karena target memiliki kelas numerik

Prediction Performance

  1. Prediction menggunakan data Validasi (val)
#prediction tanpa tune
pred_notune <- predict(forest_notune,concrete_val)

#Prediction dengan tune
pred_tune <- predict(forest_tune,concrete_val)

Mengevaluasi model random forest

library(caret)
eval_notune <- caret::postResample(pred_notune,concrete_val$strength)
eval_tune <- caret::postResample(pred_tune,concrete_val$strength)

eval_notune
##      RMSE  Rsquared       MAE 
## 5.0801937 0.9108537 3.6154340
eval_tune
##      RMSE  Rsquared       MAE 
## 5.0088060 0.9136723 3.5325130

Berdasarkan hasil komparasi di atas dapat dilihat model yang dituning (forest_tune) menggunkan tuning;“number” dan “repeats” memberikan Rsquared maupun MAE yang lebih baik yaitu Rsquared = 0.913 dan MAE=3.53.

Mengetahui apakah model overfit atau tidak

Model yang saya pilih di sini adalah model terbaik secara hasil menggunakan data validasi yaitu forest_tune

  • Rsquared dan MAE pada data train:

Rsquared MAE
0.8999934 3.785199

  • Rsquared dan MAE pada data validation (val)

Rsquared MAE 0.9136723 3.5325130

Berdasarkan jabaran di atas dapat disimpulkan baha model terbaik random forest yaitu model “forest_tune” tidak overfit. Dan selanjutnya akan digunakan sebagai model FINAL dengan alasan selain tidak overfit model ini juga memberikan performance yang baik dimana Rsquared =0.9136723 (sudah lebih dari 90%) dan MAE = 3.5325130 (sudah mencapai nilai < 4)

  1. Prediction menggunakan data test
concrete_test <- read.csv("data/data-test.csv")
concrete_test_clean <- concrete_test[,-1]

Prediksi menggunakan data test

pred_test <- predict(forest_tune,concrete_test_clean)

Menggabungkan dengan data test

strength <- data.frame (pred_test)
concrete_id <- data.frame(concrete_test$id)

colnames(concrete_id)[1] = "id"
colnames(strength)[1] = "strength"

Z<- cbind(concrete_id,strength)
submit<- write.csv(Z,"submission.csv",row.names=FALSE)

Interpretation

Interpretasi menggunakan lime Setelah memabandingkan model 2 model yaitu Deep Learning dan Random Forest dapat disimpulkan bahwa Model Random Forest memberikan Rsquared dan MAE yang lebih baik. Adapun model Deep Learning dari yang saya amati sekalipun masih berpotensi memberikan RQuared yang besar namun nilai MAE nya selalu memberikan hasil yang kurang baik. Oleh karena itu Interpretasi akan dilakukan pada model terbaik yaitu model RANDOM FOREST

Interpretasi dilakukan pada model terbaik yaitu model dari Random Forest

library(lime)
## Warning: package 'lime' was built under R version 3.6.3
## 
## Attaching package: 'lime'
## The following object is masked from 'package:dplyr':
## 
##     explain
set.seed(124)
explainer <- lime(x=concrete_clean[,-9],model =forest_notune)
explanation <- explain(x=concrete_clean[,-9] %>% slice(1:5),
                       explainer = explainer,
                       n_features = 8,
                       n_permutations = 10)
plot.f<- plot_features(explanation)
plot.f

Kesimpulan

Berikut adalah faktor yang paling banyak dan paling sedikti berpengaruh