Kanker payudara merupakan salah satu jenis kanker yang paling banyak diderita oleh perempuan di dunia. Keberhasilan penanganannya sangat bergantung pada deteksi dini dan ketepatan diagnosis, yaitu membedakan tumor jinak (benign) dan tumor ganas (malignant). Salah satu cara yang lazim digunakan adalah pemeriksaan sitologi jaringan payudara melalui biopsi jarum halus, yang menghasilkan karakteristik sel seperti ketebalan gumpalan sel, keseragaman ukuran dan bentuk sel, serta jumlah inti sel yang terlihat. Karakteristik tersebut dapat dimanfaatkan sebagai variabel prediktor untuk mengklasifikasikan kondisi kanker payudara melalui pendekatan machine learning (Wolberg & Mangasarian, 1990).
Decision Tree merupakan salah satu metode supervised learning berbasis pohon yang membentuk aturan prediksi dengan membagi data secara bertahap melalui proses splitting sehingga kelompok data yang terbentuk semakin homogen. Salah satu algoritma yang banyak digunakan adalah Classification and Regression Tree (CART); apabila variabel respons berupa kategori, pohon yang terbentuk disebut pohon klasifikasi (Classification Tree) (Breiman et al., 1984). Keunggulan metode ini adalah hasilnya mudah divisualisasikan dan diinterpretasikan sebagai aturan keputusan, serta dapat memakai variabel prediktor numerik maupun kategorik. Namun, pohon yang terlalu besar cenderung mengalami overfitting sehingga perlu dipangkas (pruning) berdasarkan parameter kompleksitas (complexity parameter, CP). Kinerja klasifikasi dievaluasi menggunakan confusion matrix beserta ukuran turunannya, serta kurva ROC (Receiver Operating Characteristic) dan nilai AUC (Area Under the Curve). Pada konteks medis, ukuran seperti sensitivitas menjadi penting karena kesalahan memprediksi tumor ganas sebagai jinak berdampak serius (James et al., 2013).
Pada praktikum ini digunakan dataset BreastCancer dari
package mlbench untuk mengklasifikasikan variabel
Class (benign atau malignant) menggunakan
Classification Tree dengan algoritma CART. Dataset ini memiliki
missing value pada salah satu variabel prediktornya, sehingga
ditangani dengan imputasi menggunakan package
mice, dan kolom Id dihapus karena hanya berupa
nomor identitas pasien. Tahapan yang dilakukan meliputi pengecekan dan
penanganan missing value, pembagian data latih dan data uji,
pembentukan dan visualisasi pohon, analisis variable
importance, prediksi dan evaluasi dengan confusion matrix,
penentuan CP terbaik, pruning, serta evaluasi ulang model
menggunakan confusion matrix, ROC, dan AUC.
BreastCancer, terutama
terkait missing value dan keseimbangan kelas pada variabel
Class, serta bagaimana penanganannya menggunakan
mice?BreastCancer serta
menangani missing value menggunakan mice.Adapun manfaat pada penelitian ini yaitu:
Bagi penulis
mice, pembentukan dan pruning pohon
klasifikasi, serta evaluasi model dengan RStudio.Bagi pembaca
Menambah ilmu pengetahuan dan pemahaman yang berkaitan dengan Decision Tree (Classification Tree) dan penerapannya dengan RStudio.
Adapun batasan masalah pada praktikum ini yaitu Gunakan dataset BreastCancer dari package mlbench untuk mengklasifikasikan kondisi kanker payudara menggunakan Decision Tree (Classification Tree). Lakukan pengecekan dan penanganan missing value menggunakan mice, kemudian bagi data menjadi training dan testing. Selanjutnya, bangun dan visualisasikan tree, analisis variable importance, lakukan prediksi dan evaluasi menggunakan confusion matrix, tentukan CP terbaik, lakukan pruning, dan evaluasi kembali model menggunakan confusion matrix, ROC, dan AUC, dan kolom ID dihapus.
Adapun sistematika penulisan dari praktikum ini adalah sebagai berikut.
BAB IPENDAHULUAN
Bab ini terdiri dari latar belakang, rumusan masalah, tujuan penelitian, manfaat penelitian, batasan masalah, dan sistematika penulisan.
BAB IITINJAUAN PUSTAKA
Bab ini berisi kajian pustaka yang terdiri dari jurnal, buku, dan
informasi pendukung mengenai Decision Tree, CART
(Classification Tree), pruning dan complexity
parameter, evaluasi model (confusion matrix, ROC, dan
AUC), serta penanganan missing value dengan mice
pada program RStudio.
BAB IIIMETODE PENELITIAN
Bab ini terdiri dari jenis dan sumber data, variabel penelitian, algoritma penelitian, dan diagram alir.
BAB IVHASIL DAN PEMBAHASAN
Bab ini berisi hasil yang diperoleh dari analisis data beserta penjelasannya pada bagian pembahasan.
BAB VKESIMPULAN
Bab ini merupakan bagian penutup laporan yang berisi kesimpulan dari hasil analisis serta saran dari penulis.
DAFTAR PUSTAKA
Decision Tree merupakan salah satu metode supervised learning berbasis pohon yang dapat digunakan untuk membentuk aturan prediksi. Data dibagi secara bertahap melalui proses splitting berdasarkan variabel prediktor sehingga terbentuk kelompok-kelompok data yang semakin homogen. Setiap percabangan menunjukkan aturan pemisahan, sedangkan simpul akhir (leaf node) menunjukkan hasil prediksi. Classification and Regression Tree (CART) dapat digunakan untuk dua jenis pemodelan: klasifikasi untuk memprediksi kategori atau kelas, dan regresi untuk memprediksi nilai numerik. Jika variabel respons berupa kategori, pohon yang terbentuk disebut pohon klasifikasi (Classification Tree); jika variabel respons berupa numerik kontinu, disebut pohon regresi (Regression Tree).
Decision Tree memiliki beberapa karakteristik, yaitu:
Sebuah Decision Tree tersusun atas beberapa komponen utama sebagai berikut:
| Komponen | Keterangan |
|---|---|
| Root node | Simpul awal atau simpul paling atas yang memuat seluruh data sebelum dilakukan pemisahan |
| Intermediate node | Simpul di antara root node dan leaf node yang masih dapat mengalami pemisahan |
| Leaf node | Simpul akhir yang menunjukkan hasil prediksi. Pada klasifikasi berupa kelas, sedangkan pada regresi berupa nilai numerik |
| Branch | Cabang yang menghubungkan satu simpul dengan simpul lainnya berdasarkan aturan tertentu |
| Attribute | Variabel prediktor yang digunakan sebagai dasar untuk melakukan pemisahan data |
| Splitting criteria | Kriteria yang digunakan untuk menentukan pemisahan terbaik. Pada klasifikasi dapat menggunakan Gini Index atau Entropy, sedangkan pada regresi dapat menggunakan ukuran kesalahan seperti MSE |
| Decision rules | Aturan keputusan yang terbentuk dari jalur percabangan dan digunakan untuk menghasilkan prediksi |
| Pruning | Proses pemangkasan cabang yang kurang penting untuk menyederhanakan pohon dan mengurangi risiko overfitting |
Pada Classification Tree, proses pemisahan data dilakukan dengan memilih aturan yang mampu menghasilkan simpul-simpul yang semakin homogen. Beberapa ukuran yang digunakan antara lain Entropy, Information Gain, dan Gini Index. Entropy mengukur tingkat ketidakpastian atau ketidakmurnian kelas dalam suatu simpul. Semakin kecil nilai Entropy, semakin homogen simpul tersebut:
\[ Entropy(t) = -\sum_{k=1}^{K} p_k \log_2(p_k) \]
dengan \(t\) adalah simpul, \(k\) adalah indeks kelas ke-\(k\) (\(k = 1,2,\ldots,K\)), dan \(p_k\) adalah proporsi observasi kelas ke-\(k\) dalam simpul. Pada data dua kelas (Ya dan Tidak) dengan proporsi \(p_1\) dan \(p_2\) (\(p_1 + p_2 = 1\)), maka \(E(D) = -p_1 \log_2 p_1 - p_2 \log_2 p_2\). Jika seluruh amatan dalam simpul berasal dari satu kelas yang sama, Entropy bernilai 0, sedangkan nilainya semakin besar apabila proporsi kelas semakin seimbang.
Information Gain mengukur seberapa besar Entropy berkurang setelah dilakukan suatu split. Jika dataset \(D\) dipartisi menjadi \(D_1, D_2, \ldots, D_J\), maka:
\[ IG = E(D) - \sum_{j=1}^{J} \frac{|D_j|}{|D|}\,E(D_j) \]
dengan \(E(D)\) adalah Entropy sebelum split, \(E(D_j)\) adalah Entropy bagian ke-\(j\), \(|D_j|\) adalah banyaknya amatan bagian ke-\(j\), dan \(|D|\) adalah banyaknya seluruh amatan. Semakin besar Information Gain, semakin baik split yang dilakukan.
Gini Index mengukur ketidakmurnian kelas (Gini impurity) dalam suatu simpul. Semakin kecil nilainya, semakin homogen simpul tersebut:
\[ Gini(t) = 1 - \sum_{k=1}^{K} p_k^2 \]
Jika \(D\) dipartisi menjadi dua bagian \(D_1\) dan \(D_2\), nilai Gini setelah pemisahan dihitung dengan rata-rata terbobot:
\[ Gini_{split} = \frac{|D_1|}{|D|}\,Gini(D_1) + \frac{|D_2|}{|D|}\,Gini(D_2) \]
Fungsi rpart pada R menggunakan Gini Index
sebagai kriteria pemisahan bawaan untuk pohon klasifikasi (Therneau
& Atkinson, 2019). Prediksi untuk observasi baru adalah kelas
mayoritas pada leaf tempat observasi tersebut jatuh.
Pohon yang terlalu besar akan menyesuaikan diri secara berlebihan dengan data latih (overfitting), sedangkan pohon yang terlalu kecil kurang mampu menangkap pola data (underfitting). Metode cost complexity pruning menyeimbangkan keduanya dengan meminimalkan:
\[ R_{\alpha}(T) = R(T) + \alpha\,|T| \]
dengan \(R(T)\) adalah galat
klasifikasi pohon \(T\) pada data
latih, \(|T|\) adalah banyaknya
leaf, dan \(\alpha \geq 0\)
adalah penalti kompleksitas. Pada rpart, penalti ini
dinyatakan secara relatif sebagai complexity
parameter (CP): sebuah split hanya dipertahankan
jika menurunkan galat relatif setidaknya sebesar CP. CP terbaik dipilih
berdasarkan galat cross-validation (xerror) yang
paling kecil, kemudian pohon dipangkas dengan fungsi
prune() (Therneau & Atkinson, 2019).
Variable importance pada rpart
dihitung dari total penurunan ketidakmurnian (impurity) yang
diberikan suatu variabel, baik ketika menjadi pemisah utama (primary
split) maupun sebagai pemisah pengganti (surrogate split).
Semakin besar nilainya, semakin berperan variabel tersebut dalam
memisahkan kelas.
Evaluasi Classification Tree dilakukan dengan membandingkan kelas aktual dan kelas hasil prediksi, yang disajikan dalam confusion matrix:
| Predicted Positive | Predicted Negative | |
|---|---|---|
| Actual Positive | True Positive (TP) | False Negative (FN) |
| Actual Negative | False Positive (FP) | True Negative (TN) |
Berdasarkan confusion matrix, ukuran evaluasi yang digunakan adalah:
\[ Accuracy = \frac{TP+TN}{TP+TN+FP+FN} \qquad Precision = \frac{TP}{TP+FP} \qquad Recall = \frac{TP}{TP+FN} \]
\[ Specificity = \frac{TN}{TN+FP} \qquad F1\text{-}Score = 2\left(\frac{Precision \times Recall}{Precision + Recall}\right) \]
Recall (sensitivitas) menunjukkan kemampuan model mendeteksi kelas positif, sedangkan specificity menunjukkan kemampuan mendeteksi kelas negatif. Pada kasus ini, kelas positif adalah malignant, sehingga recall yang tinggi berarti sedikit tumor ganas yang terlewat (false negative).
ROC (Receiver Operating Characteristic) adalah kurva yang menggambarkan hubungan antara True Positive Rate (TPR = Recall) pada sumbu-y dan False Positive Rate (FPR = 1 − Specificity) pada sumbu-x untuk berbagai nilai ambang (threshold) probabilitas. AUC (Area Under the Curve) adalah luas di bawah kurva ROC dengan rentang 0 sampai 1. Nilai AUC 0,5 setara dengan tebakan acak, sedangkan nilai mendekati 1 menunjukkan kemampuan model membedakan kedua kelas yang sangat baik (Fawcett, 2006). Secara interpretasi, AUC adalah peluang model memberi skor lebih tinggi pada observasi positif yang dipilih acak dibandingkan observasi negatif yang dipilih acak.
Missing value adalah kondisi ketika suatu observasi tidak
memiliki nilai pada variabel tertentu. Menurut mekanismenya, data hilang
dapat bersifat Missing Completely At Random (MCAR), Missing
At Random (MAR), atau Missing Not At Random (MNAR) (Little
& Rubin, 2002). Menghapus baris yang mengandung NA
mengurangi ukuran sampel dan dapat menimbulkan bias, sehingga imputasi
sering lebih dipilih.
MICE (Multivariate Imputation by
Chained Equations) adalah metode multiple imputation yang
mengisi nilai hilang secara berulang variabel demi variabel: setiap
variabel yang memiliki NA dimodelkan menggunakan variabel
lain sebagai prediktor, lalu nilai hilangnya diisi berdasarkan model
tersebut, dan proses ini diulang sampai stabil (van Buuren &
Groothuis-Oudshoorn, 2011). Proses ini menghasilkan \(m\) dataset lengkap yang berbeda sehingga
ketidakpastian akibat imputasi dapat dipertimbangkan.
Salah satu metode imputasi pada mice adalah
Predictive Mean Matching (PMM). Pada PMM,
dibangun model regresi dari data yang teramati, kemudian untuk setiap
nilai hilang dicari beberapa observasi donor yang nilai prediksinya
paling dekat, dan salah satu nilai asli donor diambil secara acak
sebagai pengisi. Karena nilai pengisi selalu berasal dari nilai yang
benar-benar teramati, PMM menjaga agar hasil imputasi tetap berada dalam
rentang dan bentuk sebaran data asli (misalnya tetap berupa bilangan
bulat 1 sampai 10).
Data yang digunakan adalah dataset BreastCancer dari
package mlbench, yang berasal dari Wisconsin
Breast Cancer Database hasil pemeriksaan sitologi biopsi jarum
halus pada jaringan payudara. Dataset ini terdiri dari 699 observasi dan
11 variabel (satu di antaranya, Id, dihapus pada analisis
sehingga tersisa 10 variabel).
| Variabel | Jenis | Keterangan |
|---|---|---|
Class |
Kategorik biner (target) | Kondisi tumor: benign (jinak) atau malignant (ganas) |
Cl.thickness |
Ordinal (skala 1–10) | Ketebalan gumpalan sel (clump thickness) |
Cell.size |
Ordinal (skala 1–10) | Keseragaman ukuran sel |
Cell.shape |
Ordinal (skala 1–10) | Keseragaman bentuk sel |
Marg.adhesion |
Ordinal (skala 1–10) | Perlekatan pada tepi sel (marginal adhesion) |
Epith.c.size |
Ordinal (skala 1–10) | Ukuran sel epitel tunggal |
Bare.nuclei |
Ordinal (skala 1–10) | Inti sel yang tidak terbungkus sitoplasma (memiliki missing value) |
Bl.cromatin |
Ordinal (skala 1–10) | Kehalusan kromatin (bland chromatin) |
Normal.nucleoli |
Ordinal (skala 1–10) | Kondisi anak inti sel normal (normal nucleoli) |
Mitoses |
Ordinal (skala 1–10) | Tingkat pembelahan sel (mitoses) |
Id |
Identitas | Nomor identitas sampel (dihapus, tidak dipakai sebagai prediktor) |
Algoritma CART membentuk pohon melalui tiga tahap yang diulang pada setiap simpul yang terbentuk:
Proses pemisahan berhenti apabila salah satu kondisi berikut tercapai: (1) simpul sudah cukup homogen terhadap variabel respons, (2) nilai variabel prediktor pada simpul tidak memungkinkan pemisahan lebih lanjut, (3) jumlah amatan dalam simpul lebih kecil dari batas minimum yang ditentukan, atau (4) kedalaman pohon telah mencapai batas maksimum.
Langkah-langkah analisis pada praktikum ini adalah:
BreastCancer,
menghapus kolom Id, lalu melihat struktur dan statistik
deskriptif.mice.Class dan
set.seed(234).rpart,
method = "class", cp = 0.008) pada data latih
dan memvisualisasikannya.xerror minimum).Diagram alir pada penelitian ini menggunakan simbol standar: oval untuk terminator (mulai dan selesai), jajargenjang untuk input dan output, serta persegi panjang untuk proses.
Diagram Alir Penelitian
# install.packages(c("mlbench", "mice", "tidyverse", "rpart", "rpart.plot",
# "caret", "pROC", "knitr"))
library(mlbench)
library(mice)
library(tidyverse)
library(rpart)
library(rpart.plot)
library(caret)
library(pROC)
library(knitr)
data(BreastCancer)
head(BreastCancer)## Id Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size
## 1 1000025 5 1 1 1 2
## 2 1002945 5 4 4 5 7
## 3 1015425 3 1 1 1 2
## 4 1016277 6 8 8 1 3
## 5 1017023 4 1 1 3 2
## 6 1017122 8 10 10 8 7
## Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses Class
## 1 1 3 1 1 benign
## 2 10 3 2 1 benign
## 3 2 3 1 1 benign
## 4 4 3 7 1 benign
## 5 1 3 1 1 benign
## 6 10 9 7 1 malignant
## 'data.frame': 699 obs. of 11 variables:
## $ Id : chr "1000025" "1002945" "1015425" "1016277" ...
## $ Cl.thickness : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 5 5 3 6 4 8 1 2 2 4 ...
## $ Cell.size : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 4 1 8 1 10 1 1 1 2 ...
## $ Cell.shape : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 4 1 8 1 10 1 2 1 1 ...
## $ Marg.adhesion : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 1 5 1 1 3 8 1 1 1 1 ...
## $ Epith.c.size : Ord.factor w/ 10 levels "1"<"2"<"3"<"4"<..: 2 7 2 3 2 7 2 2 2 2 ...
## $ Bare.nuclei : Factor w/ 10 levels "1","2","3","4",..: 1 10 2 4 1 10 10 1 1 1 ...
## $ Bl.cromatin : Factor w/ 10 levels "1","2","3","4",..: 3 3 3 3 3 9 3 3 1 2 ...
## $ Normal.nucleoli: Factor w/ 10 levels "1","2","3","4",..: 1 2 1 7 1 7 1 1 1 1 ...
## $ Mitoses : Factor w/ 9 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 5 1 ...
## $ Class : Factor w/ 2 levels "benign","malignant": 1 1 1 1 1 2 1 1 1 1 ...
Interpretasi. Data BreastCancer
berhasil dimuat ke dalam R dan berisi 699 observasi dengan 11 variabel.
Setiap baris mewakili satu sampel pemeriksaan jaringan payudara. Fungsi
str menunjukkan bahwa kolom Id bertipe
karakter (nomor identitas sampel), 5 variabel karakteristik sel bertipe
ordered factor dengan skala 1 sampai 10, dan Class
bertipe factor dengan dua level, yaitu benign dan malignant.
Variabel Class adalah target klasifikasi, sehingga kasus
ini tergolong pohon klasifikasi (Classification Tree), bukan
regresi. Urutan level Class penting karena benign
berada pada urutan pertama dan malignant pada urutan kedua;
oleh karena itu kelas malignant nanti ditetapkan secara
eksplisit sebagai kelas positif pada confusion matrix. Enam
baris pertama (head) belum memperlihatkan nilai kosong,
tetapi ringkasan data pada sub-bab berikutnya akan menunjukkan adanya
NA pada salah satu variabel prediktor, yang dibahas pada
sub-bab 4.2.
data <- BreastCancer
# Kolom Id dihapus: hanya nomor identitas, tidak membawa informasi untuk klasifikasi
data$Id <- NULL
# Prediktor (ordered factor skala 1-10) diubah menjadi skor numerik 1-10
kol_prediktor <- names(data)[names(data) != "Class"]
data[kol_prediktor] <- lapply(data[kol_prediktor],
function(x) as.numeric(as.character(x)))
str(data)## 'data.frame': 699 obs. of 10 variables:
## $ Cl.thickness : num 5 5 3 6 4 8 1 2 2 4 ...
## $ Cell.size : num 1 4 1 8 1 10 1 1 1 2 ...
## $ Cell.shape : num 1 4 1 8 1 10 1 2 1 1 ...
## $ Marg.adhesion : num 1 5 1 1 3 8 1 1 1 1 ...
## $ Epith.c.size : num 2 7 2 3 2 7 2 2 2 2 ...
## $ Bare.nuclei : num 1 10 2 4 1 10 10 1 1 1 ...
## $ Bl.cromatin : num 3 3 3 3 3 9 3 3 1 2 ...
## $ Normal.nucleoli: num 1 2 1 7 1 7 1 1 1 1 ...
## $ Mitoses : num 1 1 1 1 1 1 1 1 5 1 ...
## $ Class : Factor w/ 2 levels "benign","malignant": 1 1 1 1 1 2 1 1 1 1 ...
## [1] "benign" "malignant"
Interpretasi.
Id. Kolom Id
dihapus sehingga data tersisa 10 kolom, yaitu 9 prediktor dan 1 target
(Class). Kolom Id hanyalah nomor identitas
sampel; jika dibiarkan, algoritma dapat membentuk aturan pemisahan yang
tidak bermakna secara medis karena nomor identitas tidak berhubungan
dengan sifat sel tumor.Cell.size < 3 lebih
mudah dibaca dibandingkan pemisahan berbasis kumpulan level. Perubahan
ini juga memudahkan imputasi dengan predictive mean matching
pada tahap berikutnya.Class tetap bertipe
factor dengan level benign dan malignant.## Cl.thickness Cell.size Cell.shape Marg.adhesion
## Min. : 1.000 Min. : 1.000 Min. : 1.000 Min. : 1.000
## 1st Qu.: 2.000 1st Qu.: 1.000 1st Qu.: 1.000 1st Qu.: 1.000
## Median : 4.000 Median : 1.000 Median : 1.000 Median : 1.000
## Mean : 4.418 Mean : 3.134 Mean : 3.207 Mean : 2.807
## 3rd Qu.: 6.000 3rd Qu.: 5.000 3rd Qu.: 5.000 3rd Qu.: 4.000
## Max. :10.000 Max. :10.000 Max. :10.000 Max. :10.000
##
## Epith.c.size Bare.nuclei Bl.cromatin Normal.nucleoli
## Min. : 1.000 Min. : 1.000 Min. : 1.000 Min. : 1.000
## 1st Qu.: 2.000 1st Qu.: 1.000 1st Qu.: 2.000 1st Qu.: 1.000
## Median : 2.000 Median : 1.000 Median : 3.000 Median : 1.000
## Mean : 3.216 Mean : 3.545 Mean : 3.438 Mean : 2.867
## 3rd Qu.: 4.000 3rd Qu.: 6.000 3rd Qu.: 5.000 3rd Qu.: 4.000
## Max. :10.000 Max. :10.000 Max. :10.000 Max. :10.000
## NAs :16
## Mitoses Class
## Min. : 1.000 benign :458
## 1st Qu.: 1.000 malignant:241
## Median : 1.000
## Mean : 1.589
## 3rd Qu.: 1.000
## Max. :10.000
##
##
## Distribusi kelas Class:
##
## benign malignant
## 458 241
##
## benign malignant
## 65.52 34.48
# Rata-rata setiap prediktor menurut kelas
rata_kelas <- data %>%
group_by(Class) %>%
summarise(across(everything(), ~ mean(.x, na.rm = TRUE)))
rata_kelas## # A tibble: 2 × 10
## Class Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size Bare.nuclei
## <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 beni… 2.96 1.33 1.44 1.36 2.12 1.35
## 2 mali… 7.20 6.57 6.56 5.55 5.30 7.63
## # ℹ 3 more variables: Bl.cromatin <dbl>, Normal.nucleoli <dbl>, Mitoses <dbl>
selisih <- sapply(kol_prediktor, function(v)
rata_kelas[[v]][rata_kelas$Class == "malignant"] -
rata_kelas[[v]][rata_kelas$Class == "benign"])
# Boxplot prediktor menurut kelas
data %>%
pivot_longer(-Class, names_to = "Variabel", values_to = "Nilai") %>%
ggplot(aes(x = Class, y = Nilai, fill = Class)) +
geom_boxplot(na.rm = TRUE) +
facet_wrap(~ Variabel, ncol = 3) +
scale_fill_manual(values = c(benign = "#66b2b2", malignant = "#e07b7b")) +
labs(title = "Sebaran Prediktor Menurut Kelas Tumor", x = "Class", y = "Skor (1-10)") +
theme_minimal() +
theme(legend.position = "none")Interpretasi. Statistik deskriptif memberikan gambaran awal tentang pemusatan dan penyebaran data sebelum pemodelan.
NA
pada Bare.nuclei (16 data), yang perlu ditangani sebelum
pemodelan.## Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size
## 0 0 0 0 0
## Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses Class
## 16 0 0 0 0
## Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size
## 0.00 0.00 0.00 0.00 0.00
## Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses Class
## 2.29 0.00 0.00 0.00 0.00
##
## Total NA pada seluruh data : 16
## Jumlah baris dengan NA : 16
##
## Kelas pada baris yang mengandung NA:
##
## benign malignant
## 14 2
## Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size Bl.cromatin
## 683 1 1 1 1 1 1
## 16 1 1 1 1 1 1
## 0 0 0 0 0 0
## Normal.nucleoli Mitoses Bare.nuclei
## 683 1 1 1 0
## 16 1 1 0 1
## 0 0 16 16
## Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size Bare.nuclei
## 24 8 4 5 1 2 NA
## 41 6 6 6 9 6 NA
## 140 1 1 1 1 1 NA
## 146 1 1 3 1 2 NA
## 159 1 1 2 1 3 NA
## 165 5 1 1 1 2 NA
## 236 3 1 4 1 2 NA
## 250 3 1 1 1 2 NA
## 276 3 1 3 1 2 NA
## 293 8 8 8 1 2 NA
## 295 1 1 1 1 2 NA
## 298 5 4 3 1 2 NA
## 316 4 6 5 6 7 NA
## 322 3 1 1 1 2 NA
## 412 1 1 1 1 1 NA
## 618 1 1 1 1 1 NA
## Bl.cromatin Normal.nucleoli Mitoses Class
## 24 7 3 1 malignant
## 41 7 8 1 benign
## 140 2 1 1 benign
## 146 2 1 1 benign
## 159 1 1 1 benign
## 165 3 1 1 benign
## 236 3 1 1 benign
## 250 3 1 1 benign
## 276 2 1 1 benign
## 293 6 10 1 malignant
## 295 2 1 1 benign
## 298 2 3 1 benign
## 316 4 9 1 benign
## 322 3 1 1 benign
## 412 2 1 1 benign
## 618 1 1 1 benign
Interpretasi.
NA adalah Bare.nuclei, dengan 16 data hilang
(2.29%) yang tersebar pada 16 baris. Seluruh variabel lainnya lengkap.
Tabel md.pattern memperlihatkan bahwa 683 baris lengkap dan
16 baris hanya kehilangan satu nilai pada Bare.nuclei,
sehingga polanya sederhana (hanya satu variabel yang bermasalah).NA, sebanyak 14 berasal dari kelas benign dan 2
dari kelas malignant. Proporsi kelas benign pada baris
yang mengandung NA adalah 87.5%, dibandingkan 65.52% pada
keseluruhan data. Karena komposisi kelas pada baris yang hilang dapat
berbeda dari komposisi keseluruhan, menghapus baris tersebut berisiko
sedikit menggeser proporsi kelas, sehingga sebaiknya data hilang
diimputasi berdasarkan hubungan dengan variabel lain, bukan
dihapus.mice, yang memanfaatkan hubungan
antarvariabel untuk memperkirakan nilai yang hilang.# Imputasi dilakukan hanya pada kolom prediktor (Class tidak dipakai sebagai
# prediktor imputasi agar informasi target tidak bocor ke data uji)
imp <- mice(X, m = 5, method = "pmm", maxit = 5, printFlag = FALSE, seed = 123)
# Metode imputasi yang dipakai (hanya variabel yang punya NA)
imp$method[imp$method != ""]## Bare.nuclei
## "pmm"
## 1 2 3 4 5
## 24 4 3 10 10 7
## 41 8 10 10 9 1
## 140 5 1 1 1 1
## 146 1 1 1 1 5
## 159 1 1 1 1 1
## 165 1 1 1 1 1
## 236 1 1 1 1 1
## 250 1 1 1 1 1
## 276 1 4 1 1 1
## 293 10 2 10 10 10
## 295 1 1 1 1 1
## 298 1 1 1 1 1
## 316 10 10 10 10 1
## 322 1 1 1 1 1
## 412 1 1 1 1 1
## 618 1 3 1 1 1
# Dataset lengkap pertama dipakai untuk analisis selanjutnya
X_imp <- complete(imp, 1)
data_imp <- data.frame(X_imp, Class = data$Class)
cat("\nTotal NA setelah imputasi :", sum(is.na(data_imp)), "\n")##
## Total NA setelah imputasi : 0
## Dimensi data setelah imputasi : 699 10
# Hasil imputasi pada baris yang semula hilang
idx_na <- which(is.na(X$Bare.nuclei))
data.frame(Baris = idx_na,
Class = data$Class[idx_na],
Hasil_Imputasi = X_imp$Bare.nuclei[idx_na])## Baris Class Hasil_Imputasi
## 1 24 malignant 4
## 2 41 benign 8
## 3 140 benign 5
## 4 146 benign 1
## 5 159 benign 1
## 6 165 benign 1
## 7 236 benign 1
## 8 250 benign 1
## 9 276 benign 1
## 10 293 malignant 10
## 11 295 benign 1
## 12 298 benign 1
## 13 316 benign 10
## 14 322 benign 1
## 15 412 benign 1
## 16 618 benign 1
# Sebaran Bare.nuclei sebelum dan sesudah imputasi
bandingkan <- data.frame(
Nilai = factor(1:10),
Sebelum = as.numeric(table(factor(X$Bare.nuclei, levels = 1:10))),
Sesudah = as.numeric(table(factor(X_imp$Bare.nuclei, levels = 1:10)))
)
bandingkan## Nilai Sebelum Sesudah
## 1 1 402 413
## 2 2 30 30
## 3 3 28 28
## 4 4 19 20
## 5 5 30 31
## 6 6 4 4
## 7 7 8 8
## 8 8 21 22
## 9 9 9 9
## 10 10 132 134
data.frame(
Kondisi = c("Sebelum imputasi", "Sesudah imputasi"),
Mean = c(mean(X$Bare.nuclei, na.rm = TRUE), mean(X_imp$Bare.nuclei)),
Median = c(median(X$Bare.nuclei, na.rm = TRUE), median(X_imp$Bare.nuclei)),
SD = c(sd(X$Bare.nuclei, na.rm = TRUE), sd(X_imp$Bare.nuclei))
)## Kondisi Mean Median SD
## 1 Sebelum imputasi 3.544656 1 3.643857
## 2 Sesudah imputasi 3.532189 1 3.636812
bandingkan %>%
pivot_longer(-Nilai, names_to = "Kondisi", values_to = "Frekuensi") %>%
mutate(Kondisi = factor(Kondisi, levels = c("Sebelum", "Sesudah"))) %>%
ggplot(aes(x = Nilai, y = Frekuensi, fill = Kondisi)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7, color = "black") +
scale_fill_manual(values = c(Sebelum = "#66b2b2", Sesudah = "#008080")) +
labs(title = "Sebaran Bare.nuclei Sebelum dan Sesudah Imputasi",
x = "Skor Bare.nuclei", y = "Frekuensi") +
theme_minimal()Interpretasi.
mice dijalankan
dengan metode predictive mean matching (pmm),
m = 5 dataset imputasi, dan maxit = 5 iterasi,
dengan seed = 123 agar hasil dapat direproduksi. Imputasi
hanya dilakukan pada kolom prediktor; variabel Class
sengaja tidak dilibatkan sebagai prediktor imputasi supaya informasi
kelas tidak ikut memengaruhi nilai pengisi, mengingat data kemudian akan
dibagi menjadi data latih dan data uji. Metode pmm dipilih
karena nilai pengisinya selalu diambil dari nilai yang benar-benar
teramati, sehingga hasilnya tetap berupa bilangan bulat dalam rentang 1
sampai 10.Bare.nuclei berhasil diisi sehingga total NA
menjadi 0 dan data kembali berukuran 699 baris. Tabel
imp$imp$Bare.nuclei menunjukkan nilai pengisi dari kelima
dataset imputasi; nilai pengisi untuk satu baris dapat berbeda
antar-dataset, yang mencerminkan ketidakpastian imputasi. Untuk analisis
selanjutnya dipakai dataset lengkap pertama
(complete(imp, 1)).Bare.nuclei berubah dari 3.545 menjadi 3.532, median dari 1
menjadi 1, dan simpangan baku dari 3.644 menjadi 3.637. Perubahan yang
kecil dan diagram batang yang hampir identik menunjukkan bahwa imputasi
menjaga bentuk sebaran asli Bare.nuclei, berbeda dengan
pengisian satu nilai tetap (misalnya modus) yang mengecilkan variasi
data.set.seed(234)
train_idx <- createDataPartition(data_imp$Class, p = 0.7, list = FALSE)
train <- data_imp[train_idx, ]
test <- data_imp[-train_idx, ]
cat("Dimensi data latih (training) :", dim(train), "\n")## Dimensi data latih (training) : 490 10
## Dimensi data uji (testing) : 209 10
##
## Distribusi kelas data asli:
##
## benign malignant
## 458 241
##
## benign malignant
## 65.52 34.48
##
## Distribusi kelas data latih:
##
## benign malignant
## 321 169
##
## benign malignant
## 65.51 34.49
##
## Distribusi kelas data uji:
##
## benign malignant
## 137 72
##
## benign malignant
## 65.55 34.45
Interpretasi.
Class menggunakan
createDataPartition (p = 0.7,
set.seed(234)) menjadi 490 observasi data latih (70.1%) dan
209 observasi data uji (29.9%). Keduanya memiliki 10 kolom (9 prediktor
dan 1 target).## n= 490
##
## node), split, n, loss, yval, (yprob)
## * denotes terminal node
##
## 1) root 490 169 benign (0.655102041 0.344897959)
## 2) Cell.size< 2.5 309 11 benign (0.964401294 0.035598706)
## 4) Bare.nuclei< 3.5 293 2 benign (0.993174061 0.006825939) *
## 5) Bare.nuclei>=3.5 16 7 malignant (0.437500000 0.562500000) *
## 3) Cell.size>=2.5 181 23 malignant (0.127071823 0.872928177)
## 6) Bare.nuclei< 1.5 21 8 benign (0.619047619 0.380952381)
## 12) Cell.size< 3.5 12 0 benign (1.000000000 0.000000000) *
## 13) Cell.size>=3.5 9 1 malignant (0.111111111 0.888888889) *
## 7) Bare.nuclei>=1.5 160 10 malignant (0.062500000 0.937500000) *
##
## Jumlah leaf (simpul akhir) : 5
## Jumlah split : 4
## Variabel yang dipakai split :
## [1] "Bare.nuclei" "Cell.size"
# Informasi simpul akar
root_var <- as.character(fit.tree$frame$var[1])
root_cut <- fit.tree$splits[1, "index"]
root_txt <- ifelse(abs(fit.tree$splits[1, "ncat"]) == 1,
paste0(" dengan titik pemisah ", round(root_cut, 2)), "")
root_kelas <- levels(train$Class)[fit.tree$frame$yval[1]]
root_error <- fit.tree$frame$dev[1] / fit.tree$frame$n[1]
rpart.plot(
fit.tree,
type = 4, extra = 104, under = FALSE,
shadow.col = "gray", faclen = 0, cex = 0.8,
main = "Classification Tree Awal (Sebelum Pruning)"
)Interpretasi.
rpart menggunakan method = "class" karena
target Class berupa kategori (kasus klasifikasi), dan
cp = 0.008 sebagai batas minimal penurunan galat relatif
agar suatu split dipertahankan. Kriteria pemisahan yang dipakai
adalah Gini Index (bawaan rpart). Hasilnya adalah
pohon dengan 5 leaf (4 split) yang memakai 2 variabel
prediktor.vi <- fit.tree$variable.importance
vi_df <- data.frame(
Variabel = names(vi),
Importance = as.numeric(vi)
) %>%
mutate(Persen = Importance / sum(Importance) * 100) %>%
arrange(desc(Importance))
kable(vi_df, digits = 2, caption = "Variable Importance (Pohon Sebelum Pruning)")| Variabel | Importance | Persen |
|---|---|---|
| Cell.size | 168.18 | 21.10 |
| Cell.shape | 134.96 | 16.93 |
| Bare.nuclei | 131.40 | 16.49 |
| Bl.cromatin | 122.44 | 15.36 |
| Epith.c.size | 117.74 | 14.77 |
| Normal.nucleoli | 108.17 | 13.57 |
| Cl.thickness | 7.17 | 0.90 |
| Marg.adhesion | 6.91 | 0.87 |
ggplot(vi_df, aes(x = fct_reorder(Variabel, Importance), y = Importance)) +
geom_pointrange(aes(ymin = 0, ymax = Importance),
color = "cadetblue", size = 0.3) +
theme_minimal() +
coord_flip() +
labs(x = "", y = "Importance",
title = "Variable Importance Classification Tree (Sebelum Pruning)")Interpretasi.
Cell.size dan Cell.shape), sehingga
kepentingan dapat terbagi di antara variabel yang membawa informasi
serupa melalui mekanisme surrogate split. Karena itu urutan
kepentingan sebaiknya dibaca sebagai gambaran kelompok variabel yang
berpengaruh, bukan peringkat yang mutlak.# Prediksi kelas
pred.train <- predict(fit.tree, train, type = "class")
pred.tree <- predict(fit.tree, test, type = "class")
# Tabel prediksi vs aktual (data uji)
table(Prediksi = pred.tree, Aktual = test$Class)## Aktual
## Prediksi benign malignant
## benign 119 0
## malignant 18 72
# Confusion matrix (kelas positif = malignant)
cm_train_full <- confusionMatrix(pred.train, train$Class, positive = "malignant")
cm_full <- confusionMatrix(pred.tree, test$Class, positive = "malignant")
cm_full## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 119 0
## malignant 18 72
##
## Accuracy : 0.9139
## 95% CI : (0.8673, 0.9482)
## No Information Rate : 0.6555
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.82
##
## Mcnemar's Test P-Value : 6.151e-05
##
## Sensitivity : 1.0000
## Specificity : 0.8686
## Pos Pred Value : 0.8000
## Neg Pred Value : 1.0000
## Prevalence : 0.3445
## Detection Rate : 0.3445
## Detection Prevalence : 0.4306
## Balanced Accuracy : 0.9343
##
## 'Positive' Class : malignant
##
# Ringkasan ukuran evaluasi
ringkas_cm <- function(cm) {
c(Accuracy = unname(cm$overall["Accuracy"]),
Sensitivity = unname(cm$byClass["Sensitivity"]),
Specificity = unname(cm$byClass["Specificity"]),
Precision = unname(cm$byClass["Precision"]),
F1 = unname(cm$byClass["F1"]),
Kappa = unname(cm$overall["Kappa"]))
}
hasil_full <- rbind(Training = ringkas_cm(cm_train_full),
Testing = ringkas_cm(cm_full))
kable(hasil_full, digits = 4, caption = "Ukuran Evaluasi Sebelum Pruning")| Accuracy | Sensitivity | Specificity | Precision | F1 | Kappa | |
|---|---|---|---|---|---|---|
| Training | 0.9592 | 0.9882 | 0.9439 | 0.9027 | 0.9435 | 0.9117 |
| Testing | 0.9139 | 1.0000 | 0.8686 | 0.8000 | 0.8889 | 0.8200 |
# Komponen confusion matrix data uji
TP_f <- cm_full$table["malignant", "malignant"]
FN_f <- cm_full$table["benign", "malignant"]
FP_f <- cm_full$table["malignant", "benign"]
TN_f <- cm_full$table["benign", "benign"]
# Visualisasi confusion matrix
plot_cm <- function(cm, judul) {
ggplot(as.data.frame(cm$table), aes(x = Reference, y = Prediction, fill = Freq)) +
geom_tile(color = "white") +
geom_text(aes(label = Freq), size = 6) +
scale_fill_gradient(low = "#E0F2F1", high = "#008080") +
labs(title = judul, x = "Aktual", y = "Prediksi") +
theme_minimal() +
theme(legend.position = "none")
}
plot_cm(cm_full, "Confusion Matrix Data Uji (Sebelum Pruning)")Interpretasi.
##
## Classification tree:
## rpart(formula = Class ~ ., data = train, method = "class", cp = 0.008)
##
## Variables actually used in tree construction:
## [1] Bare.nuclei Cell.size
##
## Root node error: 169/490 = 0.3449
##
## n= 490
##
## CP nsplit rel error xerror xstd
## 1 0.798817 0 1.00000 1.00000 0.062260
## 2 0.035503 1 0.20118 0.24852 0.036667
## 3 0.011834 3 0.13018 0.21893 0.034607
## 4 0.008000 4 0.11834 0.16568 0.030403
cp_tab <- as.data.frame(fit.tree$cptable)
kable(cp_tab, digits = 5, caption = "Tabel CP (Complexity Parameter) dan Galat Cross-Validation")| CP | nsplit | rel error | xerror | xstd |
|---|---|---|---|---|
| 0.79882 | 0 | 1.00000 | 1.00000 | 0.06226 |
| 0.03550 | 1 | 0.20118 | 0.24852 | 0.03667 |
| 0.01183 | 3 | 0.13018 | 0.21893 | 0.03461 |
| 0.00800 | 4 | 0.11834 | 0.16568 | 0.03040 |
# CP terbaik: xerror minimum
bestcp <- fit.tree$cptable[which.min(fit.tree$cptable[, "xerror"]), "CP"]
idx_best <- which.min(cp_tab$xerror)
bestcp## [1] 0.008
# Pembanding: aturan 1-SE
batas_1se <- cp_tab$xerror[idx_best] + cp_tab$xstd[idx_best]
idx_1se <- which(cp_tab$xerror <= batas_1se)[1]
cp_1se <- cp_tab$CP[idx_1se]
data.frame(
Kriteria = c("xerror minimum (dipakai)", "Aturan 1-SE (pembanding)"),
CP = c(bestcp, cp_1se),
Jumlah_Split = c(cp_tab$nsplit[idx_best], cp_tab$nsplit[idx_1se]),
xerror = c(cp_tab$xerror[idx_best], cp_tab$xerror[idx_1se])
)## Kriteria CP Jumlah_Split xerror
## 1 xerror minimum (dipakai) 0.008 4 0.1656805
## 2 Aturan 1-SE (pembanding) 0.008 4 0.1656805
Interpretasi.
nsplit), galat relatif pada data latih
(rel error), galat hasil cross-validation
10-fold (xerror), serta simpangan bakunya
(xstd). Seiring bertambahnya jumlah split,
rel error terus menurun karena pohon makin cocok dengan
data latih, sedangkan xerror awalnya menurun lalu mencapai
titik minimum dan kemudian mendatar atau naik. Pola ini menunjukkan
bahwa penambahan split setelah titik tertentu tidak lagi
memperbaiki kemampuan generalisasi. Galat pada tabel dinyatakan relatif
terhadap galat simpul akar (34.49%).xerror minimum, yaitu 0.008 dengan 4
split (5 leaf) dan xerror sebesar 0.1657.
Pohon awal memiliki 4 split, sehingga pemangkasan akan tidak
mengubah ukuran pohon karena CP terbaik berada pada pohon terbesar.xerror minimum yang digunakan untuk
pruning.plotcp. Sumbu-x bawah
menunjukkan nilai CP dan sumbu-x atas menunjukkan jumlah split,
sedangkan sumbu-y menunjukkan xerror relatif beserta garis
batas 1-SE (garis putus-putus). Titik terendah pada kurva berkesesuaian
dengan CP terbaik pada tabel.xerror diperoleh dari
cross-validation acak sehingga dapat sedikit berbeda jika
set.seed diganti. Karena itu set.seed(234)
ditetapkan sebelum pembentukan pohon agar hasil dapat direproduksi.pruned.tree <- prune(fit.tree, cp = bestcp)
cat("Jumlah leaf sebelum pruning :", n_leaf(fit.tree), "\n")## Jumlah leaf sebelum pruning : 5
## Jumlah leaf sesudah pruning : 5
## CP yang digunakan : 0.008
## Variabel yang dipakai split :
## [1] "Bare.nuclei" "Cell.size"
rpart.plot(
pruned.tree,
type = 4, extra = 104, under = FALSE,
shadow.col = "gray", faclen = 0, cex = 0.9,
main = paste0("Classification Tree Setelah Pruning (CP = ", round(bestcp, 5), ")")
)## Cell.size Cell.shape Bare.nuclei Bl.cromatin Epith.c.size
## 168.179949 134.962137 131.402882 122.437928 117.739074
## Normal.nucleoli Cl.thickness Marg.adhesion
## 108.167875 7.174702 6.906558
vi_p <- pruned.tree$variable.importance
vi_p_df <- data.frame(Variabel = names(vi_p), Importance = as.numeric(vi_p)) %>%
mutate(Persen = Importance / sum(Importance) * 100) %>%
arrange(desc(Importance))
kable(head(vi_p_df, 5), digits = 2, caption = "Lima Variabel Terpenting Setelah Pruning")| Variabel | Importance | Persen |
|---|---|---|
| Cell.size | 168.18 | 21.10 |
| Cell.shape | 134.96 | 16.93 |
| Bare.nuclei | 131.40 | 16.49 |
| Bl.cromatin | 122.44 | 15.36 |
| Epith.c.size | 117.74 | 14.77 |
Interpretasi.
pred.prune.train <- predict(pruned.tree, train, type = "class")
pred.prune <- predict(pruned.tree, test, type = "class")
# Tabel prediksi vs aktual (data uji)
table(Prediksi = pred.prune, Aktual = test$Class)## Aktual
## Prediksi benign malignant
## benign 119 0
## malignant 18 72
# Confusion matrix setelah pruning (kelas positif = malignant)
cm_train_pruned <- confusionMatrix(pred.prune.train, train$Class, positive = "malignant")
cm_pruned <- confusionMatrix(pred.prune, test$Class, positive = "malignant")
cm_pruned## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 119 0
## malignant 18 72
##
## Accuracy : 0.9139
## 95% CI : (0.8673, 0.9482)
## No Information Rate : 0.6555
## P-Value [Acc > NIR] : < 2.2e-16
##
## Kappa : 0.82
##
## Mcnemar's Test P-Value : 6.151e-05
##
## Sensitivity : 1.0000
## Specificity : 0.8686
## Pos Pred Value : 0.8000
## Neg Pred Value : 1.0000
## Prevalence : 0.3445
## Detection Rate : 0.3445
## Detection Prevalence : 0.4306
## Balanced Accuracy : 0.9343
##
## 'Positive' Class : malignant
##
hasil_pruned <- rbind(Training = ringkas_cm(cm_train_pruned),
Testing = ringkas_cm(cm_pruned))
kable(hasil_pruned, digits = 4, caption = "Ukuran Evaluasi Sesudah Pruning")| Accuracy | Sensitivity | Specificity | Precision | F1 | Kappa | |
|---|---|---|---|---|---|---|
| Training | 0.9592 | 0.9882 | 0.9439 | 0.9027 | 0.9435 | 0.9117 |
| Testing | 0.9139 | 1.0000 | 0.8686 | 0.8000 | 0.8889 | 0.8200 |
# Komponen confusion matrix data uji
TP_p <- cm_pruned$table["malignant", "malignant"]
FN_p <- cm_pruned$table["benign", "malignant"]
FP_p <- cm_pruned$table["malignant", "benign"]
TN_p <- cm_pruned$table["benign", "benign"]
plot_cm(cm_pruned, "Confusion Matrix Data Uji (Sesudah Pruning)")# Probabilitas kelas positif (malignant) pada data uji
prob_full <- predict(fit.tree, test, type = "prob")[, "malignant"]
prob_pruned <- predict(pruned.tree, test, type = "prob")[, "malignant"]
# Kurva ROC dan AUC (benign = kontrol, malignant = kasus)
roc_full <- roc(test$Class, prob_full, levels = c("benign", "malignant"), direction = "<")
roc_pruned <- roc(test$Class, prob_pruned, levels = c("benign", "malignant"), direction = "<")
auc_full <- as.numeric(auc(roc_full))
auc_pruned <- as.numeric(auc(roc_pruned))
data.frame(Model = c("Sebelum Pruning", "Sesudah Pruning"),
AUC = c(auc_full, auc_pruned))## Model AUC
## 1 Sebelum Pruning 0.962794
## 2 Sesudah Pruning 0.962794
ggroc(list("Sebelum Pruning" = roc_full, "Sesudah Pruning" = roc_pruned),
legacy.axes = TRUE) +
geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "gray40") +
scale_color_manual(values = c("Sebelum Pruning" = "#E07B7B", "Sesudah Pruning" = "#008080")) +
labs(title = "Kurva ROC Data Uji",
subtitle = paste0("AUC sebelum pruning = ", round(auc_full, 4),
" | AUC sesudah pruning = ", round(auc_pruned, 4)),
x = "False Positive Rate (1 - Specificity)",
y = "True Positive Rate (Sensitivity)",
color = "Model") +
theme_minimal()# Tabel perbandingan keseluruhan
hasil_banding <- data.frame(
Model = c("Sebelum Pruning", "Sesudah Pruning"),
Jumlah_Leaf = c(n_leaf(fit.tree), n_leaf(pruned.tree)),
Acc_Train = c(hasil_full["Training", "Accuracy"], hasil_pruned["Training", "Accuracy"]),
Acc_Test = c(hasil_full["Testing", "Accuracy"], hasil_pruned["Testing", "Accuracy"]),
Sensitivity = c(hasil_full["Testing", "Sensitivity"], hasil_pruned["Testing", "Sensitivity"]),
Specificity = c(hasil_full["Testing", "Specificity"], hasil_pruned["Testing", "Specificity"]),
Precision = c(hasil_full["Testing", "Precision"], hasil_pruned["Testing", "Precision"]),
F1 = c(hasil_full["Testing", "F1"], hasil_pruned["Testing", "F1"]),
AUC = c(auc_full, auc_pruned)
)
kable(hasil_banding, digits = 4, caption = "Perbandingan Kinerja Model Sebelum dan Sesudah Pruning (Data Uji)")| Model | Jumlah_Leaf | Acc_Train | Acc_Test | Sensitivity | Specificity | Precision | F1 | AUC |
|---|---|---|---|---|---|---|---|---|
| Sebelum Pruning | 5 | 0.9592 | 0.9139 | 1 | 0.8686 | 0.8 | 0.8889 | 0.9628 |
| Sesudah Pruning | 5 | 0.9592 | 0.9139 | 1 | 0.8686 | 0.8 | 0.8889 | 0.9628 |
# Perubahan akurasi data uji (poin persentase)
perubahan_acc <- (hasil_pruned["Testing", "Accuracy"] - hasil_full["Testing", "Accuracy"]) * 100
cat("\nPerubahan akurasi data uji setelah pruning :", round(perubahan_acc, 2), "poin persentase\n")##
## Perubahan akurasi data uji setelah pruning : 0 poin persentase
## Perubahan AUC setelah pruning : 0
Interpretasi.
Class berupa kategori (benign dan
malignant), digunakan Classification Tree dengan
Gini Index sebagai kriteria pemisahan, dan prediksi berupa
kelas mayoritas pada setiap leaf.BreastCancer berisi 699
observasi dengan 10 variabel analisis setelah kolom Id
dihapus. Missing value hanya terdapat pada
Bare.nuclei sebanyak 16 data (2.29%) dan berhasil
diimputasi dengan mice (metode predictive mean
matching, m = 5) sehingga data lengkap 699 baris.
Imputasi menjaga sebaran Bare.nuclei (rata-rata 3.545
menjadi 3.532). Kelas target tidak seimbang secara sedang, yaitu 65.52%
benign dan 34.48% malignant.cp = 0.008
memiliki 5 leaf dengan split pertama pada variabel
Cell.size. Tiga variabel terpenting adalah Cell.size, Cell.shape, dan
Bare.nuclei dengan total kepentingan 54.52%, sehingga pembedaan tumor
jinak dan ganas terutama ditentukan oleh beberapa karakteristik sel
tersebut.xerror minimum adalah 0.008 dengan 4
split. Pruning mengubah jumlah leaf dari 5
menjadi 5 sehingga model menjadi lebih sederhana dan lebih mudah
diinterpretasikan.m = 5) dengan penggabungan hasil untuk menangkap
ketidakpastian imputasi.Breiman, L., Friedman, J. H., Olshen, R. A., & Stone, C. J. (1984). Classification and Regression Trees. Wadsworth.
Fawcett, T. (2006). An introduction to ROC analysis. Pattern Recognition Letters, 27(8), 861-874.
James, G., Witten, D., Hastie, T., & Tibshirani, R. (2013). An Introduction to Statistical Learning with Applications in R. Springer.
Little, R. J. A., & Rubin, D. B. (2002). Statistical Analysis with Missing Data (2nd ed.). Wiley.
Therneau, T. M., & Atkinson, E. J. (2019). An Introduction to Recursive Partitioning Using the RPART Routines. Mayo Foundation.
van Buuren, S., & Groothuis-Oudshoorn, K. (2011). mice: Multivariate Imputation by Chained Equations in R. Journal of Statistical Software, 45(3), 1-67.
Wolberg, W. H., & Mangasarian, O. L. (1990). Multisurface method of pattern separation for medical diagnosis applied to breast cytology. Proceedings of the National Academy of Sciences, 87(23), 9193-9196.