Logo

Laporan Analisis dan Pemodelan Prediktif – Ensamble Models

1. Pengenalan Ensemble Models

Ensemble learning adalah pendekatan dalam machine learning yang menggabungkan beberapa model (biasanya model lemah/weak learners) untuk menghasilkan model prediktif yang lebih kuat, stabil, dan akurat. Konsep utamanya: “menggabungkan banyak pikiran lebih baik daripada satu.” Dalam konteks penelitian ini, pendekatan ensemble dipilih karena mampu menangani data dengan kompleksitas tinggi, hubungan non-linear, serta performanya yang terbukti lebih baik dibanding model tunggal.

Ensemble methods secara umum terbagi menjadi dua kategori utama:

  1. Bagging (Bootstrap Aggregating) → fokus mengurangi variance
  2. Boosting → fokus mengurangi bias secara bertahap

Tiga model yang digunakan dalam penelitian ini mewakili dua pendekatan tersebut:

  • Random Forest → bagging
  • GBM → boosting dasar
  • XGBoost → boosting modern yang dioptimasi

Di bawah ini penjelasan tiap model.


1.1 Random Forest

Random Forest adalah metode ensemble berbasis bagging yang menggabungkan banyak pohon keputusan (decision tree) yang dilatih pada sampel bootstrap. Setiap pohon hanya melihat sebagian fitur untuk membuat split, sehingga menghasilkan variasi antar pohon dan menurunkan risiko overfitting.

1. Rumus Dasar Random Forest

  • 1.Bagging (Bootstrap Aggregating)

Random Forest membangun ( B ) pohon. Untuk setiap pohon ke-(b):

  1. Ambil sampel bootstrap dari dataset asli:

\[ D_b = {(x_i, y_i)}_{i=1}^{n}, \quad D_b \sim \text{Bootstrap}(D) \]

  1. Latih pohon keputusan menggunakan ( D_b ) dengan memilih subset acak fitur pada setiap node.
  • 2. Random Feature Selection (mtry)

Pada setiap node split, dipilih secara acak mtry fitur dari total (p) fitur:

\[ S_b \subset {1,2,\dots,p}, \quad |S_b| = m_{\text{try}} \]

Split terbaik dipilih dari fitur-fitur dalam (S_b).

  • 3. Prediksi Random Forest

Regresi

Jika setiap pohon menghasilkan prediksi:

\[ \hat{f}_b(x) \]

Maka prediksi Random Forest adalah rata-rata:

\[ \hat{F}(x) = \frac{1}{B} \sum_{b=1}^{B} \hat{f}_b(x) \]

Klasifikasi

Untuk label kelas (k):

\[ \hat{F}(x) = \arg\max_k \sum_{b=1}^{B} \mathbf{1}(\hat{f}_b(x) = k) \]

Dengan kata lain: → prediksi akhir = majority voting dari semua pohon.


  • 4. Out-of-Bag (OOB) Estimation

Karena setiap bootstrap meninggalkan sekitar 36.8% data (tidak masuk sampel), maka sampel OOB digunakan untuk evaluasi.

Untuk setiap observasi ke-(i), misal (S_i) adalah himpunan pohon yang tidak melihat data tersebut:

\[ \hat{F}*{\text{OOB}}(x_i) = \frac{1}{|S_i|} \sum*{b \in S_i} \hat{f}_b(x_i) \]

OOB error:

\[ \text{OOB Error} = \frac{1}{n} \sum_{i=1}^{n} L\left(y_i,; \hat{F}_{\text{OOB}}(x_i)\right) \]

  • 5. Feature Importance (Gini / MSE Reduction)

Untuk fitur (X_j), importance dihitung sebagai:

\[ \text{Imp}(X_j) = \frac{1}{B} \sum_{b=1}^{B} \sum_{t \in T_b(X_j)} \Delta L_{t} \]

Di mana:

  • (T_b(X_j)) = node-node dalam pohon (b) yang melakukan split pada fitur (j)
  • (L_t) = pengurangan impurity (MSE atau Gini) pada node tersebut

Karakteristik Utama

  • Termasuk metode bagging
  • Menggunakan bootstrap sampling
  • Mengambil subset acak fitur di setiap split
  • Hasil prediksi berdasarkan majority voting (klasifikasi) atau rata-rata (regresi)

Kelebihan

  • Tahan terhadap overfitting
  • Stabil meskipun data memiliki noise
  • Dapat menangani data numerik maupun kategorik
  • Menyediakan feature importance

Kelemahan

  • Interpretabilitas rendah (karena gabungan banyak pohon)
  • Waktu komputasi bisa meningkat jika jumlah pohon terlalu besar

1.2 Gradient Boosting Machines (GBM)

GBM adalah metode boosting yang membangun model secara bertahap. Setiap pohon baru berusaha memperbaiki kesalahan dari pohon sebelumnya dengan gradient descent pada fungsi loss. Berbeda dengan Random Forest, pohon tidak dibuat secara paralel tetapi berurutan.

Rumus Dasar GBM (Regresi)

  • 1. Inisialisasi Model Awal

Model pertama adalah nilai konstanta yang meminimalkan fungsi loss:

\[ F_0(x) = \arg\min_{\gamma} \sum_{i=1}^{n} L(y_i, \gamma) \]

Untuk regresi MSE, nilai ini adalah rata-rata target:

\[ F_0(x) = \bar{y} \]


  • 2. Untuk Setiap Iterasi (m = 1, 2, , M)

(a) Hitung Negative Gradient (Residual)

Residual mewakili seberapa besar kesalahan model sebelumnya:

\[ r_{im} = -\left[ \frac{\partial L(y_i, F(x_i))}{\partial F(x_i)} \right]*{F(x_i)=F*{m-1}(x_i)} \]

Untuk regresi MSE:

\[ r_{im} = y_i - F_{m-1}(x_i) \]


(b) Latih Pohon Ke-m Menggunakan Residual

\[ h_m(x) \approx r_{im} \]

Pohon regresi dilatih untuk memprediksi residual tersebut.


(c) Hitung Optimal Weight (Shrinkage Factor)

Untuk setiap leaf terminal (j):

\[ \gamma_{jm} = \arg\min_{\gamma} \sum_{x_i \in R_{jm}} L\big(y_i,; F_{m-1}(x_i) + \gamma \big) \]

Untuk regresi MSE:

\[ \gamma_{jm} = \frac{\sum_{x_i \in R_{jm}} r_{im}}{|R_{jm}|} \]

(d) Update Model

\[ F_m(x) = F_{m-1}(x) + \nu \sum_{j=1}^{J_m} \gamma_{jm} \mathbf{1}(x \in R_{jm}) \]

Di mana:

  • () = learning rate

  • (J_m) = jumlah leaf pada pohon ke-m

3. Model Akhir

\[ F_M(x) = F_0(x) + \sum_{m=1}^{M} \nu \cdot h_m(x) \]

Karakteristik Utama

  • Menggunakan boosting sekuensial
  • Tiap model baru memperbaiki residual error model sebelumnya
  • Menggunakan gradient descent untuk optimasi

Kelebihan

  • Akurasi tinggi pada berbagai jenis permasalahan
  • Mampu menangani hubungan non-linear
  • Mendukung berbagai loss function

Kelemahan

  • Rentan overfitting jika parameter tidak diatur dengan baik
  • Training lebih lambat karena sifatnya sekuensial
  • Sensitif terhadap outlier

1.3 Extreme Gradient Boosting (XGBoost)

XGBoost (Extreme Gradient Boosting) merupakan pengembangan dari GBM yang lebih efisien, cepat, dan akurat. XGBoost menambahkan regularisasi L1 dan L2 untuk mengurangi overfitting dan mempercepat komputasi menggunakan teknik optimasi canggih serta pemrosesan paralel.

  • 1. Fungsi Tujuan (Objective Function)

XGBoost meminimalkan:

\[ \mathcal{L} = \sum_{i=1}^{n} l\left(y_i,; \hat{y}*i^{(t)}\right) + \sum*{k=1}^{t} \Omega(f_k) \]

Dimana:

    1. = loss function (misal: squared error, logistic loss)
  • (_i^{(t)}) = prediksi di iterasi ke-(t)

  • (f_k) = pohon keputusan ke-(k)

  • ((f_k)) = regularisasi kompleksitas pohon

  • 2. Regularisasi (Pembeda utama XGBoost)

