1 Introduction

Naïve Bayes adalah algoritma pembelajaran mesin berbasis probabilistik yang menggunakan Teorema Bayes sebagai dasar untuk membuat prediksi. Algoritma ini disebut “naive” karena mengasumsikan bahwa semua fitur (variabel) bersifat independen satu sama lain.

Meskipun asumsi ini jarang berlaku di dunia nyata, Naïve Bayes seringkali memberikan hasil yang sangat baik, terutama dalam aplikasi klasifikasi seperti analisis teks dan pengenalan pola.

Teorema Bayes dapat dirumuskan sebagai:

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

Keterangan:

  • \(P(A|B)\): Probabilitas \(A\) terjadi dengan kondisi \(B\) diketahui (posterior).

  • \(P(B|A)\): Probabilitas \(B\) terjadi dengan kondisi \(A\) diketahui (likelihood).

  • \(P(A)\): Probabilitas awal \(A\) terjadi (prior).

  • \(P(B)\): Probabilitas awal \(B\) terjadi (normalisasi).


Naïve Bayes dengan Asumsi Independen

Asumsi independensi antar fitur mengubah probabilitas gabungan menjadi:

\[ P(X_1, X_2, \ldots, X_n|Y) = P(X_1|Y) \cdot P(X_2|Y) \cdot \ldots \cdot P(X_n|Y) \]

Prediksi kelas dilakukan dengan memaksimalkan probabilitas posterior:

\[ P(Y|X) \propto P(X|Y) \cdot P(Y) \]

Karena \(P(X)\) konstan untuk semua kelas, maka hanya perlu menghitung \(P(X|Y) \cdot P(Y)\).


Distribusi Probabilitas Naïve Bayes

  1. Gaussian Naïve Bayes (Kontinu)
    Untuk data kontinu, probabilitas dihitung menggunakan distribusi normal (Gaussian):

    \[ P(X|Y) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp{\left(-\frac{(X - \mu)^2}{2\sigma^2}\right)} \]

    Keterangan:

    • \(\mu\): Mean (rata-rata).
    • \(\sigma^2\): Varians.
  2. Multinomial Naïve Bayes (Diskrit)
    Untuk data diskrit, seperti frekuensi kata, probabilitas dihitung sebagai:

    \[ P(X|Y) = \frac{\text{Count}(X, Y) + 1}{\text{Count}(Y) + |V|} \]

    Keterangan:

    • \(\text{Count}(X, Y)\): Frekuensi fitur \(X\) pada kelas \(Y\).
    • \(|V|\): Jumlah fitur unik.
  3. Bernoulli Naïve Bayes (Biner)
    Untuk data biner (0/1), probabilitas dihitung dengan:

    \[ P(X|Y) = p^x \cdot (1-p)^{1-x} \]

    Keterangan:

    • \(p\): Probabilitas kemunculan fitur \(X\) pada kelas \(Y\).
    • \(x\): Nilai fitur (0 atau 1).

dataset = read.csv('Kesakitan.csv')
#Menyederhanakan dataset hanya untuk fitur yang relevan dan target variabel `Morbid`.
dataset = dataset[3:5]

Hanya mengambil kolom ke-3 hingga ke-5, yaitu Umur, Kapita, dan Morbid.

head(dataset)
##   Umur Kapita Morbid
## 1   19  19000      0
## 2   35  20000      0
## 3   26  43000      0
## 4   27  57000      0
## 5   19  76000      0
## 6   27  58000      0
glimpse(dataset)
## Rows: 400
## Columns: 3
## $ Umur   <int> 19, 35, 26, 27, 19, 27, 27, 32, 25, 35, 26, 26, 20, 32, 18, 29,…
## $ Kapita <int> 19000, 20000, 43000, 57000, 76000, 58000, 84000, 150000, 33000,…
## $ Morbid <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, …

Membuat variabel target bertipe factor. Memastikan bahwa model mengenali variabel target sebagai kategori, bukan nilai numerik.

