1 Introduction

Mendeteksi apakah suatu mesin akan mengalami kegagalan atau tidak dapat membantu perusahaan untuk mengurangi kemungkinan kerugian yang disebabkan oleh mesin rusak dan mengetahui mesin mana saja yang perlu dilakukan maintenance. Di sini terdapat Machine Failure dataset yang berisi tentang data sensor yang diperoleh dari kegagalan mesin yang terekam. Dari dataset tersebut akan dibuat model machine learning untuk memprediksi data sensor mesin masa depan apakah suatu mesin akan mengalami kegagalan atau tidak dengan menggunakan algoritma Naive Bayes, Decision Tree dan Random Forest yang kemudian nantinya akan dibandingkan model mana yang memprediksi lebih bagus.

2 Data Preparation

Kita akan memuat terlebih dahulu semua Library yang nantinya akan digunakan dalam melakukan analisis-analisis.

library(dplyr)
library(rsample)
library(e1071)
library(partykit)
library(ROCR)
library(inspectdf) 
library(gtools) 
library(caret) 
library(readxl)
library(class)

Kemudian memuat dataset Machine Failure.

machine <- read.csv("machine.csv")

rmarkdown::paged_table(machine)
machine$fail <- as.factor(machine$fail)
glimpse(machine)
#> Rows: 944
#> Columns: 10
#> $ footfall    <int> 0, 190, 31, 83, 640, 110, 100, 31, 180, 2800, 1600, 330, 1…
#> $ tempMode    <int> 7, 1, 7, 4, 7, 3, 7, 1, 7, 0, 0, 5, 2, 7, 7, 7, 7, 5, 7, 2…
#> $ AQ          <int> 7, 3, 2, 3, 5, 3, 5, 5, 4, 3, 3, 4, 5, 4, 5, 6, 4, 3, 6, 2…
#> $ USS         <int> 1, 3, 2, 4, 6, 4, 6, 4, 6, 3, 2, 3, 4, 4, 7, 7, 4, 3, 2, 1…
#> $ CS          <int> 6, 5, 6, 5, 4, 6, 4, 5, 3, 7, 4, 6, 6, 6, 4, 5, 5, 6, 6, 4…
#> $ VOC         <int> 6, 1, 1, 1, 0, 1, 1, 4, 3, 0, 4, 1, 5, 0, 0, 0, 1, 1, 5, 0…
#> $ RP          <int> 36, 20, 24, 28, 68, 21, 77, 21, 31, 39, 26, 31, 22, 42, 74…
#> $ IP          <int> 3, 4, 6, 6, 6, 4, 4, 4, 4, 3, 2, 4, 4, 5, 1, 3, 3, 6, 4, 3…
#> $ Temperature <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2…
#> $ fail        <fct> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0…

Dari hasil pembacaan dataset di atas, terdapat 944 data observasi dengan 10 kolom. Di sini kolom fail menjadi targetnya dan 9 kolom sisanya akan menjadi prediktor. Adapun untuk penjelasan masing-masing kolom adalah sebagai berikut.

  • footfall : Ini mengukur berapa banyak individu atau barang yang berada di dekat suatu mesin.
  • tempMode : Mode atau pengaturan suhu mesin.
  • AQ : Indeks kualitas udara di dekat mesin.
  • USS : Pengukuran data sensor ultrasonik.
  • CS : Pembacaan sensor arus, menunjukkan penggunaan arus listrik mesin.
  • VOC : Tingkat senyawa organik volatil terdeteksi di dekat mesin.
  • RP : Posisi rotasi atau RPM (putaran per menit) dari bagian-bagian mesin.
  • IP : Tekanan masukan ke mesin.
  • Temperature : Suhu pengoperasian mesin.
  • fail : Indikator kegagalan mesin (1 untuk kegagalan, 0 untuk tidak ada kegagalan).

Kemudian kita akan melakukan pengecekan apakah dataset tersebut terdapat Missing Value.

machine %>% is.na() %>% colSums()
#>    footfall    tempMode          AQ         USS          CS         VOC 
#>           0           0           0           0           0           0 
#>          RP          IP Temperature        fail 
#>           0           0           0           0

3 Cross Validation

Sebelum membuat model, di sini kita perlu memecah data menjadi 2 bagian yaitu train_machine untuk melakukan pelatihan model yang akan dibuat dan test_machine untuk menguji model yang telah dibuat.