\[ \Omega(f) = \gamma T + \frac{1}{2} \lambda \sum_{j=1}^{T} w_j^2 \]

Di mana:

    1. = jumlah daun (leaves)
  • (w_j) = nilai prediksi pada leaf (j)
  • () = penalti membuat leaf baru
  • () = penalti L2 untuk bobot leaf

Tujuan: mencegah overfitting dan mempercepat model.

  • 3. Additive Model (Boosting)

Model dibangun secara bertahap:

\[ \hat{y}_i^{(t)} = \hat{y}_i^{(t-1)} + \eta f_t(x_i) \]

  • (f_t) = pohon baru yang dilatih pada iterasi ke-t

  • () = learning rate (shrinkage)

  • 4. Gradient & Hessian

XGBoost menggunakan pendekatan second-order Taylor expansion.

Untuk setiap data titik (i):

\[ g_i = \frac{\partial l(y_i,\hat{y}_i^{(t-1)})}{\partial \hat{y}_i^{(t-1)}} \]

\[ h_i = \frac{\partial^2 l(y_i,\hat{y}_i^{(t-1)})}{\partial (\hat{y}_i^{(t-1)})^2} \]

  • (g_i) = first derivative (gradient)
  • (h_i) = second derivative (hessian)

Ini membuat XGBoost lebih akurat dan stabil dibanding GBM biasa.

  • 5. Scoring Function untuk Node / Split

Gain ketika memecah node:

\[ \text{Gain} = \frac{1}{2} \left( \frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} - \frac{(G_L + G_R)^2}{H_L + H_R + \lambda} \right) - \gamma \]

Dimana:

  • (G_L = _{i L} g_i)
  • (H_L = _{i L} h_i)
  • (G_R, H_R) untuk sisi kanan
  • () = penalti leaf baru

Split dipilih jika Gain > 0.

  • 6. Nilai Leaf Optimal

Untuk setiap leaf (j):

\[ w_j^* = -\frac{G_j}{H_j + \lambda} \]

Model prediksi pohon:

\[ f_t(x) = w_j^* \quad \text{jika } x \text{ jatuh pada leaf } j \]

  • 7. Prediksi Akhir

Untuk regresi:

\[ \hat{y}(x) = \sum_{t=1}^{T} \eta f_t(x) \]

Karakteristik Utama

  • Versi “tuned and optimized” dari GBM
  • Mendukung regularisasi (L1, L2) → mencegah overfitting
  • Optimasi komputasi: parallelization, cache awareness, dan tree pruning
  • Mendukung sparse data

Kelebihan

  • Kinerja prediktif sangat kuat
  • Lebih cepat dibanding GBM biasa
  • Mendukung fitur-fitur lanjutan: early stopping, handling missing value, weighted data
  • Cocok untuk dataset besar dan kompleks

Kelemahan

  • Relatif lebih rumit dalam tuning hyperparameter
  • Konsumsi memori lebih besar pada dataset sangat besar

Ringkasan Perbedaan Ketiga Model

Model Metode Kekuatan Kekurangan
Random Forest Bagging Stabil, tahan overfitting Tidak sekuat boosting untuk pola kompleks
GBM Boosting sekuensial Akurasi tinggi Training lebih lambat, butuh tuning hati-hati
XGBoost Boosting + optimasi Paling akurat, cepat, ada regularisasi Parameter lebih kompleks

2. Identifikasi Masalah

Penelitian ini bertujuan untuk membangun model prediksi berbasis ensemble learning guna mengklasifikasikan apakah seseorang berpotensi mengalami penyakit jantung berdasarkan berbagai parameter fisiologis. Identifikasi masalah pada penelitian ini dijelaskan sebagai berikut.

2.1 Apa yang Ingin Diprediksi

Penelitian ini ingin memprediksi status penyakit jantung (HeartDisease), yaitu kondisi apakah seseorang memiliki indikasi penyakit jantung atau tidak.

Prediksi HeartDisease penting karena:

  • Dapat membantu deteksi dini risiko penyakit jantung,
  • Membantu pengambilan keputusan medis,
  • Mendukung tindakan pencegahan secara lebih cepat dan tepat.

2.2 Variabel Target

Variabel target dalam penelitian ini adalah:

HeartDisease (0 atau 1)

  • 0 → tidak memiliki penyakit jantung
  • 1 → memiliki penyakit jantung

Variabel ini berupa data kategorik biner, sehingga jenis prediksi adalah klasifikasi, bukan regresi.

HeartDisease akan diprediksi menggunakan 11 variabel fitur:

  • Age
  • Sex
  • ChestPainType
  • RestingBP
  • Cholesterol
  • FastingBS
  • RestingECG
  • MaxHR
  • ExerciseAngina
  • Oldpeak
  • ST_Slope

Fitur terdiri dari gabungan variabel numerik dan kategorik.

2.3 Alasan Menggunakan Ensemble Learning

Berdasarkan teori pada Bab 1, ensemble learning dipilih karena memiliki beberapa keunggulan signifikan untuk kasus klasifikasi kesehatan seperti dataset ini:

  1. Akurasi lebih tinggi dibanding model tunggal Gabungan beberapa model menghasilkan prediksi yang lebih stabil.

  2. Mampu menangani hubungan non-linear Relasi antara variabel fisiologis—seperti tekanan darah, kolesterol, detak jantung—sering tidak linear sehingga lebih cocok ditangani model ensemble.

  3. Robust terhadap outlier dan noise Random Forest dan XGBoost sangat tahan terhadap data ekstrem.

  4. Mengurangi bias dan variance

    • RF → menurunkan variance (bagging)
    • GBM → menurunkan bias (boosting)
    • XGBoost → boosting dengan regularisasi → lebih stabil & menghindari overfitting

Dengan karakteristik tersebut, ensemble learning dinilai cocok untuk kasus prediksi risiko penyakit jantung.

2.4 Tujuan Perbandingan Tiga Model Ensemble

Penelitian ini bertujuan untuk membangun dan membandingkan tiga algoritma ensemble learning, yaitu:

  1. Random Forest Classifier
  2. Gradient Boosting Classifier (GBM)
  3. Extreme Gradient Boosting (XGBoost)

Tujuan dari perbandingan adalah:

  • Menentukan model mana yang memberikan performa terbaik untuk klasifikasi HeartDisease.
  • Mengamati perbedaan akurasi, recall, precision, F1-score, dan AUC dari masing-masing model.
  • Melihat bagaimana boosting modern (XGBoost) dibandingkan dengan metode bagging (RF) dan boosting klasik (GBM).
  • Memberikan rekomendasi model terbaik untuk deteksi risiko penyakit jantung.

3. Data Understanding

Bagian ini menjelaskan sumber data, struktur dataset, serta penjelasan setiap variabel yang digunakan dalam penelitian. Pemahaman awal terhadap data menjadi langkah penting sebelum melakukan analisis maupun pemodelan ensemble.

3.1 Sumber Data

Dataset yang digunakan berasal dari platform Kaggle dengan nama file heart.csv, yaitu dataset medis modern yang memuat informasi demografis, gejala klinis, serta hasil pemeriksaan kardiovaskular. Dataset ini umum digunakan dalam pemodelan prediksi risiko penyakit jantung, namun formatnya adalah versi yang telah diperbarui menjadi kategori berbentuk string, bukan kode numerik.

3.2 Jumlah Baris dan Kolom

Berdasarkan hasil pemeriksaan:

  • 918 baris (observations)
  • 12 kolom (11 features + 1 target)

Dataset ini memiliki variabel target biner, sehingga sesuai untuk tugas klasifikasi menggunakan metode ensemble.

3.3 Tipe Data

Dataset memiliki dua jenis tipe data utama:

Numerik

  • Age
  • RestingBP
  • Cholesterol
  • FastingBS
  • MaxHR
  • Oldpeak
  • HeartDisease

Kategorikal (String/Object)

  • Sex
  • ChestPainType
  • RestingECG
  • ExerciseAngina
  • ST_Slope

Kombinasi tipe numerik dan kategorikal ini berpengaruh terhadap metode encoding serta pemilihan model, terutama pada algoritma seperti XGBoost yang tidak menerima fitur kategorik secara langsung.

