Klasifikasi Alarm Kebakaran
Pendahuluan
Kita selaku tim data dari perusahaan pembuat alat pendeteksi asap (Smoke Detection) perlu membuat sistem/model yang dapat mengklasifikasikan apakah terdapat api atau tidak dengan efisien dan efektif.
Kita menyadari sering kali fenomena yang terjadi dilapangan (realitas) sulit ditemuakan polanya, bagaimana membedakan apakah terdapat api atau tidak, terutama ketika informasi yang menjadi pertimbangan (prediktor) sangat banyak. Oleh karena itu, projek Machine Learning ini dibuat untuk mencoba menyelesaikan kesulitan tersebut dengan efektif (karena memiliki ukuran kualitas yang jelas) dan efisien (karena dengan bantuan komputasi bukan manual). Projek ini menggunakan dataset dari Kaggle.
Persiapan dan Wrangling Data
Pustaka
library(dplyr)
library(rsample)
library(ggplot2)
library(plotly)
library(caret)
library(e1071)
library(partykit)
Membaca Dataset
<- read.csv("smoke_detection_iot.csv")
smoke smoke
Deskripsi kolom :
Prediktor : Kolom yang menjadi pertimbangan dalam menentukan Target (input).
X
: Index yang menjadi identitas setiap baris.UTC
: Waktu UTC Timestamp dalam detik (data konversi dari waktu biasa menjadi UTC timestamp).Temperature_C
: Tingkat Suhu dalam satuan celcius.Humidity_percent
: Tingkat Kelembaban dalam persen.TVOC_ppb
: Total Senyawa Organik Volatil; diukur dalam bagian per miliar dalam ppb.eCO2_ppm
: Besaran Konsentrasi setara co2; dihitung dari nilai yang berbeda seperti TVCO dalam ppm.Raw_H2
: Besaran Hidrogen molekuler mentah; tidak dikompensasi (Bias, suhu, dll.).Raw_Ethanol
: Besaran gas etanol mentah.Pressure_hPa
: Besaran tekanan udara dalam hPa.PM1.0
: Besaran partikel dengan diameter hingga 1 mikron.PM2.5
: Besaran partikel dengan diameter hingga 2.5 mikron.NC0.5
: Number Concentration, Ini berbeda dari PM karena NC memberikan jumlah sebenarnya dari partikel (ukuran <= 0.5 µm) di udara.NC1.0
: Number Concentration, Ini berbeda dari PM karena NC memberikan jumlah sebenarnya dari partikel (ukuran 0.5 µm <= 1 µm) di udara.NC2.5
: Number Concentration, Ini berbeda dari PM karena NC memberikan jumlah sebenarnya dari partikel (ukuran 1 µm < 2.5µm) di udara.CNT
: Penghitung sampel.
Target : Kolom yang menjadi hasil dari pertimbangan prediktor (output).
Fire_Alarm
: Menunjukan apakah ada api atau tidak; 1 = terdapat api, 0 = tidak/
Mengecek Nilai Hilang
anyNA(smoke)
#> [1] FALSE
Tidak terdapat nilai hilang sehingga dapat lanjut ke tahap selanjutnya.
Mengecek Duplikasi Data
anyDuplicated(smoke)
#> [1] 0
Tidak terdapat data yang terduplikasi sehingga dapat lanjut ke tahap selanjutnya.
Menyesuaikan Data
Struktur data sebelum Wrangling Data
glimpse(smoke)
#> Rows: 62,630
#> Columns: 16
#> $ X <int> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,…
#> $ UTC <int> 1654733331, 1654733332, 1654733333, 1654733334, 16547…
#> $ Temperature_C <dbl> 20.000, 20.015, 20.029, 20.044, 20.059, 20.073, 20.08…
#> $ Humidity_percent <dbl> 57.36, 56.67, 55.96, 55.28, 54.69, 54.12, 53.61, 53.2…
#> $ TVOC_ppb <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
#> $ eCO2_ppm <int> 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400…
#> $ Raw_H2 <int> 12306, 12345, 12374, 12390, 12403, 12419, 12432, 1243…
#> $ Raw_Ethanol <int> 18520, 18651, 18764, 18849, 18921, 18998, 19058, 1911…
#> $ Pressure_hPa <dbl> 939.735, 939.744, 939.738, 939.736, 939.744, 939.725,…
#> $ PM1.0 <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,…
#> $ PM2.5 <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,…
#> $ NC0.5 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
#> $ NC1.0 <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.00…
#> $ NC2.5 <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.00…
#> $ CNT <int> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,…
#> $ Fire_Alarm <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
Proses Wrangling Data
# Menjadikan kolom X menjadi nama kolom
rownames(smoke) <- smoke$X
<- smoke %>%
smoke_clean # Membuang kolom X karena sudah menjadi nama kolom
select(-X) %>%
# Mengubah tipe data target Target menjadi factor
mutate(Fire_Alarm = as.factor(Fire_Alarm))
Struktur data sesudah Wrangling Data
glimpse(smoke_clean)
#> Rows: 62,630
#> Columns: 15
#> $ UTC <int> 1654733331, 1654733332, 1654733333, 1654733334, 16547…
#> $ Temperature_C <dbl> 20.000, 20.015, 20.029, 20.044, 20.059, 20.073, 20.08…
#> $ Humidity_percent <dbl> 57.36, 56.67, 55.96, 55.28, 54.69, 54.12, 53.61, 53.2…
#> $ TVOC_ppb <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
#> $ eCO2_ppm <int> 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400…
#> $ Raw_H2 <int> 12306, 12345, 12374, 12390, 12403, 12419, 12432, 1243…
#> $ Raw_Ethanol <int> 18520, 18651, 18764, 18849, 18921, 18998, 19058, 1911…
#> $ Pressure_hPa <dbl> 939.735, 939.744, 939.738, 939.736, 939.744, 939.725,…
#> $ PM1.0 <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,…
#> $ PM2.5 <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00,…
#> $ NC0.5 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
#> $ NC1.0 <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.00…
#> $ NC2.5 <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.00…
#> $ CNT <int> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,…
#> $ Fire_Alarm <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
Eksplorasi Data Analisis
Ringkasan Data
summary(smoke_clean)
#> UTC Temperature_C Humidity_percent TVOC_ppb
#> Min. :1654712187 Min. :-22.01 Min. :10.74 Min. : 0
#> 1st Qu.:1654743244 1st Qu.: 10.99 1st Qu.:47.53 1st Qu.: 130
#> Median :1654761920 Median : 20.13 Median :50.15 Median : 981
#> Mean :1654792066 Mean : 15.97 Mean :48.54 Mean : 1942
#> 3rd Qu.:1654777577 3rd Qu.: 25.41 3rd Qu.:53.24 3rd Qu.: 1189
#> Max. :1655130051 Max. : 59.93 Max. :75.20 Max. :60000
#> eCO2_ppm Raw_H2 Raw_Ethanol Pressure_hPa
#> Min. : 400 Min. :10668 Min. :15317 Min. :930.9
#> 1st Qu.: 400 1st Qu.:12830 1st Qu.:19435 1st Qu.:938.7
#> Median : 400 Median :12924 Median :19501 Median :938.8
#> Mean : 670 Mean :12942 Mean :19754 Mean :938.6
#> 3rd Qu.: 438 3rd Qu.:13109 3rd Qu.:20078 3rd Qu.:939.4
#> Max. :60000 Max. :13803 Max. :21410 Max. :939.9
#> PM1.0 PM2.5 NC0.5 NC1.0
#> Min. : 0.00 Min. : 0.00 Min. : 0.00 Min. : 0.00
#> 1st Qu.: 1.28 1st Qu.: 1.34 1st Qu.: 8.82 1st Qu.: 1.38
#> Median : 1.81 Median : 1.88 Median : 12.45 Median : 1.94
#> Mean : 100.59 Mean : 184.47 Mean : 491.46 Mean : 203.59
#> 3rd Qu.: 2.09 3rd Qu.: 2.18 3rd Qu.: 14.42 3rd Qu.: 2.25
#> Max. :14333.69 Max. :45432.26 Max. :61482.03 Max. :51914.68
#> NC2.5 CNT Fire_Alarm
#> Min. : 0.000 Min. : 0 0:17873
#> 1st Qu.: 0.033 1st Qu.: 3625 1:44757
#> Median : 0.044 Median : 9336
#> Mean : 80.049 Mean :10511
#> 3rd Qu.: 0.051 3rd Qu.:17165
#> Max. :30026.438 Max. :24993
Eksplorasi Prediktor
- Nilai kolom
UTC
berada dikisaran 1,655,000,000 - Nilai kolom
Temparature_C
didominasi (75%-nya) dari rentang -22.01 C hingga 15.97 C dengan tertingggi di angka 59.93 C. - Nilai kolom
Humidity_percent
didominasi (75%-nya) dari rentang 10.74% hingga 53.24% dengan tertingggi di angka 75.20%. - Nilai kolom
TVOC_ppb
didominasi (75%-nya) dari rentang 0 ppb hingga 1,189 ppb dengan tertingggi di angka 60,000 ppb. - Nilai kolom
eCO2_ppm
didominasi (75%-nya) dari rentang 400 ppm hingga 438 ppm dengan tertingggi di angka 60,000 ppm. - Nilai kolom
Raw_H2
didominasi (75%-nya) dari rentang 10,668 hingga 13109 dengan tertingggi di angka 13,803. - Nilai kolom
Raw_Ethanol
didominasi (75%-nya) dari rentang 15,317 hingga 20078 dengan tertingggi di angka 21,410. - Nilai kolom
Pressure_hPa
didominasi (75%-nya) dari rentang 930.9 hingga 939.4 dengan tertingggi di angka 939.9. - Nilai kolom
PM1.0
didominasi (75%-nya) dari rentang 0.00 hingga 2.09 dengan tertingggi di angka 14,333.69 (Sangat tidak merata). - Nilai kolom
PM2.5
didominasi (75%-nya) dari rentang 0.00 hingga 2.18 dengan tertingggi di angka 45,432.26. - Nilai kolom
NC0.5
didominasi (75%-nya) dari rentang 0.00 hingga 14.42 dengan tertingggi di angka 61,482.03. - Nilai kolom
NC1.0
didominasi (75%-nya) dari rentang 0.00 hingga 2.25 dengan tertingggi di angka 51,914.68. - Nilai kolom
NC2.5
didominasi (75%-nya) dari rentang 0.000 hingga 0.051 dengan tertingggi di angka 30,026.438. - Nilai kolom
CNT
didominasi (75%-nya) dari rentang 0 hingga 17,165 dengan tertingggi di angka 24,993.
Eksplorasi Target
<- as.data.frame(table(smoke_clean$Fire_Alarm))
vis_data
<-
plt ggplot(data = vis_data, aes(x = Var1, y = Freq, fill = Var1,
text = glue::glue("Target : {Var1}.
Jumlah : {Freq}"))) +
geom_bar(stat = "identity") +
labs(title = "Perbandingan Target 0 (Tidak Terdapat Api) dan 1 (Terdapat Api)",
y = "Jumlah",
x = "Fire Alarm") +
theme_minimal()
ggplotly(plt, tooltip = "text" )
Pada data smoke ini di dominasi
Fire_Alarm
1 atau terdapat Api.
Pemodelan
Split Data Train-Test
prop.table(table(smoke_clean$Fire_Alarm))
#>
#> 0 1
#> 0.2853744 0.7146256
Kita menyadari proporsi Target 0 dan 1 pada data kita cenderung tidak seimbang karena Target 0 hanya 28.53% sedangkan Target 1 sebesar 71.46%.
RNGkind(sample.kind = "Rounding")
set.seed(100)
<- initial_split(data = smoke_clean, #data asli sebelum splitting
index prop = 0.74,
strata = Fire_Alarm)
<- training(index)
train <- testing(index)
test
<- upSample(x = train %>% select(-Fire_Alarm),
train y = train$Fire_Alarm,
yname = "Fire_Alarm")
Oleh karena itu, kita mencoba membagi data train dan test dengan proporsi 74% untuk data train dan 26% untuk data test. Kenapa tidak 80% dan 20%? Agar setelah dilakukan UpSample (Menambah data dengan menduplikasi agar antara jenis target seimbang) pada data train perbandingan data train dan test cenderung sekitar 80% dan 20%.
Kita menyeimbangkan proporsi Target 0 dan 1 hanya pada data train saja karena fokus pada pelatihan model adalah menemukan pola data dalam membedakan Target 0 dengan 1. Sehingga diperlukan bahan belajar (data train) yang seimbang.
- Proporsi Jenis Target Pada Data Train :
prop.table(table(train$Fire_Alarm))
#>
#> 0 1
#> 0.5 0.5
Kita tidak menyeimbangkan proporsi Target 0 dan 1 pada data test karena fokus pada pengetesan model adalah menguji apakah model kita sudah dapat menemukan pola yang membedakan Target 0 dengan 1. Sehingga tidak diperlukan soal ujian (data test) yang seimbang.
- Proporsi Jenis Target Pada Data Test :
Kita menyamakan proporsi Target 0 dan 1 pada data test seperti pada data aslinya (smoke_clean
). Karena kita mengharapkan model dapat melakukan prediksi yang sesuai dengan keadaan realitas. Alias pada pelatihan model telah berhasil menemukakn pola pembeda Target 0 dan 1.
prop.table(table(smoke_clean$Fire_Alarm))
#>
#> 0 1
#> 0.2853744 0.7146256
prop.table(table(test$Fire_Alarm))
#>
#> 0 1
#> 0.2853721 0.7146279
Berikut jumlah dan proporasi data train dan test setelah dilakukan UpSample
.
<- nrow(train)/(nrow(train) + nrow(test))*100
prop_train <- nrow(test)/(nrow(train) + nrow(test))*100
prop_test
data.frame(Data = c("Train", "Test", "Total"),
Jumlah = c(nrow(train), nrow(test), nrow(train)+nrow(test)),
Proporsi_persen = c(prop_train, prop_test, prop_train + prop_test)
)
Naive Bayes
1. Melakukan Scaling
<- train %>%
train_scale mutate(UTC = scale(UTC),
Temperature_C = scale(Temperature_C),
Humidity_percent = scale(Humidity_percent),
TVOC_ppb = scale(TVOC_ppb),
eCO2_ppm = scale(eCO2_ppm),
Raw_H2 = scale(Raw_H2),
Raw_Ethanol = scale(Raw_Ethanol),
Pressure_hPa = scale(Pressure_hPa),
PM1.0 = scale(PM1.0),
PM2.5 = scale(PM2.5),
NC0.5 = scale(NC0.5),
NC1.0 = scale(NC1.0),
NC2.5 = scale(NC2.5),
CNT = scale(CNT)
)
<- test %>%
test_scale mutate(UTC = scale(UTC),
Temperature_C = scale(Temperature_C),
Humidity_percent = scale(Humidity_percent),
TVOC_ppb = scale(TVOC_ppb),
eCO2_ppm = scale(eCO2_ppm),
Raw_H2 = scale(Raw_H2),
Raw_Ethanol = scale(Raw_Ethanol),
Pressure_hPa = scale(Pressure_hPa),
PM1.0 = scale(PM1.0),
PM2.5 = scale(PM2.5),
NC0.5 = scale(NC0.5),
NC1.0 = scale(NC1.0),
NC2.5 = scale(NC2.5),
CNT = scale(CNT)
)
Kita membuat data yang memiliki skala yang sama karena terbukti meningkatkan performa model Naive Bayes.
2. Membangun Model
<- naiveBayes(Fire_Alarm~., train_scale) model_nb
Kita menjadikan kolom
Fire_Alarm
sebagai target dan kolom sisanya sebagai predikor.
3. Prediksi Data Test
<- predict(object = model_nb, newdata = test_scale, type = "class") pred_nb
Membandingkan bagaimana hasil prediksi dan nilai sebenarnya.
data.frame(prediksi = pred_nb,
aktual = test$Fire_Alarm)
4. Evaluasi Model
confusionMatrix(data = pred_nb, reference = test_scale$Fire_Alarm, positive = "1")
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 3064 290
#> 1 1583 11347
#>
#> Accuracy : 0.885
#> 95% CI : (0.88, 0.8898)
#> No Information Rate : 0.7146
#> P-Value [Acc > NIR] : < 0.00000000000000022
#>
#> Kappa : 0.6923
#>
#> Mcnemar's Test P-Value : < 0.00000000000000022
#>
#> Sensitivity : 0.9751
#> Specificity : 0.6594
#> Pos Pred Value : 0.8776
#> Neg Pred Value : 0.9135
#> Prevalence : 0.7146
#> Detection Rate : 0.6968
#> Detection Prevalence : 0.7940
#> Balanced Accuracy : 0.8172
#>
#> 'Positive' Class : 1
#>
Pada umumnya kita mengevaluasi model menggunakan 5 ukuran:
- Re-call/Sensitivity = dari semua data aktual yang
1
(terdapat api), seberapa mampu proporsi model memprediksi benar. - Specificity = dari semua data aktual yang
0
(tidak terdapat api), seberapa mampu proporsi model memprediksi yang benar. - Accuracy = seberapa mampu model memprediksi dengan benar target Target secara keseluruhan.
- Precision (Pos Pred Value) = dari semua hasil prediksi Target
1
(terdapat api), seberapa mampu model saya dapat memprediksi benar. - Negative Predict Value (Neg Pred Value) : dari semua hasil prediksi Target
0
(tidak terdapat api), seberapa mampu model saya dapat memprediksi benar.
Sebaiknya pada kasus ini, kita memperhatikan metrik selain Accuracy karena data test asli memiliki ketidakseimbangan Target.
- Sensitivity : 0.9751
- Specificity : 0.6594
- Accuracy : 0.885
- Pos Pred Value (Precision) : 0.8776
- Neg Pred Value : 0.9135
Model kita sudah menghasilkan performa yang cukup baik pada beberapa ukuran, tetapi pada ukuran Specificity masih kurang baik. Hal ini berarti performa model kita dalam memprediksi Target 0 (Tidak terdapat api) masih kurang baik jika dibandingkan dengan total data sebenarnya Target 0. Dari 4,647 data Target 0, model melakukan kesalahan sebanyak 1,583 kali.
Decision Tree
Kita ingin mencoba algoritma Decision Tree dalam mengklasifikasikan dataset yang sama. Harapannya dapat menghasilkan model yang baik.
1. Membangun Model
<- ctree(formula = Fire_Alarm~., data = train) subs_tree
Kita menjadikan kolom
Fire_Alarm
sebagai target dan kolom sisanya sebagai predikor. Kita tidak menggunakan data train yang telah di skalakan karena secara performa lebih baik tidak di skalakan.
2. Interpretasi Model
subs_tree
#>
#> Model formula:
#> Fire_Alarm ~ UTC + Temperature_C + Humidity_percent + TVOC_ppb +
#> eCO2_ppm + Raw_H2 + Raw_Ethanol + Pressure_hPa + PM1.0 +
#> PM2.5 + NC0.5 + NC1.0 + NC2.5 + CNT
#>
#> Fitted party:
#> [1] root
#> | [2] CNT <= 5743
#> | | [3] CNT <= 3177
#> | | | [4] Pressure_hPa <= 931.269
#> | | | | [5] Temperature_C <= 20.67: 0 (n = 34, err = 0.0%)
#> | | | | [6] Temperature_C > 20.67
#> | | | | | [7] Pressure_hPa <= 931.179: 1 (n = 764, err = 0.0%)
#> | | | | | [8] Pressure_hPa > 931.179
#> | | | | | | [9] PM1.0 <= 140.84: 0 (n = 22, err = 0.0%)
#> | | | | | | [10] PM1.0 > 140.84: 1 (n = 77, err = 0.0%)
#> | | | [11] Pressure_hPa > 931.269
#> | | | | [12] eCO2_ppm <= 453: 0 (n = 23195, err = 0.0%)
#> | | | | [13] eCO2_ppm > 453: 0 (n = 444, err = 0.5%)
#> | | [14] CNT > 3177
#> | | | [15] Pressure_hPa <= 937.501: 0 (n = 9427, err = 0.0%)
#> | | | [16] Pressure_hPa > 937.501: 1 (n = 3820, err = 0.0%)
#> | [17] CNT > 5743: 1 (n = 28457, err = 0.0%)
#>
#> Number of inner nodes: 8
#> Number of terminal nodes: 9
# visualisasi decision tree
plot(subs_tree, type="simple")
A. Deskripsi :
- Yang berbentuk Oval no 1 merupakan Root Node : Percabangan pertama dalam menentukan nilai target yaitu
CNT
. - Yang berbentuk Oval no 2, 3, 4, 6, 8, 11 dan 14 merupakan Interior Node : Percabangan selanjutnya yang menggunakan prediktor lain apabila Root Node tidak cukup menentukan target.
- Yang berbentuk persegi panjang no 5, 7, 9, 10, 12, 13, 15, 16, 17 merupakan Terminal/Leaf Node : Keputusan akhir berupa nilai target yang diprediksi.
B. Model Decision Tree kita berhasil mengklasifikasikan data hampir mendekati sempurna karena error yang dihasilkan kebanyakan 0% dan hanya satu yang 0.5% (pada node no 13).
C. Kemudian terdapat pula beberapa prediktor yang tidak digunakan contohnya PM0.5
,PM2.5
dll berarti memang model sudah cukup menggunakan sebagian prediktor saja dalam mengklasifikasikan data kita.
D. Model kita menghasilkan aturan dalam memprediksi sebagai berikut.
Melihat nilai data CNT apakah > 5743, jika ya maka langsung diklasifikasikan 1 alias terdapat api dan tingkat kesalahan (error) adalah 0%.
Apabila
CNT
<= 5743, maka akan dicek kembali apakah :CNT
> 3177, jika ya maka dilanjutkan dengan melihat nilaiPressure_hPa
, jika > 937.501 maka diklasifikasikan terdapat api (error = 0%), jika <= 937.501 maka diklasifikasikan tidak terdapat api (error = 0%)- Atau CNT <= 3177, maka dilanjutkan dengan melihat
Pressure_hPa
, jika > 931.269 maka dilanjutkan mengecekeCO2_ppm
, jika <= 453 maka diklasifikasikan tidak terdapat api (error = 0%), jika > 453 maka diklasifikasikan terdapat api (error = 0.5%)
Ketika node no 3, nilai
Pressure_hPac
<= 931.269 maka akan dilanjutkan mengecekTemperature_C
. Jika suhu <= 20.67 maka langsung diklasifikasikan tidak terdapat api (error = 0%). Jika suhu > 20.67 maka dilanjutkan mengecekPressure_hPa
. KetikaPressure_hPa
<= 931.179 maka langsung diklasifikasikan terdapat api (error = 0%).Tetapi ketika
Pressure_hPa
> 931.179 maka dilanjutkan mengecekPM1.0
. KetikaPM1.0
<= 140.84 maka diklasifikasikan tidak terdapat api (error = 0%) dan ketikaPM1.0
> 140.84 maka diklasifikasikan terdapat api (error = 0%).
3. Prediksi Data Test
<- predict(object = subs_tree, newdata = test, type = "response") pred_dt
Membandingkan bagaimana hasil prediksi dan nilai sebenarnya.
data.frame(prediksi = pred_dt,
aktual = test$Fire_Alarm)
4. Evaluasi Model
confusionMatrix(data = pred_dt, reference = test$Fire_Alarm, positive = "1")
#> Confusion Matrix and Statistics
#>
#> Reference
#> Prediction 0 1
#> 0 4645 2
#> 1 2 11635
#>
#> Accuracy : 0.9998
#> 95% CI : (0.9994, 0.9999)
#> No Information Rate : 0.7146
#> P-Value [Acc > NIR] : <0.0000000000000002
#>
#> Kappa : 0.9994
#>
#> Mcnemar's Test P-Value : 1
#>
#> Sensitivity : 0.9998
#> Specificity : 0.9996
#> Pos Pred Value : 0.9998
#> Neg Pred Value : 0.9996
#> Prevalence : 0.7146
#> Detection Rate : 0.7145
#> Detection Prevalence : 0.7146
#> Balanced Accuracy : 0.9997
#>
#> 'Positive' Class : 1
#>
Pada umumnya kita mengevaluasi model menggunakan 5 ukuran:
- Re-call/Sensitivity = dari semua data aktual yang
1
(terdapat api), seberapa mampu proporsi model memprediksi benar. - Specificity = dari semua data aktual yang
0
(tidak terdapat api), seberapa mampu proporsi model memprediksi yang benar. - Accuracy = seberapa mampu model memprediksi dengan benar target Target secara keseluruhan.
- Precision (Pos Pred Value) = dari semua hasil prediksi Target
1
(terdapat api), seberapa mampu model saya dapat memprediksi benar. - Negative Predict Value (Neg Pred Value) : dari semua hasil prediksi Target
0
(tidak terdapat api), seberapa mampu model saya dapat memprediksi benar.
Sebaiknya pada kasus ini, kita memperhatikan metrik selain Accuracy karena data test asli memiliki ketidakseimbangan Target.
- Sensitivity : 0.9998
- Specificity : 0.9996
- Accuracy : 0.9998
- Pos Pred Value (Precision) : 0.9998
- Neg Pred Value : 0.9996
Kita berhasil menghasilkan model yang hanya salah 4 kali dalam mengklasifikasikan Target dari data test yang berisi 16,284 data.
Secara keseluruhan model
Decision Tree
kita sudah sangat baik karena semua metrik memiliki performa hampir 100%.
Perbandingan Performa Naive Bayes dengan Decision Tree
data.frame(
Metrics = c("Sensitivity", "Specificity", "Accuracy", "Pos Pred Value", "Neg Pred Value"),
Naive_Bayes = c(0.9751, 0.6594, 0.885, 0.8776, 0.9135 ),
Decision_Tree = c(0.9998, 0.9996, 0.9998, 0.9998, 0.9996)
)
Secara performa saya merasa dengan menggunakan Decision Tree
lebih cocok dibandingkan Naive Bayes
pada kasus data smoke. Hal ini disebabkan nilai dari 5 metrik diatas relatif lebih tinggi. Artinya Decision Tree relatif dapat mengklasifikasikan 0
(Tidak Terdapat Api) dan 1
(Terdapat Api) dengan sangat baik karena performa dalam membedakan kedua Target di atas mendekati 100 %. Pada kasus ini kita tidak menggangap algoritma Naive Bayes lebih buruk daripada Decision Tree, tetapi menggangap pada kasus data smoke ini cenderung lebih cocok menggunakan algoritma Decision Tree.
Kesimpulan
Kita telah melalui berbagai proses dalam pembuatan Machine Learning yang dapat membedakan Target 0 (Tidak Terdapat Api) dan 1 (Terdapat Api). Pada proses tersebut, kita telah mencoba dua algoritma dalam membangun Machine Learning yaitu Naive Bayes dan Decision Tree. Selain itu, kita telah mengevaluasi Machine Learning dan menghasilkan kesimpulan bahwa dengan algoritma Decision Tree memiliki performa relatif lebih baik (lebih cocok) dibandingkan Naive Bayes. Harapannya melalui projek ini dapat menjadi referensi dalam membangun Machine Learning untuk melakukan klasifikasi sehingga dapat menjadi dasar dalam mengambil keputusan secara efektif dan efisien. Sekian terima kasih banyak yang telah melihat projek ini. Saya juga menyukai masukan dan kolaborasi sehingga apabila ada masukan, saran, kritik atau untuk berkolaborasi dapat menghubungi lewat Linkedin.