RNGkind(sample.kind = "Rounding")
set.seed(123)
splitter <- initial_split(data = machine, prop = 0.8)
train_machine <- training(splitter)
test_machine <- testing(splitter)

3.1 Cek Imbalance Class

Proporsi yang seimbang penting agar model klasifikasi mempelajari karakteristik setiap kelas secara seimbang, tidak dominan hanya satu kelas saja. Hal ini mencegah model bias terhadap kelas yang lebih besar proporsinya sehingga hanya baik untuk memprediksi 1 kelas saja. Maka dari itu, perlu dicek imbalance class dari dataset train_machine.

table(train_machine$fail) %>% prop.table()
#> 
#>         0         1 
#> 0.5960265 0.4039735

Dari hasil pengecekan di atas dapat diketahui bahwa train_machine memiliki proporsi class pada kolom fail yaitu sebesar 60:40 yang mana proporsi tersebut masih dikatakan cukup seimbang sehingga bisa digunakan sebagai data train.

4 Modelling

Pembuatan model dari ketiga algoritma akan menggunakan seluruh kolom/variabel (selain kolom target) menjadi prediktor.

4.1 Naive Bayes

4.1.1 Model Naive Bayes

Pada konsep Algoritma Naive Bayes memanfaatkan Teorema Bayes yaitu sebuah rumus matematis yang digunakan untuk menentukan probabilitas bersyarat dari suatu peristiwa berdasarkan pengetahuan sebelumnya dan bukti baru.

Teorema Bayes dapat dinyatakan dengan rumus sebagai berikut:

\[[ P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)} ]\]

Di mana:

  • ( P(A|B) ) adalah probabilitas terjadinya peristiwa ( A ) dengan syarat bahwa peristiwa ( B ) telah terjadi (probabilitas bersyarat).
  • ( P(B|A) ) adalah probabilitas terjadinya peristiwa ( B ) dengan syarat bahwa peristiwa ( A ) telah terjadi.
  • ( P(A) ) adalah probabilitas terjadinya peristiwa ( A ) (probabilitas awal).
  • ( P(B) ) adalah probabilitas terjadinya peristiwa ( B ).

Kemudian kita akan membuat Model Machine Learning dengan Naive Bayes.

model_nb <- naiveBayes(formula = fail ~ .,
                       data = train_machine,
                       laplace = 1)
model_nb
#> 
#> Naive Bayes Classifier for Discrete Predictors
#> 
#> Call:
#> naiveBayes.default(x = X, y = Y, laplace = laplace)
#> 
#> A-priori probabilities:
#> Y
#>         0         1 
#> 0.5960265 0.4039735 
#> 
#> Conditional probabilities:
#>    footfall
#> Y       [,1]      [,2]
#>   0 412.0533 1263.9376
#>   1 214.5049  899.3785
#> 
#>    tempMode
#> Y       [,1]     [,2]
#>   0 3.791111 2.677284
#>   1 3.701639 2.733713
#> 
#>    AQ
#> Y       [,1]     [,2]
#>   0 3.642222 1.230096
#>   1 5.340984 1.004165
#> 
#>    USS
#> Y       [,1]      [,2]
#>   0 3.522222 1.3680068
#>   1 2.121311 0.9842702
#> 
#>    CS
#> Y       [,1]      [,2]
#>   0 5.335556 1.4955994
#>   1 5.442623 0.8981815
#> 
#>    VOC
#> Y       [,1]     [,2]
#>   0 1.335556 1.486638
#>   1 5.009836 1.255213
#> 
#>    RP
#> Y       [,1]     [,2]
#>   0 46.78222 16.59653
#>   1 47.65902 16.14251
#> 
#>    IP
#> Y       [,1]     [,2]
#>   0 4.377778 1.638742
#>   1 4.718033 1.562040
#> 
#>    Temperature
#> Y       [,1]     [,2]
#>   0 15.26889 6.386313
#>   1 17.95082 5.011914