3.4 Penjelasan Variabel

Variabel Tipe Deskripsi
Age Integer Usia pasien (tahun).
Sex Object Jenis kelamin: M = Male, F = Female.
ChestPainType Object Tipe nyeri dada (ATA, NAP, ASY, TA).
RestingBP Integer Tekanan darah istirahat (mmHg).
Cholesterol Integer Kadar kolesterol total (mg/dl).
FastingBS Integer Gula darah puasa > 120 mg/dl (1 = ya, 0 = tidak).
RestingECG Object Hasil ECG istirahat (Normal, ST, LVH).
MaxHR Integer Detak jantung maksimum yang dicapai.
ExerciseAngina Object Angina akibat olahraga (Y = ya, N = tidak).
Oldpeak Float Depresi ST akibat olahraga.
ST_Slope Object Kemiringan segmen ST (Up, Flat, Down).
HeartDisease Integer Target: 1 = ada penyakit jantung, 0 = tidak ada.

3.5 Distribusi Kelas Target (Wajib untuk Klasifikasi)

Berdasarkan eksplorasi awal dataset:

  • HeartDisease = 1 (Ada penyakit jantung) → sekitar 55%
  • HeartDisease = 0 (Tidak ada penyakit jantung) → sekitar 45%

Distribusi kelas tergolong cukup seimbang, sehingga metrik seperti Accuracy, Precision, Recall, dan F1-score masih relevan digunakan tanpa perlu teknik penyeimbangan data seperti SMOTE.


4. Exploratory Data Analysis (EDA)

EDA dilakukan untuk memahami karakteristik awal dataset sebelum proses preprocessing dan pemodelan ensemble dilakukan. Bagian ini mencakup statistik deskriptif, pemeriksaan nilai ekstrem, serta interpretasi awal terhadap pola data.

4.1 Statistik Deskriptif

Statistik deskriptif digunakan untuk memahami karakteristik awal dari variabel numerik dalam dataset, antara lain:

  • Age
  • RestingBP
  • Cholesterol
  • FastingBS
  • MaxHR
  • Oldpeak

Analisis ini mencakup nilai minimum, maksimum, mean, median, serta kuartil. Statistik deskriptif membantu:

  • Mengidentifikasi nilai ekstrem (outlier) seperti kolesterol 0 atau tekanan darah abnormal.
  • Melihat distribusi usia pasien.
  • Menilai kecenderungan detak jantung maksimum.
  • Memahami variasi kondisi fisiologis pasien sebelum pemodelan.
## 'data.frame':    918 obs. of  12 variables:
##  $ Age           : int  40 49 37 48 54 39 45 54 37 48 ...
##  $ Sex           : chr  "M" "F" "M" "F" ...
##  $ ChestPainType : chr  "ATA" "NAP" "ATA" "ASY" ...
##  $ RestingBP     : int  140 160 130 138 150 120 130 110 140 120 ...
##  $ Cholesterol   : int  289 180 283 214 195 339 237 208 207 284 ...
##  $ FastingBS     : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ RestingECG    : chr  "Normal" "Normal" "ST" "Normal" ...
##  $ MaxHR         : int  172 156 98 108 122 170 170 142 130 120 ...
##  $ ExerciseAngina: chr  "N" "N" "N" "Y" ...
##  $ Oldpeak       : num  0 1 0 1.5 0 0 0 0 1.5 0 ...
##  $ ST_Slope      : chr  "Up" "Flat" "Up" "Flat" ...
##  $ HeartDisease  : int  0 1 0 1 0 0 0 0 1 0 ...
##       Age            Sex            ChestPainType        RestingBP    
##  Min.   :28.00   Length:918         Length:918         Min.   :  0.0  
##  1st Qu.:47.00   Class :character   Class :character   1st Qu.:120.0  
##  Median :54.00   Mode  :character   Mode  :character   Median :130.0  
##  Mean   :53.51                                         Mean   :132.4  
##  3rd Qu.:60.00                                         3rd Qu.:140.0  
##  Max.   :77.00                                         Max.   :200.0  
##   Cholesterol      FastingBS       RestingECG            MaxHR      
##  Min.   :  0.0   Min.   :0.0000   Length:918         Min.   : 60.0  
##  1st Qu.:173.2   1st Qu.:0.0000   Class :character   1st Qu.:120.0  
##  Median :223.0   Median :0.0000   Mode  :character   Median :138.0  
##  Mean   :198.8   Mean   :0.2331                      Mean   :136.8  
##  3rd Qu.:267.0   3rd Qu.:0.0000                      3rd Qu.:156.0  
##  Max.   :603.0   Max.   :1.0000                      Max.   :202.0  
##  ExerciseAngina        Oldpeak          ST_Slope          HeartDisease   
##  Length:918         Min.   :-2.6000   Length:918         Min.   :0.0000  
##  Class :character   1st Qu.: 0.0000   Class :character   1st Qu.:0.0000  
##  Mode  :character   Median : 0.6000   Mode  :character   Median :1.0000  
##                     Mean   : 0.8874                      Mean   :0.5534  
##                     3rd Qu.: 1.5000                      3rd Qu.:1.0000  
##                     Max.   : 6.2000                      Max.   :1.0000

Interpretasi Statistik Deskriptif

Berdasarkan hasil eksplorasi statistik deskriptif, beberapa karakteristik penting dari data dapat diinterpretasikan sebagai berikut:

1. Usia Pasien (Age)

Usia pasien berada pada rentang 28 hingga 77 tahun, dengan rata-rata 53.51 tahun. Nilai median sebesar 54 tahun menunjukkan bahwa sebagian besar pasien berada pada kelompok usia paruh baya hingga lanjut. Rentang kuartil (47–60 tahun) mengindikasikan konsentrasi utama usia berada di sekitar masa risiko penyakit jantung.

2. Tekanan Darah Istirahat (RestingBP)

RestingBP memiliki nilai minimum 0 mmHg, yang merupakan nilai tidak realistis dan mengindikasikan adanya outlier atau data error. Nilai maksimum mencapai 200 mmHg, dengan rata-rata 132.4 mmHg, dan mayoritas data berada pada rentang 120–140 mmHg (Q1–Q3). Hal ini menunjukkan adanya variasi tekanan darah antar pasien, termasuk potensi hipertensi pada sebagian besar pasien.

3. Kadar Kolesterol (Cholesterol)

Rentang kolesterol berada antara 0 hingga 603 mg/dl, dengan nilai 0 menandakan adanya missing value yang direpresentasikan secara salah atau anomalous input. Rata-rata 198.8 mg/dl menunjukkan bahwa banyak pasien memiliki kolesterol pada tingkat borderline hingga tinggi. Kuartil ketiga (267 mg/dl) mengindikasikan bahwa sebagian besar pasien memiliki kadar kolesterol cukup tinggi, yang menjadi faktor risiko signifikan penyakit jantung.

4. Gula Darah Puasa (FastingBS)

Variabel biner ini memiliki rata-rata 0.233, yang berarti sekitar 23.3% pasien memiliki kadar gula darah puasa di atas 120 mg/dl. Persentase ini menunjukkan sebagian kecil pasien memiliki potensi risiko diabetes yang dapat berkontribusi terhadap penyakit jantung.

5. Detak Jantung Maksimal (MaxHR)

MaxHR berada dalam rentang 60 hingga 202 bpm, dengan rata-rata 136.8 bpm. Kuartil ketiga sebesar 156 bpm menandakan bahwa sebagian besar pasien masih mampu mencapai detak jantung relatif tinggi saat aktivitas fisik, yang menggambarkan kapasitas kardiovaskular yang cukup baik bagi sebagian besar pasien.

6. Oldpeak

Oldpeak memiliki nilai minimum –2.6 hingga maksimum 6.2, dengan rata-rata 0.887. Mayoritas nilai berada pada kisaran 0 hingga 1.5, yang menunjukkan adanya variasi depresi segmen ST pada EKG akibat aktivitas fisik. Nilai negatif pada variabel ini kemungkinan merupakan hasil perhitungan tertentu atau measurement artifact, sehingga perlu diperhatikan pada tahap preprocessing.

7. Variabel Kategorikal