dataset$Morbid = factor(dataset$Morbid, levels = c(0, 1))
str(dataset)
## 'data.frame':    400 obs. of  3 variables:
##  $ Umur  : int  19 35 26 27 19 27 27 32 25 35 ...
##  $ Kapita: int  19000 20000 43000 57000 76000 58000 84000 150000 33000 65000 ...
##  $ Morbid: Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 2 1 1 ...

2 Splitting Train-Test

Menggunakan training set untuk melatih model dan test set untuk mengevaluasi performa model.

library(caTools)
set.seed(785)
split = sample.split(dataset$Morbid, SplitRatio = 0.80)
training_set = subset(dataset, split == TRUE)
test_set = subset(dataset, split == FALSE)

3 Features Scaling

Perbedaan skala antar fitur dapat memengaruhi kinerja model. Untuk mengatasi hal ini, disarankan untuk selalu melakukan scaling pada fitur, terutama ketika terdapat perbedaan skala yang signifikan. Salah satu metode scaling yang dapat digunakan adalah normalisasi (MinMax Scaling), yang mengubah setiap fitur menjadi rentang nilai antara 0 dan 1.

Melakukan normalisasi data pada fitur numerik (Umur dan Kapita) agar berada pada skala yang sama.

training_set[-3] = scale(training_set[-3])
test_set[-3] = scale(test_set[-3])

4 Modelling

Membuat model yang dapat memprediksi apakah seseorang akan mengalami kesakitan (Morbid).

Fitting Naïve Bayes to the Training set

Melatih model Naïve Bayes menggunakan fitur (Umur dan Kapita) pada training.

library(e1071)
classifier = naiveBayes(x = training_set[-3],
                        y = training_set$Morbid) 

Predicting the Test set results

Mengevaluasi performa model pada data yang belum dilihat (test set).

Menggunakan model yang dilatih untuk memprediksi target pada test set.

y_pred = predict(classifier, newdata = test_set[-3])
y_pred
##  [1] 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1
## [39] 1 1 0 0 1 0 0 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 1 0 0 1 1
## [77] 1 1 1 1
## Levels: 0 1

5 Evaluasi Model

Mengevaluasi performa model dengan menghitung metrik seperti akurasi, sensitivitas, dan spesifisitas.

cm = table(test_set[, 3], y_pred)

library(caret)
conf_matrix = confusionMatrix(cm)
print(conf_matrix)
## Confusion Matrix and Statistics
## 
##    y_pred
##      0  1
##   0 43  4
##   1  9 24
##                                           
##                Accuracy : 0.8375          
##                  95% CI : (0.7382, 0.9105)
##     No Information Rate : 0.65            
##     P-Value [Acc > NIR] : 0.0001648       
##                                           
##                   Kappa : 0.657           
##                                           
##  Mcnemar's Test P-Value : 0.2672575       
##                                           
##             Sensitivity : 0.8269          
##             Specificity : 0.8571          
##          Pos Pred Value : 0.9149          
##          Neg Pred Value : 0.7273          
##              Prevalence : 0.6500          
##          Detection Rate : 0.5375          
##    Detection Prevalence : 0.5875          
##       Balanced Accuracy : 0.8420          
##                                           
##        'Positive' Class : 0               
## 

Evaluasi Model

Accuracy:

Accuracy adalah proporsi prediksi yang benar dibandingkan dengan total prediksi yang dibuat. Di sini, Accuracy sebesar 0.8375 artinya sekitar 83.75% dari prediksi model adalah benar.

95% Confidence Interval (CI):

Ini menunjukkan rentang akurasi model dengan tingkat kepercayaan 95%. CI: (0.7382, 0.9105). Artinya, keyakinan akurasi model berada antara 73.82% hingga 91.05%.

No Information Rate (NIR):

NIR adalah akurasi yang dapat dicapai dengan hanya memprediksi kelas yang paling banyak, tanpa mempertimbangkan fitur atau model. NIR diperoleh sebesar 0.65, yang berarti model bisa saja memprediksi kelas mayoritas dengan akurasi 65% tanpa menggunakan informasi lain.