Dari hasil pemodelan di atas, kita akan mendapatkan 2 elemen yaitu:

  • A-Priori Probabilities : Elemen tersebut menunjukkan peluang kelas tanpa adanya variabel/prediktor. Jadi murni hanya menghitung probabilitas dari masing-masing kelas target tanpa memperhitungkan variabel-variabel yang ada.
  • Conditional Probabilities : Elemen ini menunjukkan peluang prediktor jika diketahui variabel targetnya. Conditional Probabilities yang dihasilkan di sini tidak berupa probabilitas dikarenakan data pada variabel yang ada merupakan variabel kontinu (bukan kategorikal), sehingga yang dihitung pada model tersebut adalah rata-rata dan varians dari fitur/variabel tersebut untuk setiap kelas target.

4.1.2 Prediction Naive Bayes

Kemudian kita akan melakukan prediksi menggunakan model Naive Bayes di atas terhadap data test kita dan kemudian membandingkan hasil prediksi dengan data aktualnya.

pred_nb <- predict(object = model_nb,
                   newdata = test_machine,
                   type = "class")

4.1.3 Model Evaluation

Untuk mengevaluasi model, kita akan menggunakan Confusion Matrix.

conf_nb <- confusionMatrix(data = pred_nb,
                           reference = test_machine$fail,
                           positive="1")

conf_nb
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 93 13
#>          1  8 75
#>                                              
#>                Accuracy : 0.8889             
#>                  95% CI : (0.8352, 0.9299)   
#>     No Information Rate : 0.5344             
#>     P-Value [Acc > NIR] : <0.0000000000000002
#>                                              
#>                   Kappa : 0.7759             
#>                                              
#>  Mcnemar's Test P-Value : 0.3827             
#>                                              
#>             Sensitivity : 0.8523             
#>             Specificity : 0.9208             
#>          Pos Pred Value : 0.9036             
#>          Neg Pred Value : 0.8774             
#>              Prevalence : 0.4656             
#>          Detection Rate : 0.3968             
#>    Detection Prevalence : 0.4392             
#>       Balanced Accuracy : 0.8865             
#>                                              
#>        'Positive' Class : 1                  
#> 

4.2 Decision Tree

4.2.1 Model Decision Tree

Decision tree merupakan tree-based model yang cukup sederhana dengan performa yang robust/powerful untuk membuat prediksi. Seperti namanya, decision tree menghasilkan struktur pohon yang tersusun dari pertanyaan-pertanyaan yang berkaitan dengan variabel prediktor. Pertanyaan-pertanyaan ini akan menjadi guidance dalam menentukan hasil prediksi.

model_dt <- ctree(formula = fail ~ .,
                  data = train_machine)
plot(model_dt, type = "simple")

4.2.2 Prediction Decision Tree

Kemudian kita akan melakukan prediksi menggunakan model Decision Tree di atas terhadap data test kita dan kemudian membandingkan hasil prediksi dengan data aktualnya.

pred_dt <- predict(object = model_dt,
                   newdata = test_machine,
                   type = "response")

4.2.3 Model Evaluation

Untuk mengevaluasi model, kita akan menggunakan Confusion Matrix.

conf_dt <- confusionMatrix(data = pred_dt,
                           reference = test_machine$fail,
                           positive="1")

conf_dt
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 99 20
#>          1  2 68
#>                                                
#>                Accuracy : 0.8836               
#>                  95% CI : (0.8291, 0.9256)     
#>     No Information Rate : 0.5344               
#>     P-Value [Acc > NIR] : < 0.00000000000000022
#>                                                
#>                   Kappa : 0.763                
#>                                                
#>  Mcnemar's Test P-Value : 0.0002896            
#>                                                
#>             Sensitivity : 0.7727               
#>             Specificity : 0.9802               
#>          Pos Pred Value : 0.9714               
#>          Neg Pred Value : 0.8319               
#>              Prevalence : 0.4656               
#>          Detection Rate : 0.3598               
#>    Detection Prevalence : 0.3704               
#>       Balanced Accuracy : 0.8765               
#>                                                
#>        'Positive' Class : 1                    
#> 

4.3 Random Forest

4.3.1 Model Random Forest

Random forest terbentuk dari sekumpulan decision tree. Masing-masing decision tree memiliki karakteristik yang berbeda dan tidak saling berhubungan.

Random Forest termasuk ke dalam Ensamble Method yang merupakan pendekatan machine learning untuk melakukan prediksi dengan mengombinasikan prediksi dari beberapa model menjadi sebuah prediksi. Dengan kombinasi dari beberapa prediktor tersebut, ensemble method dapat meningkatkan performa prediksi model.