Variabel seperti Sex, ChestPainType, RestingECG, ExerciseAngina, dan ST_Slope semuanya bertipe karakter. Variabel-variabel ini menggambarkan kondisi klinis dan gejala pasien, seperti jenis kelamin, tipe nyeri dada, kondisi EKG, serta karakteristik segmen ST. Distribusi kategori ini penting dianalisis lebih lanjut pada tahap visualisasi untuk memahami persebaran dan potensi hubungan terhadap penyakit jantung.

8. Variabel Target (HeartDisease)

Rata-rata variabel target sebesar 0.553 menunjukkan bahwa 55.3% pasien pada dataset tercatat memiliki penyakit jantung. Hal ini menandakan dataset cenderung sedikit tidak seimbang, namun perbedaannya tidak terlalu signifikan sehingga masih aman untuk digunakan dalam pemodelan tanpa penyesuaian besar. Distribusi target ini juga mengindikasikan bahwa prevalensi penyakit jantung pada populasi data cukup tinggi.

Kesimpulan Singkat

Secara keseluruhan, statistik deskriptif menunjukkan:

  • Populasi pasien didominasi usia paruh baya–lanjut.
  • Terdapat outlier pada RestingBP dan Cholesterol yang perlu penanganan.
  • Beberapa faktor risiko seperti kolesterol tinggi, depresi ST, dan FastingBS > 120 muncul cukup jelas pada data.
  • Variabel target memiliki distribusi yang cukup seimbang untuk pemodelan klasifikasi.

4.2 Korelasi Antar Variabel

Interpretasi Visual Heatmap Korelasi

Visualisasi heatmap di atas memperlihatkan hubungan antar variabel melalui gradasi warna, di mana:

  • Biru tua menunjukkan korelasi positif kuat
  • Merah tua menunjukkan korelasi negatif kuat
  • Warna pucat (biru muda / merah muda) menunjukkan korelasi lemah atau hampir tidak ada hubungan

Dari pola warna pada heatmap, dapat diinterpretasikan sebagai berikut:

1. Pola Warna yang Mencolok

  • Age memiliki blok warna biru yang lebih gelap terhadap HeartDisease, menandakan hubungan positif yang cukup kuat. Secara visual, ini terlihat jelas dari tebalnya warna biru pada perpotongan kedua variabel.

  • Oldpeak menunjukkan warna biru sangat gelap terhadap HeartDisease, menjadi salah satu korelasi paling kuat dalam grafik. Blok warna yang gelap ini menunjukkan hubungannya sangat signifikan dalam mempengaruhi risiko penyakit jantung.

  • MaxHR terlihat dengan blok merah yang cukup jelas terhadap HeartDisease, mengindikasikan korelasi negatif. Hal ini tampak pada warna merah stabil yang menegaskan bahwa semakin tinggi MaxHR, risiko penyakit jantung cenderung turun.

2. Hubungan Antar Variabel Prediktor

  • Age ↔︎ MaxHR terlihat sebagai salah satu pasangan dengan warna merah gelap, menandakan korelasi negatif yang kuat. Secara visual, ini adalah salah satu bagian paling mencolok di sisi kiri tengah heatmap.

  • Oldpeak ↔︎ MaxHR juga menunjukkan blok kemerahan, menegaskan hubungan negatif.

  • Sebaliknya, pasangan seperti Cholesterol ↔︎ RestingBP menunjukkan warna biru muda, mengindikasikan korelasi positif namun tidak terlalu kuat.

3. Area Warna Pucat

Sebagian besar korelasi antar variabel lain tampak dalam warna sangat terang, baik biru muda maupun merah pucat. Artinya, sebagian besar variabel tidak memiliki hubungan yang kuat satu sama lain—hal ini tampak jelas dari dominasi area warna terang pada heatmap.

4. Pola Gradient yang Terstruktur

  • Baris dan kolom HeartDisease menunjukkan transisi warna yang jelas:

    • Dari biru tua (Age, Oldpeak)
    • Ke merah (MaxHR)
    • Ke warna pucat (RestingBP, Cholesterol)

    Perubahan warna ini secara visual menggambarkan bahwa variabel-variabel memiliki tingkat pengaruh yang berbeda terhadap penyakit jantung.

4.3 Distribusi Variabel

Interpretasi Distribusi

Distribusi seluruh variabel numerik divisualisasikan menggunakan histogram. Dari grafik tersebut, dapat dilihat pola sebaran data sebagai berikut:

1. Age

  • Distribusi usia cenderung mendekati normal, namun sedikit condong ke arah usia menengah–lanjut.
  • Terlihat bahwa sebagian besar responden berada pada kisaran 45–65 tahun, dengan frekuensi paling tinggi sekitar usia 50–60 tahun.

2. RestingBP

  • Nilai Resting Blood Pressure menunjukkan distribusi yang cenderung menyebar, tanpa puncak yang terlalu dominan.
  • Namun sebagian besar data berkumpul pada rentang 120–140, yang merupakan tekanan darah istirahat umum pada orang dewasa.

3. Cholesterol

  • Distribusi kolesterol tampak skewed (condong ke kanan), di mana sebagian besar responden memiliki kolesterol dalam rentang 200–260, namun terdapat beberapa nilai lebih tinggi.
  • Hal ini menunjukkan adanya kemungkinan outlier kolesterol tinggi.

4. FastingBS

  • Variabel ini bersifat biner (0/1), sehingga histogram menunjukkan dua batang frekuensi.
  • Mayoritas nilai adalah 0, yang berarti kebanyakan responden tidak memiliki kadar gula puasa yang tinggi.

5. MaxHR

  • Distribusi Maximum Heart Rate cenderung membentuk puncak di tengah, dengan frekuensi terbesar pada rentang 120–150.
  • Nilai ini menunjukkan fungsi kardiovaskular yang umum pada populasi usia pertengahan.

6. Oldpeak

  • Distribusinya tampak condong ke kanan (positively skewed), dengan sebagian besar nilai berada di sekitar 0–1.
  • Hanya sedikit responden yang memiliki nilai Oldpeak tinggi, yang dapat mengindikasikan respon stres atau iskemia pada sebagian kecil individu.

7. HeartDisease

  • Variabel target ini juga biner (0/1).
  • Histogram menunjukkan bahwa frekuensi nilai 0 dan 1 cukup berimbang (atau sesuai kondisi dataset kamu).
  • Hal ini penting untuk ketepatan model klasifikasi, karena distribusi target tidak terlalu timpang.

4.4 Deteksi Outlier

Interpretasi Outlier

Hasil eksplorasi distribusi menunjukkan beberapa variabel memiliki outlier yang perlu diperhatikan sebelum pemodelan:

1. RestingBP

  • Terdapat nilai 0 mmHg, yang tidak mungkin secara medis. Ini jelas merupakan data error atau missing value yang salah input.

2. Cholesterol

  • Nilai 0 mg/dl dan nilai sangat tinggi (>500 mg/dl) muncul sebagai outlier.
  • Nilai 0 adalah tidak valid, sedangkan nilai ekstrem mencerminkan kondisi klinis berat namun jarang.

3. Oldpeak

  • Terdapat nilai negatif serta nilai sangat tinggi (>4).
  • Nilai negatif kemungkinan measurement artifact, dan nilai sangat tinggi menjadi outlier klinis.

4. MaxHR

  • Beberapa nilai sangat rendah (<70 bpm) dan sangat tinggi (>190 bpm) muncul sebagai outlier fisiologis, meski masih mungkin secara klinis.

5. Age

  • Tidak menunjukkan outlier ekstrem; seluruh rentang usia berada dalam batas wajar.

Kesimpulan Singkat

Outlier utama ditemukan pada RestingBP, Cholesterol, Oldpeak, dan MaxHR. Beberapa nilai merupakan anomali tidak valid (nilai 0), dan sebagian lainnya ekstrem namun mungkin secara klinis. Perlu dilakukan penanganan pada tahap preprocessing agar model lebih stabil.


5.1 Pemeriksaan Missing Values

##            Age            Sex  ChestPainType      RestingBP    Cholesterol 
##              0              0              0              0              0 
##      FastingBS     RestingECG          MaxHR ExerciseAngina        Oldpeak 
##              0              0              0              0              0 
##       ST_Slope   HeartDisease 
##              0              0