P-Value [Acc > NIR]:

Nilai p ini menguji apakah akurasi model lebih baik daripada prediksi yang hanya memanfaatkan NIR. P-Value diperoleh sebesar 0.0001648, menunjukkan bahwa akurasi model secara signifikan lebih baik daripada hanya memprediksi kelas mayoritas (NIR).

Kappa:

Kappa mengukur kesepakatan antara model dan data yang lebih tinggi dari yang diharapkan secara kebetulan. Kappa diperoleh sebesar 0.657, yang menunjukkan kesepakatan yang baik antara prediksi model dan data aktual (skala 0-1, semakin mendekati 1 semakin baik).

Mcnemar’s Test P-Value:

Ini adalah uji statistik untuk memeriksa apakah ada perbedaan signifikan dalam prediksi model (False Positive vs False Negative). P-Value diperoleh sebesar 0.2672575, yang berarti tidak ada perbedaan signifikan antara prediksi False Positives dan False Negatives.

Metrik Kinerja Klasifikasi

Sensitivity (Recall or True Positive Rate):

Sensitivity mengukur seberapa baik model menangkap kasus positif. Sensitivity = TP / (TP + FN) = 0.8269, artinya model mengenali 82.69% kasus positif.

Specificity (True Negative Rate):

Specificity mengukur seberapa baik model mengenali kasus negatif. Specificity = TN / (TN + FP) = 0.8571, artinya model mengenali 85.71% kasus negatif.

Positive Predictive Value (Precision):

Precision mengukur seberapa akurat prediksi positif model. Precision = TP / (TP + FP) = 0.9149, artinya 91.49% dari prediksi positif model adalah benar.

Negative Predictive Value:

Negatif Prediktif mengukur seberapa akurat prediksi negatif model. NPV = TN / (TN + FN) = 0.7273, artinya 72.73% dari prediksi negatif model adalah benar.

Prevalence:

Prevalence mengukur proporsi kelas positif dalam data. Prevalence: 0.65, artinya 65% dari data adalah kelas positif (misalnya, mengalami kesakitan).

Detection Rate:

Detection Rate mengukur proporsi kasus positif yang berhasil terdeteksi oleh model. Detection Rate = TP / Total Positif = 0.5375, artinya model berhasil mendeteksi 53.75% dari semua kasus positif.

Detection Prevalence:

Detection Prevalence mengukur proporsi prediksi positif yang dihasilkan oleh model.

Detection Prevalence = Prediksi Positif / Total Data = 0.5875, artinya 58.75% dari semua prediksi model adalah positif.

Balanced Accuracy:

Ini adalah rata-rata dari Sensitivity dan Specificity, memberikan gambaran yang lebih seimbang mengenai kinerja model dalam mendeteksi kedua kelas.

Balanced Accuracy = (Sensitivity + Specificity) / 2 = 0.8420, yang menunjukkan kinerja model yang cukup baik dalam mendeteksi kedua kelas.

6 ROC Curve dan AUC Score

Menghitung dan memplot ROC curve untuk mengevaluasi trade-off antara sensitivitas dan spesifisitas, serta menghitung skor AUC.

library(pROC)
# Menghitung probabilitas prediksi
y_prob = predict(classifier, newdata = test_set[-3], type = "raw")[, 2]

# Menghasilkan ROC curve
roc_obj = roc(test_set$Morbid, y_prob)
plot(roc_obj, col = "blue", main = "ROC Curve - Naïve Bayes")

auc_value = auc(roc_obj)
cat("AUC Score:", auc_value, "\n")
## AUC Score: 0.877176

Melalui ukuran AUC, tampak model ini menunjukkan performa yang baik dalam membedakan antara kelas positif dan negatif. Model ini mampu membedakan dengan baik, karena nilai AUC mendekati 1, yang menunjukkan bahwa model memiliki kemampuan prediksi yang sangat baik dalam mengidentifikasi kedua kelas.