train_ctrl <- trainControl(method = "repeatedcv",
                           number = 10,
                           repeats = 5)

model_rf <- train(fail ~ .,
                  data = train_machine,
                  method = "rf",
                  trControl = train_ctrl
                  )

4.3.2 Prediction Random Forest

pred_rf <- predict(object = model_rf,
                   newdata = test_machine,
                   type = "raw")

4.3.3 Model Evaluation

4.3.3.1 Confusion Matrix

Untuk mengevaluasi model, kita akan menggunakan Confusion Matrix.

conf_dt <- confusionMatrix(data = pred_rf,
                           reference = test_machine$fail,
                           positive="1")

conf_dt
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 96 10
#>          1  5 78
#>                                              
#>                Accuracy : 0.9206             
#>                  95% CI : (0.8725, 0.9549)   
#>     No Information Rate : 0.5344             
#>     P-Value [Acc > NIR] : <0.0000000000000002
#>                                              
#>                   Kappa : 0.8399             
#>                                              
#>  Mcnemar's Test P-Value : 0.3017             
#>                                              
#>             Sensitivity : 0.8864             
#>             Specificity : 0.9505             
#>          Pos Pred Value : 0.9398             
#>          Neg Pred Value : 0.9057             
#>              Prevalence : 0.4656             
#>          Detection Rate : 0.4127             
#>    Detection Prevalence : 0.4392             
#>       Balanced Accuracy : 0.9184             
#>                                              
#>        'Positive' Class : 1                  
#> 

Pada Random Forest terdapat beberapa Special Evaluation yaitu antara lain.

4.3.3.2 Out-Of-Bag (OOB)

Pada tahap bootstrap sampling, terdapat data yang tidak digunakan dalam pembuatan model. Data ini yang disebut sebagai data out-of-bag (OOB).

Model random forest akan menggunakan data OOB sebagai data untuk melakukan evaluasi dengan cara menghitung error (serupa dengan data testing). Error inilah yang disebut OOB Error. Dalam kasus klasifikasi, OOB error merupakan persentase data OOB yang misklasifikasi. Intrepertasi terhadap nilai OOB error adalah semakin kecil semakin bagus model. Biasanya model yang bagus memiliki OOB Error < 10%.

model_rf$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: 10.2%
#> Confusion matrix:
#>     0   1 class.error
#> 0 413  37  0.08222222
#> 1  40 265  0.13114754

4.3.3.3 ROC-AUC

Sebelumnya, kita sudah mengetahui bahwa accuracy tidak representatif apabila digunakan untuk kasus kelas target yang imbalance. Sebagai alternatif, kita dapat menggunakan precision atau recall. Akan tetapi, kedua metrics ini sangat berpengaruh pada nilai threshold.

Untuk mengetahui apakah model kita baik di semua threshold, kita dapat membuat plot ROC (Receiver Operating Characteristic).

ROC merupakan plot antara TPR (True Positive Rate) dan FPR (False Positive Rate) pada setiap threshold. TPR pada sumbu y dan FPR pada sumbu x.

# prediksi: ambil nilai peluang
pred_rf_prob <- predict(object = model_rf,
                        newdata = test_machine,
                        type = "prob")

# ambil peluang kelas positif: 1
pred_prob <- pred_rf_prob[, "1"]

# membuat prediction object agar dapt menghitung nilai TPR, FPR,
rf_roc <- prediction(predictions = pred_prob,
                    labels = test_machine$fail,
                    label.ordering = c("0", "1"))

# membuat plot ROC
viz_roc <- performance(
  rf_roc,
  "tpr",
  "fpr"
)

plot(viz_roc)

Interpretasi terhadap Plot ROC : Plot ROC yang ideal adalah TPR mendekati 1. Karena ROC adalah berbentuk visual, untuk mengetahui apakah model kita sudah baik di semua threshold, kita memerlukan AUC (Area Under Curve).

rf_auc <- performance(rf_roc, "auc")
rf_auc@y.values
#> [[1]]
#> [1] 0.9738411

5 Conclusion

Untuk mengambil kesimpulan, kita bisa bandingkan confusion matrix dari masing-masing model.