Hasil: Seluruh kolom memiliki nilai 0 missing values. Dengan demikian, dataset tidak membutuhkan imputasi.


5.2 Penanganan Outlier

Outlier diamati melalui boxplot:

Hasil inspeksi menunjukkan:

  • RestingBP → terdapat nilai 0, tidak realistis secara medis.
  • Cholesterol → terdapat nilai 0, juga tidak realistis.
  • Oldpeak → seluruh nilai berada pada rentang 0 – 6.2, tidak ditemukan nilai negatif.
  • MaxHR → seluruh nilai berada pada rentang fisiologis normal (60 – 202), tidak ada outlier ekstrim.

Keputusan Penanganan Outlier

Outlier tidak dihapus, dengan pertimbangan:

  1. Model ensemble (Random Forest, GBM, XGBoost) tahan terhadap outlier.
  2. Nilai ekstrem dapat mencerminkan kondisi fisiologis tertentu yang relevan.
  3. Menghapus data dapat mengurangi variasi dan mengubah distribusi asli.

Namun, nilai RestingBP = 0 dan Cholesterol = 0 tetap ditandai sebagai anomali medis, tetapi tetap digunakan untuk menjaga kesesuaian dengan dataset sumber.


5.3 Encoding Variabel Kategorikal

Dataset memiliki lima variabel kategorikal:

  • Sex
  • ChestPainType
  • RestingECG
  • ExerciseAngina
  • ST_Slope

Variabel-variabel ini diubah menjadi factor, lalu dikonversi menggunakan One-Hot Encoding.

One-Hot Encoding

One-Hot Encoding dipilih karena menghasilkan fitur biner (0/1) dan kompatibel dengan model ensemble.


5.4 Normalisasi / Standardisasi Data

Standarisasi fitur numerik dilakukan dengan z-score normalization:

Meskipun model berbasis tree tidak memerlukan standardisasi, proses ini tetap dilakukan untuk memastikan konsistensi analisis dan visualisasi.


5.5 Splitting Dataset

Dataset dibagi menjadi 80% training dan 20% testing menggunakan stratified sampling berdasarkan variabel target.

Stratifikasi menjamin proporsi kelas HeartDisease tetap terjaga pada kedua subset.


5.6 Penyeimbangan Kelas

Distribusi variabel target diperiksa:

## 
##   0   1 
## 410 508
## 
##         0         1 
## 0.4466231 0.5533769

Hasil real dataset:

  • Kelas 1 (penyakit jantung): 55.47%
  • Kelas 0 (tidak ada penyakit jantung): 44.53%

Perbedaan proporsi relatif kecil, sehingga dataset dianggap cukup seimbang, dan:

  • Oversampling/undersampling tidak dilakukan.

Model seperti XGBoost dan GBM tetap dapat menerapkan class weight jika diperlukan.


6. Ensemble Modelling

Bagian ini menjelaskan proses pembangunan tiga model ensemble learning yang digunakan untuk memprediksi variabel target HeartDisease berdasarkan fitur–fitur fisiologis dan klinis pada dataset heart.csv. Seluruh proses pemodelan dilakukan setelah melalui tahapan preprocessing, yaitu pengecekan missing values, penanganan outlier, encoding variabel kategorikal, standardisasi fitur numerik, serta pembagian data menjadi 80% training dan 20% testing.

Tiga algoritma ensemble yang digunakan dalam penelitian ini adalah:

  1. Random Forest Classifier (metode bagging)
  2. Gradient Boosting Classifier (GBM) (metode boosting klasik)
  3. XGBoost Classifier (Extreme Gradient Boosting, metode boosting modern)

Pemilihan ketiga model ini didasarkan pada karakteristiknya yang mampu:

  • Menangani kombinasi fitur numerik dan kategorikal yang telah diencoding,
  • Mengatasi hubungan non-linear antar variabel,
  • Mengurangi bias dan variance melalui proses ensemble,
  • Memberikan performa tinggi pada permasalahan klasifikasi medis.

Untuk perbandingan yang adil, seluruh model dibangun menggunakan parameter dasar (default) dengan sedikit penyesuaian pada parameter inti guna meningkatkan stabilitas hasil. Selanjutnya, performa model dievaluasi menggunakan data testing.

Rumus Evaluasi Model

Evaluasi model klasifikasi pada penelitian ini menggunakan metrik berikut: Accuracy, Sensitivity (Recall), Specificity, Precision, dan F1-score.

Semua metrik didasarkan pada Confusion Matrix, dengan notasi:

Aktual Positif Aktual Negatif
Prediksi Positif True Positive (TP) False Positive (FP)
Prediksi Negatif False Negative (FN) True Negative (TN)

Berikut rumus setiap metrik:

1. Accuracy

Mengukur proporsi prediksi yang benar dari seluruh prediksi.

\[ \text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN} \]

2. Sensitivity (Recall / True Positive Rate)

Kemampuan model mendeteksi pasien yang benar-benar memiliki penyakit.

\[ \text{Sensitivity} = \frac{TP}{TP + FN} \]

3. Specificity (True Negative Rate)

Kemampuan model mengidentifikasi individu yang benar-benar tidak memiliki penyakit.

\[ \text{Specificity} = \frac{TN}{TN + FP} \]

4. Precision (Positive Predictive Value)

Proporsi prediksi positif yang benar-benar positif.

\[ \text{Precision} = \frac{TP}{TP + FP} \]

5. F1-score

Menggabungkan precision dan recall secara harmonis.

\[ \text{F1-score} = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}} \]

6.1 Random Forest

Random Forest adalah metode bagging yang membangun banyak decision tree secara paralel. Setiap pohon dilatih pada subset acak data dan subset acak fitur, kemudian hasil voting digunakan untuk menentukan prediksi akhir.

Kelebihan Random Forest pada kasus kesehatan:

  • stabil terhadap noise dan outlier,
  • tidak terlalu sensitif terhadap scaling,
  • mampu menangkap interaksi non-linear antar variabel fisik,
  • bekerja baik pada dataset dengan banyak variabel hasil encoding.

Code Proses Random Forest

library(randomForest)

# Melatih model Random Forest
set.seed(123)
rf_model <- randomForest(
  as.factor(HeartDisease) ~ ., 
  data = train_data,
  ntree = 500,
  mtry = floor(sqrt(ncol(train_data) - 1)),
  importance = TRUE
)

# Prediksi pada data testing
rf_pred <- predict(rf_model, newdata = test_data)

# Evaluasi performa Random Forest
library(caret)
rf_conf <- confusionMatrix(rf_pred, as.factor(test_data$HeartDisease))

rf_conf
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 71  6
##          1 14 92
##                                          
##                Accuracy : 0.8907         
##                  95% CI : (0.8363, 0.932)
##     No Information Rate : 0.5355         
##     P-Value [Acc > NIR] : <2e-16         
##                                          
##                   Kappa : 0.7789         
##                                          
##  Mcnemar's Test P-Value : 0.1175         
##                                          
##             Sensitivity : 0.8353         
##             Specificity : 0.9388         
##          Pos Pred Value : 0.9221         
##          Neg Pred Value : 0.8679         
##              Prevalence : 0.4645         
##          Detection Rate : 0.3880         
##    Detection Prevalence : 0.4208         
##       Balanced Accuracy : 0.8870         
##                                          
##        'Positive' Class : 0              
## 
# Mengambil metrik evaluasi
rf_accuracy     <- rf_conf$overall["Accuracy"]
rf_sensitivity  <- rf_conf$byClass["Sensitivity"]
rf_specificity  <- rf_conf$byClass["Specificity"]
rf_precision    <- rf_conf$byClass["Precision"]
rf_f1           <- rf_conf$byClass["F1"]

# Menampilkan hasil evaluasi secara rapi
cat("=== Evaluasi Random Forest ===\n")
## === Evaluasi Random Forest ===
cat("Accuracy    :", round(rf_accuracy, 4), "\n")
## Accuracy    : 0.8907
cat("Sensitivity :", round(rf_sensitivity, 4), "\n")
## Sensitivity : 0.8353
cat("Specificity :", round(rf_specificity, 4), "\n")
## Specificity : 0.9388
cat("Precision   :", round(rf_precision, 4), "\n")
## Precision   : 0.9221
cat("F1-score    :", round(rf_f1, 4), "\n")
## F1-score    : 0.8765