7 Variable Importance

Meskipun Naïve Bayes tidak secara langsung menghasilkan nilai “variable importance” seperti model berbasis pohon (misalnya Random Forest), tapi tetap dapat membuat grafik “variable importance” berdasarkan analisis distribusi atau skor likelihood rasio dari fitur-fitur dalam model.

library(dplyr)
library(ggplot2)

# Menghitung mean dan standard deviation untuk setiap kelas
summary_stats <- dataset %>%
  group_by(Morbid) %>%
  summarise(
    Mean_Umur = mean(Umur),
    SD_Umur = sd(Umur),
    Mean_Kapita = mean(Kapita),
    SD_Kapita = sd(Kapita)
  )

# Menghitung likelihood ratio
Umur_likelihood_ratio <- abs(summary_stats$Mean_Umur[1] - summary_stats$Mean_Umur[2]) / 
  (summary_stats$SD_Umur[1] + summary_stats$SD_Umur[2])
Umur_likelihood_ratio
## [1] 0.5917271
salary_likelihood_ratio <- abs(summary_stats$Mean_Kapita[1] - summary_stats$Mean_Kapita[2]) / 
  (summary_stats$SD_Kapita[1] + summary_stats$SD_Kapita[2])
salary_likelihood_ratio
## [1] 0.3362888
# Membuat dataframe untuk visualisasi
variable_importance <- data.frame(
  Variable = c("Umur", "Kapita"),
  Importance = c(Umur_likelihood_ratio, salary_likelihood_ratio)
)

# Membuat grafik variable importance
ggplot(variable_importance, aes(x = reorder(Variable, -Importance), y = Importance, fill = Variable)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Variable Importance (Likelihood Ratio)", x = "Variable", y = "Importance") +
  theme_minimal() +
  scale_fill_manual(values = c("steelblue", "tomato"))

8 Visualisasi

Memahami bagaimana model memisahkan kelas berdasarkan fitur.

Memvisualisasikan decision boundary model pada training set

# Visualising the Training set results
library(ElemStatLearn)
set = training_set
X1 = seq(min(set[, 1]) - 1, max(set[, 1]) + 1, by = 0.01)
X2 = seq(min(set[, 2]) - 1, max(set[, 2]) + 1, by = 0.01)
grid_set = expand.grid(X1, X2)
colnames(grid_set) = c('Umur', 'Kapita')
y_grid = predict(classifier, newdata = grid_set)
plot(set[, -3],
     main = 'Naïve Bayes (Training set)',
     xlab = 'Umur', ylab = 'Estimated Salary',
     xlim = range(X1), ylim = range(X2))
contour(X1, X2, matrix(as.numeric(y_grid), length(X1), length(X2)), add = TRUE)
points(grid_set, pch = '.', col = ifelse(y_grid == 1, 'springgreen3', 'tomato'))
points(set, pch = 21, bg = ifelse(set[, 3] == 1, 'green4', 'red3'))

Memvisualisasikan decision boundary model pada test set

# Visualising the Test set results
library(ElemStatLearn)
set = test_set
X1 = seq(min(set[, 1]) - 1, max(set[, 1]) + 1, by = 0.01)
X2 = seq(min(set[, 2]) - 1, max(set[, 2]) + 1, by = 0.01)
grid_set = expand.grid(X1, X2)
colnames(grid_set) = c('Umur', 'Kapita')
y_grid = predict(classifier, newdata = grid_set)
plot(set[, -3], main = 'Naïve Bayes (Test set)',
     xlab = 'Umur', ylab = 'Estimated Salary',
     xlim = range(X1), ylim = range(X2))
contour(X1, X2, matrix(as.numeric(y_grid), length(X1), length(X2)), add = TRUE)
points(grid_set, pch = '.', col = ifelse(y_grid == 1, 'springgreen3', 'tomato'))
points(set, pch = 21, bg = ifelse(set[, 3] == 1, 'green4', 'red3'))


Direktorat Statistik Kesejahteraan Rakyat, BPS,