5.1 Confusion Matrix Naive Bayes

conf_nb <- confusionMatrix(data = pred_nb,
                           reference = test_machine$fail,
                           positive="1")

conf_nb
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 93 13
#>          1  8 75
#>                                              
#>                Accuracy : 0.8889             
#>                  95% CI : (0.8352, 0.9299)   
#>     No Information Rate : 0.5344             
#>     P-Value [Acc > NIR] : <0.0000000000000002
#>                                              
#>                   Kappa : 0.7759             
#>                                              
#>  Mcnemar's Test P-Value : 0.3827             
#>                                              
#>             Sensitivity : 0.8523             
#>             Specificity : 0.9208             
#>          Pos Pred Value : 0.9036             
#>          Neg Pred Value : 0.8774             
#>              Prevalence : 0.4656             
#>          Detection Rate : 0.3968             
#>    Detection Prevalence : 0.4392             
#>       Balanced Accuracy : 0.8865             
#>                                              
#>        'Positive' Class : 1                  
#> 

5.2 Confusion Matrix Decision Tree

conf_dt <- confusionMatrix(data = pred_dt,
                           reference = test_machine$fail,
                           positive="1")

conf_dt
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 99 20
#>          1  2 68
#>                                                
#>                Accuracy : 0.8836               
#>                  95% CI : (0.8291, 0.9256)     
#>     No Information Rate : 0.5344               
#>     P-Value [Acc > NIR] : < 0.00000000000000022
#>                                                
#>                   Kappa : 0.763                
#>                                                
#>  Mcnemar's Test P-Value : 0.0002896            
#>                                                
#>             Sensitivity : 0.7727               
#>             Specificity : 0.9802               
#>          Pos Pred Value : 0.9714               
#>          Neg Pred Value : 0.8319               
#>              Prevalence : 0.4656               
#>          Detection Rate : 0.3598               
#>    Detection Prevalence : 0.3704               
#>       Balanced Accuracy : 0.8765               
#>                                                
#>        'Positive' Class : 1                    
#> 

5.3 Confusion Matrix Random Forest

conf_rf <- confusionMatrix(data = pred_rf,
                           reference = test_machine$fail,
                           positive="1")

conf_rf
#> Confusion Matrix and Statistics
#> 
#>           Reference
#> Prediction  0  1
#>          0 96 10
#>          1  5 78
#>                                              
#>                Accuracy : 0.9206             
#>                  95% CI : (0.8725, 0.9549)   
#>     No Information Rate : 0.5344             
#>     P-Value [Acc > NIR] : <0.0000000000000002
#>                                              
#>                   Kappa : 0.8399             
#>                                              
#>  Mcnemar's Test P-Value : 0.3017             
#>                                              
#>             Sensitivity : 0.8864             
#>             Specificity : 0.9505             
#>          Pos Pred Value : 0.9398             
#>          Neg Pred Value : 0.9057             
#>              Prevalence : 0.4656             
#>          Detection Rate : 0.4127             
#>    Detection Prevalence : 0.4392             
#>       Balanced Accuracy : 0.9184             
#>                                              
#>        'Positive' Class : 1                  
#> 

Kembali lagi ke tujuan utama masalah bisnis yang ingin diselesaikan yaitu membuat sistem Early Warning untuk mendeteksi mesin mana yang memiliki kemungkinan akan gagal atau rusak, sehingga perusahaan bisa melakukan maintenance untuk mencegah kerusakan tersebut.

Dari perumusan masalah di atas, maka dapat disimpulkan bahwa kita lebih memperhatikan sekecil mungkin jumlah mesin yang diprediksi tidak gagal/rusak namun sebenarnya gagal/rusak (FN), daripada jumlah mesin yang diprediksi gagal/rusak, namun sebenarnya tidak rusak (FP).

Maka, metirks performa model yang digunakan adalah Sensitivity/Recall dengan logika semakin tinggi nilai Sensitivity maka semakin kecil jumlah FN sehingga mengurangi kemungkinan mesin yang akan rusak tapi tidak dilakukan maintenance. Dan model yang memberikan nilai Sensitivity/Recall paling tinggi adalah pada Model Random Forest. Pada Model Random Forest masih bisa dimaksimalkan hasil modelnya dengan mencari cut-off angka dalam K-Fold Cross Validation.