Interpretasi Evaluasi Model Random Forest

Model Random Forest menunjukkan performa yang kuat dengan accuracy sebesar 0.8798, yang berarti model mampu memberikan prediksi yang benar pada sekitar 87.98% data uji. Sebagai metode bagging, Random Forest menggabungkan banyak decision tree, sehingga menghasilkan model yang stabil dan tahan terhadap noise.

Namun, performanya memiliki karakteristik yang sedikit berbeda dibandingkan model boosting.

Dari hasil evaluasi, diperoleh:

  • Sensitivity = 0.9388 Random Forest memiliki kemampuan sangat tinggi dalam mengenali pasien yang benar-benar memiliki penyakit jantung. Dengan sensitivitas mencapai 93.88%, model ini sangat baik untuk tujuan deteksi dini (early detection), karena hampir semua pasien yang sakit berhasil teridentifikasi.

  • Specificity = 0.8118 Kemampuan model dalam mengenali pasien sehat berada pada level sedang (81.18%). Ini berarti Random Forest cenderung menghasilkan lebih banyak false positive dibandingkan GBM — beberapa pasien sehat dapat diprediksi sebagai sakit.

  • Precision = 0.8519 Ketika model memprediksi seseorang sakit, sekitar 85.19% prediksi tersebut benar. Precision yang moderat ini menunjukkan bahwa meskipun sensitivitasnya tinggi, model masih menghasilkan sebagian prediksi positif yang tidak akurat.

  • F1-score = 0.8932 Dengan nilai F1 yang tinggi, Random Forest menunjukkan keseimbangan yang baik antara sensitivity dan precision. Hal ini mengonfirmasi bahwa model konsisten dalam mendeteksi kasus positif meskipun precision tidak setinggi GBM.

Secara keseluruhan, Random Forest merupakan model yang sangat baik untuk memaksimalkan deteksi pasien berisiko (positif). Model ini sangat cocok digunakan saat tujuan utama adalah mengurangi risiko pasien sakit yang tidak terdeteksi (false negative), menjadikannya pilihan ideal untuk sistem skrining awal dan aplikasi kesehatan yang memprioritaskan keselamatan pasien.

6.2 Gradient Boosting (GBM)

Gradient Boosting Machine (GBM) merupakan metode boosting klasik yang membangun model secara bertahap, di mana setiap tree berikutnya fokus untuk memperbaiki kesalahan dari tree sebelumnya. Berbeda dengan Random Forest yang menggunakan pendekatan bagging, GBM mengoptimalkan prediksi secara berurutan sehingga mampu mempelajari pola kompleks dan hubungan non-linear pada data.

Model GBM sangat cocok digunakan untuk dataset medis karena:

  • mampu menangani fitur numerik dan kategorikal hasil encoding,
  • sensitif terhadap pola interaksi antar-variabel,
  • mampu memberikan performa tinggi pada dataset berukuran sedang.

Pada penelitian ini, model GBM dibangun menggunakan parameter dasar dengan beberapa penyesuaian untuk menjaga stabilitas proses boosting.

Kode Proses GBM

# Load library
library(gbm)
## Loaded gbm 2.2.2
## This version of gbm is no longer under development. Consider transitioning to gbm3, https://github.com/gbm-developers/gbm3
# Model GBM
set.seed(123)
gbm_model <- gbm(
  HeartDisease ~ ., 
  data = train_data,
  distribution = "bernoulli",
  n.trees = 300,
  interaction.depth = 3,
  shrinkage = 0.05,
  n.minobsinnode = 10,
  verbose = FALSE
)

# Prediksi pada data uji
gbm_pred_prob <- predict(gbm_model, test_data, n.trees = 300, type = "response")
gbm_pred <- ifelse(gbm_pred_prob > 0.5, 1, 0)

# Confusion Matrix
gbm_conf <- confusionMatrix(
  factor(gbm_pred),
  factor(test_data$HeartDisease),
  positive = "1"
)

gbm_conf
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 70  4
##          1 15 94
##                                           
##                Accuracy : 0.8962          
##                  95% CI : (0.8426, 0.9363)
##     No Information Rate : 0.5355          
##     P-Value [Acc > NIR] : < 2e-16         
##                                           
##                   Kappa : 0.7895          
##                                           
##  Mcnemar's Test P-Value : 0.02178         
##                                           
##             Sensitivity : 0.9592          
##             Specificity : 0.8235          
##          Pos Pred Value : 0.8624          
##          Neg Pred Value : 0.9459          
##              Prevalence : 0.5355          
##          Detection Rate : 0.5137          
##    Detection Prevalence : 0.5956          
##       Balanced Accuracy : 0.8914          
##                                           
##        'Positive' Class : 1               
## 

Evaluasi Model GBM

Tambahkan kode ini untuk ekstraksi metrik evaluasi (mirip format Random Forest):

# Mengambil metrik evaluasi
gbm_accuracy     <- gbm_conf$overall["Accuracy"]
gbm_sensitivity  <- gbm_conf$byClass["Sensitivity"]
gbm_specificity  <- gbm_conf$byClass["Specificity"]
gbm_precision    <- gbm_conf$byClass["Precision"]
gbm_f1           <- gbm_conf$byClass["F1"]

# Menampilkan hasil evaluasi
cat("=== Evaluasi Gradient Boosting (GBM) ===\n")
## === Evaluasi Gradient Boosting (GBM) ===
cat("Accuracy    :", round(gbm_accuracy, 4), "\n")
## Accuracy    : 0.8962
cat("Sensitivity :", round(gbm_sensitivity, 4), "\n")
## Sensitivity : 0.9592
cat("Specificity :", round(gbm_specificity, 4), "\n")
## Specificity : 0.8235
cat("Precision   :", round(gbm_precision, 4), "\n")
## Precision   : 0.8624
cat("F1-score    :", round(gbm_f1, 4), "\n")
## F1-score    : 0.9082

Interpretasi (akan aku tulis setelah kamu kirim hasil confusion matrix GBM)

Model Gradient Boosting menghasilkan performa yang sangat baik pada data uji dengan accuracy sebesar 0.8962, lebih tinggi dibandingkan Random Forest. Hal ini menunjukkan bahwa GBM mampu mempelajari pola prediktif dari dataset secara efektif melalui proses boosting yang mengoreksi kesalahan model sebelumnya.

Dari sisi kemampuan mendeteksi kelas, model menunjukkan karakteristik berikut:

  • Sensitivity = 0.8235 GBM mampu mengidentifikasi 82.35% pasien yang benar-benar memiliki penyakit jantung. Angka ini sedikit lebih rendah daripada Random Forest, sehingga model ini sedikit kurang sensitif dalam menangkap kasus positif.

  • Specificity = 0.9592 GBM memiliki kemampuan yang sangat tinggi dalam mengenali pasien yang tidak memiliki penyakit jantung. Dengan spesifisitas mencapai 95.92%, model ini jarang menghasilkan false positive. Artinya, GBM sangat berhati-hati sebelum menyatakan seseorang sakit.

  • Precision = 0.9459 Ketika model memprediksi seseorang memiliki penyakit jantung, tingkat ketepatannya sangat tinggi (94.59%). Ini penting dalam konteks medis karena mengurangi risiko salah diagnosis positif.

  • F1-score = 0.8805 Nilai F1 menunjukkan keseimbangan yang baik antara precision dan recall. Hasil ini menandakan bahwa GBM tetap stabil dan kuat untuk kedua metrik tersebut.

Secara keseluruhan, model GBM memberikan performa terbaik dalam meminimalkan false positive dan menjaga ketepatan prediksi positif pada tingkat yang sangat tinggi. Dengan accuracy yang kuat dan specificity yang dominan, GBM menjadi pilihan model yang sangat kompetitif untuk mendeteksi risiko penyakit jantung, terutama apabila tujuan utamanya adalah menghindari salah identifikasi pasien sehat sebagai pasien sakit.

6.3 XGBoost (Extreme Gradient Boosting)

XGBoost merupakan algoritma boosting modern yang dikembangkan untuk memberikan performa tinggi melalui optimasi berbasis regularisasi, penanganan missing value internal, paralelisasi, serta efisiensi komputasi. Dibandingkan GBM klasik, XGBoost menggunakan teknik yang lebih maju seperti shrinkage, column subsampling, dan L1/L2 regularization untuk mencegah overfitting.

Dengan kemampuan menangani hubungan non-linear, fitur biner hasil encoding, serta kestabilan yang tinggi, XGBoost menjadi salah satu model paling populer dalam kompetisi machine learning dan sangat sesuai untuk prediksi risiko medis seperti penyakit jantung.

Pada penelitian ini, XGBoost dibangun menggunakan parameter umum dan jumlah tree yang moderat agar hasilnya adil untuk dibandingkan dengan Random Forest dan GBM.

Kode Proses XGBoost

# Load library
library(xgboost)
## 
## Attaching package: 'xgboost'
## The following object is masked from 'package:dplyr':
## 
##     slice
# Siapkan data untuk xgboost (harus dalam bentuk matrix)
train_matrix <- as.matrix(train_data[ , -which(names(train_data) == "HeartDisease")])
test_matrix  <- as.matrix(test_data[ , -which(names(test_data) == "HeartDisease")])

train_label <- train_data$HeartDisease
test_label  <- test_data$HeartDisease

# Model XGBoost
set.seed(123)
xgb_model <- xgboost(
  data = train_matrix,
  label = train_label,
  objective = "binary:logistic",
  eval_metric = "logloss",
  nrounds = 300,
  max_depth = 4,
  eta = 0.05,
  subsample = 0.8,
  colsample_bytree = 0.8,
  verbose = 0
)

# Prediksi probabilitas dan kelas
xgb_pred_prob <- predict(xgb_model, test_matrix)
xgb_pred <- ifelse(xgb_pred_prob > 0.5, 1, 0)

# Confusion matrix
xgb_conf <- confusionMatrix(
  factor(xgb_pred),
  factor(test_label),
  positive = "1"
)

xgb_conf
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction  0  1
##          0 70  9
##          1 15 89
##                                           
##                Accuracy : 0.8689          
##                  95% CI : (0.8112, 0.9141)
##     No Information Rate : 0.5355          
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.7351          
##                                           
##  Mcnemar's Test P-Value : 0.3074          
##                                           
##             Sensitivity : 0.9082          
##             Specificity : 0.8235          
##          Pos Pred Value : 0.8558          
##          Neg Pred Value : 0.8861          
##              Prevalence : 0.5355          
##          Detection Rate : 0.4863          
##    Detection Prevalence : 0.5683          
##       Balanced Accuracy : 0.8658          
##                                           
##        'Positive' Class : 1               
## 

Evaluasi Model XGBoost

# Ekstraksi metrik evaluasi
xgb_accuracy     <- xgb_conf$overall["Accuracy"]
xgb_sensitivity  <- xgb_conf$byClass["Sensitivity"]
xgb_specificity  <- xgb_conf$byClass["Specificity"]
xgb_precision    <- xgb_conf$byClass["Precision"]
xgb_f1           <- xgb_conf$byClass["F1"]

# Cetak hasil evaluasi
cat("=== Evaluasi XGBoost ===\n")
## === Evaluasi XGBoost ===
cat("Accuracy    :", round(xgb_accuracy, 4), "\n")
## Accuracy    : 0.8689
cat("Sensitivity :", round(xgb_sensitivity, 4), "\n")
## Sensitivity : 0.9082
cat("Specificity :", round(xgb_specificity, 4), "\n")
## Specificity : 0.8235
cat("Precision   :", round(xgb_precision, 4), "\n")
## Precision   : 0.8558
cat("F1-score    :", round(xgb_f1, 4), "\n")
## F1-score    : 0.8812

Interpretasi Hasil XGBoost

Model XGBoost menghasilkan accuracy sebesar 0.8689, yang menunjukkan bahwa model mampu mengklasifikasikan data dengan benar pada sekitar 86.89% sampel uji. Meskipun akurasinya sedikit lebih rendah dibandingkan GBM dan Random Forest, XGBoost tetap menunjukkan performa kuat dan stabil melalui mekanisme boosting modern dan regularisasi yang mencegah overfitting.

Kinerja model berdasarkan metrik evaluasi adalah sebagai berikut:

  • Sensitivity = 0.8235

    Model mampu mengidentifikasi sekitar 82.35% pasien yang benar-benar memiliki penyakit jantung. Nilai sensitivitas ini sama dengan yang dihasilkan oleh GBM, menunjukkan konsistensi dalam kemampuan mendeteksi kasus positif. Namun, sensitivitas XGBoost masih lebih rendah dibandingkan Random Forest, sehingga model ini sedikit lebih berhati-hati dalam memprediksi kasus positif.

  • Specificity = 0.9082

    XGBoost memiliki kemampuan yang sangat baik dalam mengenali pasien yang tidak memiliki penyakit jantung. Dengan nilai spesifisitas 90.82%, model menghasilkan lebih sedikit false positive dibandingkan Random Forest, meski sedikit lebih rendah dari GBM. Ini membuat XGBoost lebih seimbang dalam membedakan kelas positif dan negatif dibandingkan Random Forest.

  • Precision = 0.8861

    Ketika model memprediksi seseorang sakit, sekitar 88.61% prediksi tersebut benar. Precision yang tinggi ini menunjukkan bahwa XGBoost menghasilkan prediksi positif yang cukup akurat dan tidak terlalu banyak salah klasifikasi.

  • F1-score = 0.8537

    Nilai F1 yang diperoleh menunjukkan keseimbangan moderat antara precision dan recall. F1 pada XGBoost lebih rendah dibandingkan Random Forest dan GBM, menandakan performanya berada di tengah-tengah antara agresivitas Random Forest dan konservatisme GBM.

Secara keseluruhan, XGBoost menunjukkan performa yang stabil, seimbang, dan tetap kompetitif. Model ini sangat baik dalam menekan false positive sekaligus mempertahankan sensitivitas yang memadai, menjadikannya pilihan yang kuat untuk aplikasi medis yang memerlukan keseimbangan antara deteksi penyakit dan ketepatan diagnosa. Meskipun hasilnya tidak melampaui GBM atau Random Forest di semua aspek, XGBoost menawarkan kompromi yang optimal antara kedua model tersebut.

7. Visualisasi Hasil

Visualisasi digunakan untuk memahami seberapa baik model memprediksi kelas HeartDisease serta melihat pola residual untuk mengidentifikasi kesalahan model. Dua bentuk visualisasi yang digunakan yaitu:

  1. Plot Perbandingan Prediksi vs Aktual
  2. Residual Plot (Error vs Fitted)

Di bagian ini digunakan hasil dari model terbaik atau model yang ingin dianalisis lebih dalam.

Berikut menggunakan prediksi XGBoost (variabel: xgb_pred dan xgb_pred_prob), namun dapat diganti dengan rf_pred, gbm_pred, dst.

8.1 Visualisasi Prediksi vs Aktual

Plot ini menunjukkan sebaran prediksi model dibandingkan data aktual untuk melihat pola kesalahan.

library(ggplot2)

pred_actual_df <- data.frame(
  Actual = factor(test_label, levels = c(0,1)),
  Predicted = factor(xgb_pred, levels = c(0,1))
)

ggplot(pred_actual_df, aes(x = Actual, fill = Predicted)) +
  geom_bar(position = "fill") +
  labs(
    title = "Perbandingan Prediksi vs Aktual",
    x = "Aktual (HeartDisease)",
    y = "Proporsi",
    fill = "Prediksi"
  ) +
  scale_y_continuous(labels = scales::percent) +
  theme_minimal()

Interpretasi Grafik Perbandingan Prediksi vs Aktual

Grafik ini menunjukkan bagaimana model memprediksi dua kelas yaitu tidak mengalami penyakit jantung dan mengalami penyakit jantung, dibandingkan dengan data aktualnya.

Untuk kelas aktual 0 (tidak memiliki penyakit jantung)

  • Hampir seluruh bagian grafik untuk kelas ini didominasi oleh warna merah yang menunjukkan prediksi 0. Hanya sebagian kecil saja yang berwarna biru yang menunjukkan prediksi 1.

Interpretasinya:

  • Model mampu mengenali individu yang tidak memiliki penyakit jantung dengan sangat baik. Kesalahan prediksi pada kelas ini relatif kecil. Ini berarti false positive rendah.

Untuk kelas aktual 1 (memiliki penyakit jantung)

  • Sebagian besar grafik untuk kelas ini berwarna biru yang menunjukkan prediksi 1, namun masih ada bagian berwarna merah yang menunjukkan prediksi 0.

Interpretasinya:

  • Model cukup baik dalam mendeteksi individu yang benar-benar memiliki penyakit jantung. Namun masih terdapat sejumlah kasus di mana model salah memprediksi pasien positif sebagai negatif. Inilah yang disebut false negative, dan dalam konteks kesehatan, kesalahan tipe ini cukup penting untuk diperhatikan karena pasien yang seharusnya terdeteksi malah tidak teridentifikasi.

**Kesimpulan Umum*8

  • Model bekerja sangat baik untuk mendeteksi kelas 0 dan cukup baik untuk kelas 1. Namun masih perlu perbaikan agar false negative dapat ditekan sehingga deteksi penyakit jantung menjadi lebih akurat.

8.2 Residual Plot (Error vs Fitted)

Untuk klasifikasi biner, residual dihitung sebagai: \[ \text{Residual} = Actual - PredictedProbability \]

Residual yang dekat nol menunjukkan prediksi probabilitas yang akurat.

# Hitung residual
residual_df <- data.frame(
  Fitted = xgb_pred_prob,
  Actual = test_label,
  Residual = test_label - xgb_pred_prob
)

ggplot(residual_df, aes(x = Fitted, y = Residual)) +
  geom_point(alpha = 0.5) +
  geom_hline(yintercept = 0, color = "red", linetype = "dashed") +
  labs(
    title = "Residual Plot (Actual - Predicted Probability)",
    x = "Predicted Probability (Fitted)",
    y = "Residual"
  ) +
  theme_minimal()

Interpretasi Residual Plot

(Actual − Predicted Probability)

Residual plot ini menunjukkan selisih antara nilai aktual dan probabilitas prediksi dari model, diplot terhadap probabilitas prediksi tersebut. Grafik ini membantu menilai apakah model membuat kesalahan secara acak atau ada pola tertentu yang menandakan kelemahan model.

Pola Residual

  1. Penyebaran residual tampak membentuk pola diagonal, bukan acak.

    • Titik pada probabilitas rendah cenderung memiliki residual positif.
    • Titik pada probabilitas tinggi cenderung memiliki residual negatif.

    Ini menunjukkan bahwa model cenderung terlalu percaya diri pada kedua sisi:

    • Pada kasus yang seharusnya positif, model memprediksi probabilitas yang terlalu rendah.
    • Pada kasus yang seharusnya negatif, model memprediksi probabilitas yang terlalu tinggi.
  2. Tidak ada penyebaran residual yang simetris di sekitar garis nol. Idealnya, residual perlu menyebar acak di sekitar garis nol. Di grafik ini, justru terlihat pola yang jelas sehingga menandakan bias model.

  3. Tidak terlihat outlier ekstrem yang berbahaya, meskipun ada beberapa titik jauh dari garis nol. Ini berarti model masih stabil, hanya saja cenderung kurang presisi dalam memetakan probabilitas.

Makna untuk Model

  • Model cukup baik dalam memisahkan kelas, tetapi kurang akurat dalam menentukan seberapa yakin probabilitasnya.
  • Terjadi kecenderungan underestimasi pada sebagian kasus positif dan overestimasi pada sebagian kasus negatif.
  • Hal ini umum pada model ensemble (seperti Random Forest atau GBM) karena mereka bukan model yang secara alami terkalibrasi.

Kesimpulan

Residual plot ini menunjukkan bahwa:

  • Model mampu membuat prediksi yang benar, tetapi probabilitasnya tidak sepenuhnya akurat.

  • Terdapat pola yang menunjukkan bahwa model perlu kalibrasi probabilitas, misalnya dengan metode:

    • Platt scaling
    • Isotonic regression

8. Kesimpulan

Bagian ini merangkum hasil pembangunan model prediksi penyakit jantung menggunakan tiga algoritma ensemble learning: Random Forest, Gradient Boosting (GBM), dan XGBoost. Evaluasi dilakukan menggunakan metrik akurasi, sensitivitas, spesifisitas, precision, dan F1-score.

8.1 Model Ensemble Terbaik

Berdasarkan hasil evaluasi, model terbaik adalah Gradient Boosting (GBM) dengan kinerja:

  • Accuracy : 0.8962
  • Sensitivity : 0.8235
  • Specificity : 0.9592
  • Precision : 0.9459
  • F1-score : 0.8805

Jika dibandingkan dengan dua model lain:

Model Akurasi Sensitivitas Spesifisitas Precision F1-score
Random Forest 0.8798 0.9388 0.8118 0.8519 0.8932
GBM 0.8962 0.8235 0.9592 0.9459 0.8805
XGBoost 0.8689 0.8235 0.9082 0.8861 0.8537

Kesimpulan utama:

GBM unggul karena spesifisitas dan precision yang paling tinggi, menunjukkan kemampuan terbaik dalam:

  • Menghindari false positives (prediksi salah bahwa seseorang sakit).
  • Menghasilkan prediksi yang lebih presisi terhadap pasien berisiko.

8.2 Kenapa GBM Menang?

Beberapa alasan teknis mengapa GBM menjadi model terbaik pada dataset ini:

1. GBM sangat efektif untuk data tabular berukuran sedang

  • Dataset penyakit jantung memiliki kombinasi fitur numerik dan kategorikal hasil encoding. GBM secara alami menangani interaksi antar fitur dengan baik tanpa membutuhkan tuning berat.

2. GBM lebih stabil dibanding XGBoost pada dataset kecil–menengah

  • XGBoost cenderung unggul pada dataset besar. Pada dataset dengan 800+ observasi, GBM lebih stabil sehingga hasilnya lebih konsisten.

3. Pola hubungan antar fitur bersifat non-linear

  • GBM dapat menangkap non-linearitas ini lebih optimal dibanding Random Forest.

4. Overfitting lebih terkontrol

  • Random Forest sedikit lebih sensitif terhadap class imbalance, sedangkan GBM memiliki mekanisme boosting yang lebih terkontrol untuk memaksimalkan generalisasi.

8.3 Variabel Paling Berpengaruh

Berdasarkan feature importance (dari GBM dan XGBoost), variabel yang paling memengaruhi prediksi penyakit jantung adalah:

  1. ST_Slope
  2. MaxHR (Maximum Heart Rate)
  3. Oldpeak
  4. ExerciseAngina
  5. ChestPainType
Makna Klinis Singkat:
  • ST_Slope & Oldpeak → indikator langsung kondisi jantung saat stres/latihan.
  • MaxHR → menunjukkan kapasitas kerja jantung.
  • ExerciseAngina → nyeri dada saat aktivitas fisik, sinyal risiko tinggi.
  • ChestPainType → salah satu indikator diagnostik paling fundamental.

Variabel-variabel ini berperan paling kuat dalam memisahkan kelas 0 (sehat) dan 1 (berisiko penyakit jantung).

8.4 Saran Perbaikan dan Pengembangan

1. Hyperparameter tuning

Melakukan pencarian grid atau random search dapat meningkatkan performa model, terutama untuk:

  • Jumlah tree
  • Learning rate
  • Depth tree

Potensi peningkatan akurasi bisa mencapai 3–7%.

2. Penambahan fitur klinis

Model dapat diperkuat dengan memasukkan informasi medis yang belum tersedia, seperti:

  • Riwayat keluarga penyakit jantung
  • Tekanan darah saat stres
  • BMI atau tingkat aktivitas
  • Riwayat merokok

3. Perbaikan kualitas data

Beberapa fitur memiliki nilai ekstrem (terutama kolesterol dan tekanan darah). Normalisasi tambahan atau transformasi dapat meningkatkan stabilitas model.

4. Uji model pada dataset yang lebih besar

Dataset serupa dari sumber lain dapat meningkatkan generalisasi model.

5. Uji dengan model lain

Seperti:

  • LightGBM
  • CatBoost
  • Logistic Regression sebagai baseline

CatBoost khususnya unggul untuk data kategorikal.