BAB I PENDAHULUAN

1.1 Latar Belakang

Machine learning merupakan salah satu bidang dalam kecerdasan buatan yang memungkinkan komputer mempelajari pola dari data untuk menghasilkan prediksi maupun mendukung proses pengambilan keputusan. Penerapan machine learning semakin berkembang seiring dengan meningkatnya ketersediaan data dan kebutuhan akan metode analisis yang mampu memberikan hasil secara akurat dan efisien. Berbagai algoritma machine learning dapat digunakan untuk menyelesaikan permasalahan klasifikasi maupun regresi di berbagai bidang. Namun, setiap algoritma memiliki karakteristik masing-masing, sehingga pemilihan metode yang tepat menjadi hal penting dalam membangun model prediksi (Saputri, Firmansyah, & Purnomo, 2025). Salah satu algoritma yang dapat digunakan untuk mengatasi permasalahan tersebut adalah Random Forest, yang menerapkan konsep ensemble learning dengan menggabungkan sejumlah pohon keputusan untuk menghasilkan prediksi yang lebih akurat (Jollyta dkk., 2023).

Random Forest merupakan salah satu algoritma supervised learning yang menerapkan konsep ensemble learning dengan menggabungkan sejumlah pohon keputusan (decision tree) untuk menyelesaikan permasalahan klasifikasi maupun regresi. Algoritma ini membangun sekumpulan pohon keputusan menggunakan berbagai sampel hasil pengambilan secara acak dari data yang tersedia serta pemilihan subset variabel pada setiap proses pembentukan pohon. Hasil prediksi dari seluruh pohon kemudian digabungkan melalui mekanisme voting pada klasifikasi atau rata-rata (averaging) pada regresi. Penggabungan tersebut bertujuan untuk meningkatkan akurasi prediksi serta mengurangi risiko overfitting dibandingkan dengan penggunaan satu pohon keputusan (Habibi, Fahira, & Dwiyanti, 2023).

Double Random Forest (DRF) merupakan metode yang diperkenalkan oleh Han, Kim, dan Lee pada tahun 2020 sebagai pengembangan dari algoritma Random Forest. Metode ini dikembangkan untuk mengatasi kondisi underfitting yang dapat terjadi ketika pohon keputusan yang dihasilkan oleh Random Forest belum memiliki ukuran atau kompleksitas yang memadai dalam menangkap pola data (Fransiska, 2026). Melalui pendekatan yang dikembangkan, DRF berupaya meningkatkan kemampuan model dalam mempelajari struktur data sehingga menghasilkan prediksi yang lebih baik. Dalam praktikum ini, algoritma Random Forest dan Double Random Forest diterapkan menggunakan bahasa pemrograman R sebagai alat komputasi. Penggunaan R diharapkan dapat membantu proses pembentukan model, pengolahan data, serta evaluasi kinerja kedua algoritma sehingga prinsip kerja dan karakteristik masing-masing metode dapat dipahami secara lebih mendalam.

1.2 Rumusan Masalah

Berdasarkan latar belakang, rumusan masalah yang dapat disimpulkan adalah:

  1. Bagaimana metode Random Forest dan Double Random Forest sebagai metode ensemble berbasis Decision Tree?
  2. Bagaimana cara mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi?
  3. Bagaimana cara mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest?

1.3 Tujuan

Adapun tujuan penelitian ini yaitu:

  1. Mahasiswa dapat memahami Random Forest dan Double Random Forest sebagai metode ensemble berbasis Decision Tree.
  2. Mahasiswa dapat mengimplementasikan Random Forest untuk klasifikasi dan regresi, serta Double Random Forest untuk klasifikasi dan regresi.
  3. Mahasiswa dapat mengevaluasi performa model, memahami Out-of-Bag (OOB) error, dan membandingkan Random Forest dengan Double Random Forest.

BAB II TINJAUAN PUSTAKA

2.1 Random Forest

Random Forest adalah metode klasifikasi yang membangun beberapa pohon keputusan (decision tree) menggunakan sampel dan variabel data latih yang dipilih secara acak yang bertujuan untuk meningkatkan akurasi model. Metode ini merupakan bootsrap aggregating (bagging) juga random feature selection. Bootsrap aggregating (bagging) diterapkan dalam metode Random Forest, yakni proses pembentukan pohon diperlukan beberapa kumpulan bootstrap yang diperoleh melalui kumpulan data latih dengan pengembalian. Kemudian, sebuah pohon ditumbuhkan pada kumpulan data latih baru dengan menggunakan random reature selection, dengan tidak melakukan pemangkasan (pruning) pada pohon tersebut. Hasil akhir dari metode klasifikasi Random Forest diperoleh dengan mengambil hasil mayoritas (major voting) dari pohon-pohon yang telah terbentuk (Mola, Rumlaklak, & Polly, 2024).

Berikut ini merupakan langkah-langkah klasifikasi menggunakan metode Random Forest (Mola, Rumlaklak, & Polly, 2024):

  1. Membuat bootstrap sample

    Proses bootstrap sample, yakni melakukan penarikan sampel acak berukuran \(N\) pengamatan dari data training dengan pengembalian (replacement).

  2. Penentuan nilai mtry atau max features

    Terdapat tiga cara untuk mendapatkan nilai mtry yaitu:

    \[\text{mtry}_1 = \frac{1}{2}\sqrt{p} \quad(2.1)\]

    \[\text{mtry}_2 = \sqrt{p} \quad(2.2) \]

    \[\text{mtry}_3 = 2 \times \sqrt{p} \quad(2.3)\]

    Keterangan:

    • mtry = banyaknya fitur yang dipertimbangkan untuk setiap split
    • \(p\) = jumlah total fitur dalam dataset

    Penggunaan parameter mtry yang sesuai akan menghasilkan Random Forest dengan keterkaitan yang relatif rendah antara pohon-pohonnya, tetapi tetap memiliki kekuatan masing-masing pohon yang signifikan, ditunjukkan dengan perolehan nilai error OOB yang kecil. Out of Bag (OOB) merupakan nilai pengamatan dari gugus data asli yang tidak termuat dalam sample bootstrap pada setiap iterasinya. Data OOB tidak digunakan untuk membangun pohon, tetapi digunakan sebagai data validasi pada pohon yang bersesuaian.

    Prediksi kesalahan klasifikasi Random Forest dapat diestimasi melalui error OOB. Nilai OOB error yang kecil menandakan bahwa model Random Forest memiliki kinerja yang baik dalam memperkirakan kesalahan prediksi pada data yang tidak terlihat selama proses pelatihan. Dengan kata lain, semakin kecil nilai OOB error, semakin akurat model dalam membuat prediksi pada data baru.

  3. Membangun pohon keputusan (decision tree)

    Pohon keputusan merupakan salah satu metode yang dapat mengubah fakta yang besar sehingga menjadi pohon keputusan yang memprediksi aturan. Setiap pohon dalam Random Forest dibangun dari bootstrap sample sehingga rata-rata sekitar 63.2% amatan dari dataset asli akan dipilih dalam bootstrap sample untuk setiap pohon dan sekitar 36.8% amatan akan menjadi data OOB untuk pohon tersebut. Langkah awal membangun pohon keputusan adalah penentuan root node dengan cara menghitung nilai entropy dan nilai information gain. Penghitungan nilai entropy dan gain dapat menggunakan rumus pada persamaan di bawah ini

    \[\text{Entropy}(S) = \sum_{i=1}^{n} -P_i \log_2 P_i \quad (2.4)\]

    Keterangan:

    • \(S\) = himpunan kasus
    • \(n\) = jumlah partisi \(S\)
    • \(P_i\) = proporsi dari \(S_i\) terhadap \(S\)

    \[\text{Gain}(S, A) = \text{Entropy}(S) - \sum_{i=1}^{n} \frac{|S_i|}{|S|} \times \text{Entropy}(S_i) \quad (2.5)\]

    Keterangan:

    • \(S\) = himpunan kasus
    • \(A\) = atribut
    • \(n\) = jumlah partisi atribut \(A\)
    • \(|S_i|\) = jumlah kasus pada partisi ke-\(i\)
    • \(|S|\) = jumlah kasus dalam \(S\)

    Setelah mendapatkan nilai entropy dan gain untuk setiap fitur, maka fitur yang memiliki gain tertinggi akan dijadikan sebagai root node. Langkah berikutnya, ulangi proses di atas (menghitung entropy dan gain) untuk menentukan node selanjutnya. Proses ini berlanjut sampai semua fitur memiliki kelas yang sama atau tidak ada lagi fitur yang dapat dipartisi lebih lanjut.

  4. Membangun Random Forest (ensemble)

    Ulangi langkah 1 – 3 sebanyak \(k\) kali sehingga terbentuk sebuah hutan (forest) yang terdiri atas \(k\) pohon.

  5. Majority vote untuk klasifikasi

    Dalam Random Forest, majority vote adalah salah satu metode yang digunakan untuk membuat prediksi akhir berdasarkan output dari banyak pohon keputusan yang terbentuk dalam ensemble model tersebut. Cara kerjanya adalah sebagai berikut:

    1. Setelah melatih sejumlah besar pohon keputusan pada sampel data yang berbeda-beda (bootstrap samples) dan fitur-fitur yang dipilih secara acak, setiap pohon memberikan prediksi berdasarkan fitur-fitur tersebut.

    2. Ketika ada data baru yang masuk, setiap pohon di dalam Random Forest memberikan prediksi terhadap data tersebut.

    3. Majority vote dilakukan dengan menghitung jumlah suara atau prediksi dari setiap pohon keputusan.

    4. Kelas atau nilai yang memiliki mayoritas suara atau prediksi akan dipilih sebagai hasil prediksi akhir dari Random Forest.

Adapun keunggulan dan kelemahan dari metode Random Forest sebagai berikut (Romahdoni, 2024):

  • Keunggulan

    1. Akurasi Tinggi dan Stabil. Karena menggabungkan banyak pohon, Random Forest memiliki tingkat akurasi yang lebih tinggi dibanding satu Decision Tree. Model ini juga stabil terhadap perubahan data.

    2. Tahan terhadap Overfitting. Mekanisme random sampling dan bagging membuat model tidak mudah menyesuaikan diri terlalu spesifik dengan data latih.

    3. Mendukung Fitur Penting (Feature Importance). Random Forest dapat menunjukkan atribut atau variabel mana yang paling berpengaruh terhadap hasil prediksi. Fitur ini sangat berguna dalam analisis bisnis.

    4. Dapat Digunakan untuk Berbagai Jenis Data. Baik untuk data numerik maupun kategorikal, serta mendukung dua jenis prediksi: klasifikasi dan regresi.

    5. Cocok untuk Data dengan Dimensi Tinggi. Random Forest bekerja baik meski jumlah fitur sangat banyak, tanpa memerlukan normalisasi data yang rumit.

  • Kelemahan

    1. Kurang Efisien untuk Data Sangat Besar. Metode ini membangun banyak pohon, sehingga waktu komputasi dan penggunaan memori bisa cukup besar.

    2. Sulit Diinterpretasikan. Meskipun menghasilkan prediksi yang akurat, sulit menjelaskan “mengapa” model memberikan hasil tertentu (karena banyaknya pohon di dalamnya).

    3. Tidak Cocok untuk Real-Time Prediction. Jika model berisi ribuan pohon, waktu prediksi bisa lebih lambat, sehingga kurang ideal untuk sistem yang memerlukan respons cepat.

2.2 Double Random Forest

Double Random Forest (DRF) adalah metode yang diperkenalkan oleh Han, Kim, dan Lee pada tahun 2020. DRF dikembangkan untuk situasi ketika Random Forest masih mengalami underfitting karena tree yang dihasilkan belum cukup besar. Pada Random Forest standar, setiap tree dibentuk menggunakan satu bootstrap sample pada awal tree. Karena satu bootstrap sample hanya mengandung sekitar 63,2% observasi unik, jumlah observasi unik yang tersedia untuk membentuk tree lebih sedikit daripada seluruh data training. Setiap tree DRF dibangun menggunakan seluruh data training, sedangkan bootstrap digunakan sementara pada setiap node untuk mencari aturan split.

Secara sederhana, proses Double Random Forest dilakukan sebagai berikut (Fransiska, 2026):

  1. Memulai setiap tree dengan seluruh data training, bukan satu bootstrap sample untuk seluruh tree.
  2. Pada node yang sedang diproses, mengambil bootstrap sample dari observasi yang mencapai node tersebut.
  3. Memilih mtry prediktor secara acak dan mencari split terbaik menggunakan bootstrap sample pada node.
  4. Setelah split terbaik ditemukan, bootstrap sample tidak diteruskan. Split tersebut diterapkan kembali pada data asli yang mencapai node, kemudian observasi asli dikirim ke child nodes.
  5. Mengulangi proses pada node berikutnya sampai aturan penghentian tercapai, lalu mengulangi untuk seluruh tree.
  6. Menggabungkan prediksi seluruh tree. Pada klasifikasi, hasil akhir diperoleh melalui majority voting, sedangkan pada regresi prediksi akhir diperoleh dengan merata-ratakan prediksi seluruh tree.

Pada metode ini, setiap tree menggunakan seluruh data training untuk tumbuh, sehingga DRF cenderung dapat menghasilkan tree yang lebih besar. Pada saat yang sama, penggunaan bootstrap pada setiap node dan random feature subset tetap menambahkan keragaman pada aturan split. Konsekuensinya, DRF umumnya membutuhkan waktu komputasi lebih besar dibanding RF karena proses bootstrap dilakukan berulang pada banyak node.

Aspek Random Forest Double Random Forest
Penggunaan data Setiap pohon dibentuk dari data yang berbeda-beda, yaitu hasil bootstrap resampling pada data latih. Setiap pohon dibentuk dari data yang sama, yaitu keseluruhan data latih.
Jumlah observasi unik \(1 - e^{-1} \approx 0{,}63\) kali dari data latih Sementara pada setiap node untuk mencari split
Proses pemisahan Random feature subset Bootstrap sampling pada setiap node dan random feature subset.
Ukuran pohon Menghasilkan pohon yang lebih kecil dibandingkan dengan double random forest. Cenderung menghasilkan pohon yang lebih besar dan beragam dibandingkan random forest.
Waktu komputasi Waktu komputasi lebih cepat dibandingkan double random forest. Waktu komputasi lebih lama dibandingkan random forest.
Penentuan hasil prediksi akhir Majority voting dari penggabungan hasil prediksi \(k\) buah pohon. Majority voting dari penggabungan hasil prediksi \(k\) buah pohon.
Tabel 1. Perbedaan Random Forest dan Double Random Forest

2.3 Metrik Evaluasi

Ukuran kebaikan model berasal dari confusion matrix, yaitu label yang menunjukkan perbandingan antara hasil prediksi dengan label aktual. Confusion Matrix dapat dilihat pada tabel di bawah ini (Syukron, Santoso, & Widiharih, 2020):

Predicted Class True Class: Positive True Class: Negative
Positive True Positive Count (TP) False Positive Count (FP)
Negative False Negative Count (FN) True Negative Count (TN)
Tabel 2. Confusion Matrix

1. Akurasi (Accuracy)

Akurasi merupakan metrik yang menunjukkan proporsi prediksi yang benar terhadap keseluruhan data. Akurasi dapat dihitung menggunakan formula berikut (Direktorat Jenderal Pendidikan Tinggi, Riset, dan Teknologi, n.d):

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

Akurasi memang menjadi metrik yang paling umum untuk digunakan dalam menilai kinerja. Namun, metrik ini cenderung memberikan gambaran yang keliru ketika distribusi tidak seimbang. Pada data yang tidak seimbang (imbalanced dataset), sebuah model dapat terlihat berkinerja baik dengan akurasi tinggi, padahal tidak mampu mengenali kelas minoritas.

2. Spesifisitas

Spesifisitas adalah tingkat ketepatan pada kelas negatif dalam data aktual, yaitu persentase banyaknya prediksi yang tepat pada observasi yang sebenarnya negatif. Spesifisitas dapat dihitung menggunakan persamaan di bawah ini (Istiana & Mustafiril, 2023):

\[Spesifisitas = \frac{TN}{TN + FP}\] 3. Presisi

Metrik Presisi dapat digunakan untuk mengukur seberapa tepat model dalam memberikan prediksi positif. Nilai prediksi yang tinggi mengindikasikan bahwa model jarang salah memberikan label positif. Metrik presisi dapat dihitung menggunakan formula berikut (Direktorat Jenderal Pendidikan Tinggi, Riset, dan Teknologi, n.d):

\[Precision = \frac{TP}{TP + FP}\] 4. Recall

Recall merupakan metrik yang digunakan untuk mengukur kemampuan model dalam mengenali data yang sebenarnya termasuk dalam kelas positif. Semakin tinggi nilai recall, maka semakin besar proporsi data positif yang berhasil diidentifikasi dengan benar oleh model.

\[Recall = \frac{TP}{TP + FN}\] 6. F1-Score

F1-Score digunakan untuk melihat kinerja model dengan mempertimbangkan precision dan recall secara bersamaan. Nilai F1-Score diperoleh dari rata-rata harmonik kedua metrik tersebut, sehingga memberikan ukuran yang lebih seimbang. Perhitungan F1-Score dapat dilakukan menggunakan persamaan berikut (Direktorat Jenderal Pendidikan Tinggi, Riset, dan Teknologi, n.d):

\[F1\text{-}Score = 2 \times \frac{precision \times recall}{precision + recall}\]

BAB III METODE PENELITIAN

3.1 Jenis dan Sumber Data

Jenis data yang digunakan dalam praktikum ini terdiri atas data kategorik dan numerik. Data kategorik merupakan data yang menunjukkan kelompok atau kategori tertentu untuk membedakan karakteristik suatu objek, sedangkan data numerik merupakan data yang dinyatakan dalam bentuk angka dan dapat digunakan dalam perhitungan matematis. Sumber data yang digunakan dalam praktikum ini adalah data sekunder, yaitu data yang telah tersedia sebelumnya dan dimanfaatkan untuk memenuhi kebutuhan analisis. Data sekunder yang digunakan berupa dataset BreastCancer yang tersedia dalam pemrograman R dan terdiri atas 699 observasi serta 11 variabel.

3.2 Variabel Penelitian

Variabel penelitian merupakan karakteristik atau atribut yang menjadi objek pengamatan dalam suatu penelitian. Pada praktikum ini, dataset BreastCancer terdiri atas 11 variabel, yaitu satu variabel identitas, sembilan variabel prediktor, dan satu variabel target. Variabel Class berperan sebagai variabel target bertipe kategorik yang terdiri atas dua kelas, yaitu benign (jinak) dan malignant (ganas). Sembilan variabel prediktor meliputi Cl.thickness, Cell.size, Cell.shape, Marg.adhesion, Epith.c.size, Bare.nuclei, Bl.cromatin, Normal.nucleoli, dan Mitoses. Variabel Cl.thickness, Cell.size, Cell.shape, Marg.adhesion, dan Epith.c.size bertipe kategorik ordinal (ordered factor), sedangkan Bare.nuclei, Bl.cromatin, Normal.nucleoli, dan Mitoses bertipe kategorik (factor). Sementara itu, variabel Id bertipe karakter dan berfungsi sebagai identitas setiap pengamatan, sehingga tidak digunakan sebagai prediktor dalam pemodelan.

3.3 Analisis Data

Adapun analisis data pada batasan masalah ini sebagai berikut: 1. Memanggil dan mengeksplorasi dataset BreastCancer. 2. Menghapus variabel Id dan menangani missing value. 3. Membagi data latih dan data uji dengan proporsi 70:30. 4. Membentuk model Random Forest dengan mtry 2, 3, dan 5 serta jumlah pohon 200, 500, dan 1000. 5. Menampilkan OOB error sebagai evaluasi internal model. 6. Melakukan prediksi pada data uji dan menyusun confusion matrix serta menghitung metrik evaluasi (Accuracy, Precision, Recall, Specificity, dan F1-Score8). 7. Membandingkan hasil evaluasi kesembilan model dan variable importance*.

BAB IV HASIL DAN PEMBAHASAN

4.1 Library dan Data

library(ranger)
library(mlbench)
library(caret)

# Memuat data
data(BreastCancer, package = "mlbench")
bc <- BreastCancer
str(bc)
## '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 ...
summary(bc)
##          Id       Cl.thickness   Cell.size     Cell.shape  Marg.adhesion
##  Length   :699   1      :145   1      :384   1      :353   1      :407  
##  N.unique :645   5      :130   10     : 67   2      : 59   2      : 58  
##  N.blank  :  0   3      :108   3      : 52   10     : 58   3      : 58  
##  Min.nchar:  5   4      : 80   2      : 45   3      : 56   10     : 55  
##  Max.nchar:  8   10     : 69   4      : 40   4      : 44   4      : 33  
##                  2      : 50   5      : 30   5      : 34   8      : 25  
##                  (Other):117   (Other): 81   (Other): 95   (Other): 63  
##   Epith.c.size  Bare.nuclei   Bl.cromatin  Normal.nucleoli    Mitoses   
##  2      :386   1      :402   2      :166   1      :443     1      :579  
##  3      : 72   10     :132   3      :165   10     : 61     2      : 35  
##  4      : 48   2      : 30   1      :152   3      : 44     3      : 33  
##  1      : 47   5      : 30   7      : 73   2      : 36     10     : 14  
##  6      : 41   3      : 28   4      : 40   8      : 24     4      : 12  
##  5      : 39   (Other): 61   5      : 34   6      : 22     7      :  9  
##  (Other): 66   NAs    : 16   (Other): 69   (Other): 69     (Other): 17  
##        Class    
##  benign   :458  
##  malignant:241  
##                 
##                 
##                 
##                 
## 

Pada tahap awal penyelesaian batasan masalah, dilakukan pemanggilan dan pemeriksaan dataset BreastCancer dari paket mlbench. Setelah melakukan pemeriksaan struktur, dataset terdiri atas 699 observasi dan 11 variabel. Variabel tersebut mencakup satu variabel identitas, yaitu Id, sembilan variabel prediktor yang menggambarkan karakteristik sel, serta satu variabel respons Class yang terdiri atas dua kategori, yaitu benign dan malignant. Hasil fungsi summary() menunjukkan bahwa terdapat 458 observasi pada kelas benign dan 241 observasi pada kelas malignant. Selain itu, ditemukan 16 nilai hilang (missing values) pada variabel Bare.nuclei. Oleh karena itu, diperlukan penanganan nilai hilang sebelum pemodelan dilakukan. Variabel Id berfungsi sebagai identitas observasi, sehingga pada kasus ini variabel Id dihapus.

4.2 Persiapan Data

# Menghapus Id karena hanya merupakan identifier
bc$Id <- NULL

# Menghapus observasi yang mengandung missing value
bc <- na.omit(bc)

# Memastikan respons berupa factor
bc$Class <- droplevels(as.factor(bc$Class))

# Melihat kategori respons
levels(bc$Class)
## [1] "benign"    "malignant"
# Distribusi kelas
table(bc$Class)
## 
##    benign malignant 
##       444       239
prop.table(table(bc$Class))
## 
##    benign malignant 
## 0.6500732 0.3499268

Tahap selanjutnya adalah eksplorasi data. Pada tahapan ini dilakukan untuk mengetahui struktur, ukuran, dan karakteristik dataset BreastCancer. Berdasarkan hasil, dataset terdiri atas 699 pengamatan dan 11 variabel. Hasil ringkasan data menunjukkan bahwa variabel Bare.nuclei memiliki 16 missing value, sehingga perlu dilakukan penanganan sebelum pemodelan. Selain itu, variabel Id memiliki 645 nilai unik dan berfungsi sebagai identitas pengamatan, bukan sebagai prediktor dalam model. Kemudian, dilakukan pemeriksaan distribusi kelas pada variabel Class. Hasilnya menunjukkan bahwa terdapat 458 pengamatan pada kelas benign dan 241 pengamatan pada kelas malignant. Distribusi tersebut menunjukkan bahwa jumlah pengamatan pada kelas benign lebih banyak dibandingkan kelas malignant, sehingga data memiliki distribusi kelas yang tidak seimbang.

4.3 Penanganan Missing Value

# Membagi data training dan testing (70% training dan 30% testing)
set.seed(234)
idx.cls <- createDataPartition(bc$Class, p = 0.70, list = FALSE)
bc.train <- bc[idx.cls, ]
bc.test <- bc[-idx.cls, ]

# Memeriksa ukuran data
dim(bc.train)
## [1] 479  10
dim(bc.test)
## [1] 204  10
# Distribusi kelas pada training dan testing
table(bc.train$Class)
## 
##    benign malignant 
##       311       168
table(bc.test$Class)
## 
##    benign malignant 
##       133        71

Pada tahap selanjutnya, dilakukan pembagian dataset menjadi data training dan data testing dengan proporsi 70:30 menggunakan fungsi createDataPartition() serta menetapkan set.seed(234) agar pembagian data dapat direproduksi. Hasil pembagian menunjukkan bahwa data training terdiri atas 490 observasi, sedangkan data testing terdiri atas 209 observasi. Data training memiliki 321 observasi kelas benign dan 169 kelas malignant. Sementara itu, data testing terdiri atas 137 observasi kelas benign dan 72 kelas malignant. Data training digunakan untuk membangun model, sedangkan data testing digunakan untuk menguji kemampuan prediksi model.

4.4 Kombinasi Parameter

mtry.set  <- c(2, 3, 5)
trees.set <- c(200, 500, 1000)

grid <- expand.grid(mtry = mtry.set, num.trees = trees.set)
grid$Model <- paste0("mtry", grid$mtry, "_tree", grid$num.trees)
grid
##   mtry num.trees          Model
## 1    2       200  mtry2_tree200
## 2    3       200  mtry3_tree200
## 3    5       200  mtry5_tree200
## 4    2       500  mtry2_tree500
## 5    3       500  mtry3_tree500
## 6    5       500  mtry5_tree500
## 7    2      1000 mtry2_tree1000
## 8    3      1000 mtry3_tree1000
## 9    5      1000 mtry5_tree1000
# Wadah penyimpan hasil
hasil.eval <- data.frame()
list.model <- list()
list.cm    <- list()
list.imp   <- list()

Pada tahap ini, dilakukan penentuan kombinasi parameter yang akan digunakan dalam pembentukan model Random Forest. Parameter yang digunakan terdiri atas mtry sebesar 2, 3, dan 5 serta jumlah pohon (num.trees) sebanyak 200, 500, dan 1.000. Kombinasi kedua parameter tersebut menghasilkan sembilan skenario model yang berbeda. Seluruh skenario akan digunakan untuk melihat pengaruh kombinasi parameter terhadap kinerja model Random Forest dalam melakukan klasifikasi.

4.5 Prediksi data testing

# Bentuk model, evaluasi OOB & data testing
# ---------------------------------------------------------
for (i in seq_len(nrow(grid))) {
  
  m  <- grid$mtry[i]
  nt <- grid$num.trees[i]
  nm <- grid$Model[i]
  
  # Membentuk Random Forest
  set.seed(234)
  rf <- ranger(
    Class ~ ., data = bc.train,
    num.trees       = nt,
    mtry            = m,
    min.node.size   = 1,
    replace         = TRUE,
    sample.fraction = 1,
    importance      = "permutation",
    seed            = 234
  )
  
  # Tampilkan bentuk model
  cat("\n==================================================\n")
  cat("Model:", nm, "\n")
  cat("==================================================\n")
  print(rf)
  
  # Prediksi data testing
  pred <- predict(rf, data = bc.test)$predictions
  pred <- factor(pred, levels = levels(bc.test$Class))
  
  # Confusion matrix (kelas positif = malignant)
  cm  <- confusionMatrix(data = pred, reference = bc.test$Class,
                         positive = "malignant")
  tab <- table(Aktual = bc.test$Class, Prediksi = pred)
  
  TN <- tab["benign", "benign"]
  FP <- tab["benign", "malignant"]
  FN <- tab["malignant", "benign"]
  TP <- tab["malignant", "malignant"]
  
  Accuracy    <- (TP + TN) / (TP + TN + FP + FN)
  Precision   <- TP / (TP + FP)
  Recall      <- TP / (TP + FN)
  Specificity <- TN / (TN + FP)
  F1          <- 2 * (Precision * Recall) / (Precision + Recall)
  
  hasil.eval <- rbind(
    hasil.eval,
    data.frame(
      Model       = nm,
      mtry        = m,
      num.trees   = nt,
      OOB_Error   = rf$prediction.error,
      TN = TN, FP = FP, FN = FN, TP = TP,
      Accuracy, Precision, Recall, Specificity,
      F1_Score    = F1
    )
  )
  
  list.model[[nm]] <- rf
  list.cm[[nm]]    <- cm
  list.imp[[nm]]   <- sort(rf$variable.importance, decreasing = TRUE)
}
## 
## ==================================================
## Model: mtry2_tree200 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  200 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             2 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry3_tree200 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  200 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             3 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.71 % 
## 
## ==================================================
## Model: mtry5_tree200 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  200 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             5 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry2_tree500 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  500 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             2 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry3_tree500 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  500 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             3 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry5_tree500 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  500 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             5 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry2_tree1000 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  1000 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             2 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.92 % 
## 
## ==================================================
## Model: mtry3_tree1000 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  1000 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             3 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.71 % 
## 
## ==================================================
## Model: mtry5_tree1000 
## ==================================================
## Ranger result
## 
## Call:
##  ranger(Class ~ ., data = bc.train, num.trees = nt, mtry = m,      min.node.size = 1, replace = TRUE, sample.fraction = 1, importance = "permutation",      seed = 234) 
## 
## Type:                             Classification 
## Number of trees:                  1000 
## Sample size:                      479 
## Number of independent variables:  9 
## Mtry:                             5 
## Target node size:                 1 
## Variable importance mode:         permutation 
## Splitrule:                        gini 
## OOB prediction error:             2.71 %

Berdasarkan hasil pembentukan sembilan model Random Forest dengan kombinasi parameter yang berbeda, diketahui bahwa seluruh model menggunakan 9 variabel prediktor dan ukuran sampel sebanyak 479 observasi. Hasil menunjukkan bahwa nilai Out-of-Bag (OOB) prediction error berkisar antara 2,71% hingga 2,92%. Nilai kesalahan terendah sebesar 2,71% diperoleh pada model mtry3_tree200, mtry3_tree1000, dan mtry5_tree1000. Sementara itu, model lainnya menghasilkan nilai kesalahan sebesar 2,92%. Hal ini menunjukkan bahwa ketiga model tersebut memiliki tingkat kesalahan prediksi yang lebih rendah dibandingkan model lainnya berdasarkan nilai OOB.

4.6 Evaluasi OOB

oob.tabel <- hasil.eval[, c("Model", "mtry", "num.trees", "OOB_Error")]
oob.tabel$OOB_Accuracy <- 1 - oob.tabel$OOB_Error
print(oob.tabel, row.names = FALSE)
##           Model mtry num.trees  OOB_Error OOB_Accuracy
##   mtry2_tree200    2       200 0.02922756    0.9707724
##   mtry3_tree200    3       200 0.02713987    0.9728601
##   mtry5_tree200    5       200 0.02922756    0.9707724
##   mtry2_tree500    2       500 0.02922756    0.9707724
##   mtry3_tree500    3       500 0.02922756    0.9707724
##   mtry5_tree500    5       500 0.02922756    0.9707724
##  mtry2_tree1000    2      1000 0.02922756    0.9707724
##  mtry3_tree1000    3      1000 0.02713987    0.9728601
##  mtry5_tree1000    5      1000 0.02713987    0.9728601
# Confusion matrix OOB tiap model
for (nm in names(list.model)) {
  cat("\n== OOB Confusion Matrix:", nm, "==\n")
  print(list.model[[nm]]$confusion.matrix)
}
## 
## == OOB Confusion Matrix: mtry2_tree200 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry3_tree200 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      5       163
## 
## == OOB Confusion Matrix: mtry5_tree200 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry2_tree500 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry3_tree500 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry5_tree500 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry2_tree1000 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      6       162
## 
## == OOB Confusion Matrix: mtry3_tree1000 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      5       163
## 
## == OOB Confusion Matrix: mtry5_tree1000 ==
##            predicted
## true        benign malignant
##   benign       303         8
##   malignant      5       163
# OOB error dalam bentuk matriks (baris = mtry, kolom = num.trees)
oob.matriks <- tapply(hasil.eval$OOB_Error,
                      list(mtry = hasil.eval$mtry,
                           num.trees = hasil.eval$num.trees),
                      mean)
round(oob.matriks, 4)
##     num.trees
## mtry    200    500   1000
##    2 0.0292 0.0292 0.0292
##    3 0.0271 0.0292 0.0271
##    5 0.0292 0.0292 0.0271

Berdasarkan hasil evaluasi OOB (Out-of-Bag) terhadap sembilan model Random Forest, diperoleh nilai OOB Error berkisar antara 2,71% hingga 2,92%, dengan OOB Accuracy sebesar 97,08% hingga 97,29%. Nilai OOB Error terendah sebesar 2,71% diperoleh pada model mtry3_tree200, mtry3_tree1000, dan mtry5_tree1000. Hasil confusion matrix menunjukkan bahwa seluruh model mampu mengklasifikasikan sebagian besar observasi dengan benar, yaitu sebanyak 303 observasi kelas benign dan 162–163 observasi kelas malignant. Sementara itu, kesalahan klasifikasi terdiri atas 8 observasi benign yang diprediksi sebagai malignant dan 5–6 observasi malignant yang diprediksi sebagai benign. Berdasarkan matriks kombinasi parameter, nilai OOB Error cenderung sama pada setiap kombinasi mtry dan num.trees, sehingga perubahan jumlah pohon dan banyaknya variabel yang digunakan pada setiap pemisahan belum menunjukkan perbedaan kinerja yang signifikan. Dengan demikian, ketiga model dengan OOB Error sebesar 2,71% memberikan hasil terbaik berdasarkan evaluasi internal model.

4.7 Menghitung Ukuran Evaluasi Klasifikasi

# ---------------------------------------------------------
# Confusion matrix & ukuran evaluasi data testing
# ---------------------------------------------------------
# Confusion matrix lengkap tiap model
for (nm in names(list.cm)) {
  cat("\n== Confusion Matrix Data Testing:", nm, "==\n")
  print(list.cm[[nm]])
}
## 
## == Confusion Matrix Data Testing: mtry2_tree200 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       130         1
##   malignant      3        70
##                                           
##                Accuracy : 0.9804          
##                  95% CI : (0.9506, 0.9946)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9571          
##                                           
##  Mcnemar's Test P-Value : 0.6171          
##                                           
##             Sensitivity : 0.9859          
##             Specificity : 0.9774          
##          Pos Pred Value : 0.9589          
##          Neg Pred Value : 0.9924          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3431          
##    Detection Prevalence : 0.3578          
##       Balanced Accuracy : 0.9817          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry3_tree200 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       130         3
##   malignant      3        68
##                                           
##                Accuracy : 0.9706          
##                  95% CI : (0.9371, 0.9891)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9352          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9577          
##             Specificity : 0.9774          
##          Pos Pred Value : 0.9577          
##          Neg Pred Value : 0.9774          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3333          
##    Detection Prevalence : 0.3480          
##       Balanced Accuracy : 0.9676          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry5_tree200 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         4
##   malignant      4        67
##                                           
##                Accuracy : 0.9608          
##                  95% CI : (0.9242, 0.9829)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9136          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9437          
##             Specificity : 0.9699          
##          Pos Pred Value : 0.9437          
##          Neg Pred Value : 0.9699          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3284          
##    Detection Prevalence : 0.3480          
##       Balanced Accuracy : 0.9568          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry2_tree500 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         1
##   malignant      4        70
##                                          
##                Accuracy : 0.9755         
##                  95% CI : (0.9437, 0.992)
##     No Information Rate : 0.652          
##     P-Value [Acc > NIR] : <2e-16         
##                                          
##                   Kappa : 0.9465         
##                                          
##  Mcnemar's Test P-Value : 0.3711         
##                                          
##             Sensitivity : 0.9859         
##             Specificity : 0.9699         
##          Pos Pred Value : 0.9459         
##          Neg Pred Value : 0.9923         
##              Prevalence : 0.3480         
##          Detection Rate : 0.3431         
##    Detection Prevalence : 0.3627         
##       Balanced Accuracy : 0.9779         
##                                          
##        'Positive' Class : malignant      
##                                          
## 
## == Confusion Matrix Data Testing: mtry3_tree500 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       130         3
##   malignant      3        68
##                                           
##                Accuracy : 0.9706          
##                  95% CI : (0.9371, 0.9891)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9352          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9577          
##             Specificity : 0.9774          
##          Pos Pred Value : 0.9577          
##          Neg Pred Value : 0.9774          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3333          
##    Detection Prevalence : 0.3480          
##       Balanced Accuracy : 0.9676          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry5_tree500 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         4
##   malignant      4        67
##                                           
##                Accuracy : 0.9608          
##                  95% CI : (0.9242, 0.9829)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9136          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9437          
##             Specificity : 0.9699          
##          Pos Pred Value : 0.9437          
##          Neg Pred Value : 0.9699          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3284          
##    Detection Prevalence : 0.3480          
##       Balanced Accuracy : 0.9568          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry2_tree1000 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         2
##   malignant      4        69
##                                           
##                Accuracy : 0.9706          
##                  95% CI : (0.9371, 0.9891)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9356          
##                                           
##  Mcnemar's Test P-Value : 0.6831          
##                                           
##             Sensitivity : 0.9718          
##             Specificity : 0.9699          
##          Pos Pred Value : 0.9452          
##          Neg Pred Value : 0.9847          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3382          
##    Detection Prevalence : 0.3578          
##       Balanced Accuracy : 0.9709          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry3_tree1000 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         3
##   malignant      4        68
##                                           
##                Accuracy : 0.9657          
##                  95% CI : (0.9306, 0.9861)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9246          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9577          
##             Specificity : 0.9699          
##          Pos Pred Value : 0.9444          
##          Neg Pred Value : 0.9773          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3333          
##    Detection Prevalence : 0.3529          
##       Balanced Accuracy : 0.9638          
##                                           
##        'Positive' Class : malignant       
##                                           
## 
## == Confusion Matrix Data Testing: mtry5_tree1000 ==
## Confusion Matrix and Statistics
## 
##            Reference
## Prediction  benign malignant
##   benign       129         5
##   malignant      4        66
##                                           
##                Accuracy : 0.9559          
##                  95% CI : (0.9179, 0.9796)
##     No Information Rate : 0.652           
##     P-Value [Acc > NIR] : <2e-16          
##                                           
##                   Kappa : 0.9025          
##                                           
##  Mcnemar's Test P-Value : 1               
##                                           
##             Sensitivity : 0.9296          
##             Specificity : 0.9699          
##          Pos Pred Value : 0.9429          
##          Neg Pred Value : 0.9627          
##              Prevalence : 0.3480          
##          Detection Rate : 0.3235          
##    Detection Prevalence : 0.3431          
##       Balanced Accuracy : 0.9498          
##                                           
##        'Positive' Class : malignant       
## 
# Ringkasan ukuran evaluasi
evaluasi.test <- hasil.eval[, c("Model", "mtry", "num.trees",
                                "TN", "FP", "FN", "TP",
                                "Accuracy", "Precision", "Recall",
                                "Specificity", "F1_Score")]
evaluasi.test[, 8:12] <- round(evaluasi.test[, 8:12], 4)
print(evaluasi.test, row.names = FALSE)
##           Model mtry num.trees  TN FP FN TP Accuracy Precision Recall
##   mtry2_tree200    2       200 130  3  1 70   0.9804    0.9589 0.9859
##   mtry3_tree200    3       200 130  3  3 68   0.9706    0.9577 0.9577
##   mtry5_tree200    5       200 129  4  4 67   0.9608    0.9437 0.9437
##   mtry2_tree500    2       500 129  4  1 70   0.9755    0.9459 0.9859
##   mtry3_tree500    3       500 130  3  3 68   0.9706    0.9577 0.9577
##   mtry5_tree500    5       500 129  4  4 67   0.9608    0.9437 0.9437
##  mtry2_tree1000    2      1000 129  4  2 69   0.9706    0.9452 0.9718
##  mtry3_tree1000    3      1000 129  4  3 68   0.9657    0.9444 0.9577
##  mtry5_tree1000    5      1000 129  4  5 66   0.9559    0.9429 0.9296
##  Specificity F1_Score
##       0.9774   0.9722
##       0.9774   0.9577
##       0.9699   0.9437
##       0.9699   0.9655
##       0.9774   0.9577
##       0.9699   0.9437
##       0.9699   0.9583
##       0.9699   0.9510
##       0.9699   0.9362
# Gabungan OOB error + performa testing
ringkasan <- hasil.eval
ringkasan[, c("OOB_Error", "Accuracy", "Precision",
              "Recall", "Specificity", "F1_Score")] <-
  round(ringkasan[, c("OOB_Error", "Accuracy", "Precision",
                      "Recall", "Specificity", "F1_Score")], 4)
print(ringkasan, row.names = FALSE)
##           Model mtry num.trees OOB_Error  TN FP FN TP Accuracy Precision Recall
##   mtry2_tree200    2       200    0.0292 130  3  1 70   0.9804    0.9589 0.9859
##   mtry3_tree200    3       200    0.0271 130  3  3 68   0.9706    0.9577 0.9577
##   mtry5_tree200    5       200    0.0292 129  4  4 67   0.9608    0.9437 0.9437
##   mtry2_tree500    2       500    0.0292 129  4  1 70   0.9755    0.9459 0.9859
##   mtry3_tree500    3       500    0.0292 130  3  3 68   0.9706    0.9577 0.9577
##   mtry5_tree500    5       500    0.0292 129  4  4 67   0.9608    0.9437 0.9437
##  mtry2_tree1000    2      1000    0.0292 129  4  2 69   0.9706    0.9452 0.9718
##  mtry3_tree1000    3      1000    0.0271 129  4  3 68   0.9657    0.9444 0.9577
##  mtry5_tree1000    5      1000    0.0271 129  4  5 66   0.9559    0.9429 0.9296
##  Specificity F1_Score
##       0.9774   0.9722
##       0.9774   0.9577
##       0.9699   0.9437
##       0.9699   0.9655
##       0.9774   0.9577
##       0.9699   0.9437
##       0.9699   0.9583
##       0.9699   0.9510
##       0.9699   0.9362
# Model terbaik (F1 tertinggi, lalu OOB error terendah)
urut        <- order(-hasil.eval$F1_Score, hasil.eval$OOB_Error)
model.best  <- hasil.eval$Model[urut[1]]
cat("\nModel terbaik berdasarkan F1-score (tie-break OOB error):",
    model.best, "\n")
## 
## Model terbaik berdasarkan F1-score (tie-break OOB error): mtry2_tree200

Berdasarkan hasil evaluasi sembilan model Random Forest menggunakan data testing, diperoleh nilai akurasi berkisar antara 95,59% hingga 98,04%. Model mtry2_tree200 menghasilkan kinerja terbaik dengan akurasi sebesar 98,04%, precision sebesar 95,89%, sensitivity atau recall sebesar 98,59%, specificity sebesar 97,74%, dan F1-score sebesar 97,22%. Berdasarkan confusion matrix, model tersebut mampu mengklasifikasikan 130 observasi kelas benign dan 70 observasi kelas malignant dengan benar. Sementara itu, terdapat tiga observasi kelas benign yang salah diklasifikasikan sebagai malignant dan satu observasi kelas malignant yang salah diklasifikasikan sebagai benign. Selain itu, nilai Kappa sebesar 0,9571 menunjukkan tingkat kesesuaian klasifikasi yang sangat tinggi. Meskipun beberapa model lainnya memiliki nilai OOB Error yang lebih rendah, model mtry2_tree200 tetap terpilih sebagai model terbaik karena menghasilkan F1-score tertinggi dengan mempertimbangkan nilai OOB Error sebagai kriteria tambahan.

4.8 Variable Importance

# Variable Importance
# ---------------------------------------------------------
# Tabel importance semua model (baris = variabel, kolom = model)
var.names <- names(list.model[[1]]$variable.importance)
imp.tabel <- sapply(list.model, function(x) x$variable.importance[var.names])
imp.tabel <- round(imp.tabel, 5)
imp.tabel[order(-rowMeans(imp.tabel)), ]
##                 mtry2_tree200 mtry3_tree200 mtry5_tree200 mtry2_tree500
## Bare.nuclei           0.08392       0.09722       0.12594       0.08050
## Cell.size             0.07872       0.09165       0.08978       0.07726
## Cell.shape            0.06097       0.06281       0.04271       0.06297
## Cl.thickness          0.02449       0.02779       0.02326       0.02675
## Marg.adhesion         0.01925       0.01913       0.02090       0.01911
## Normal.nucleoli       0.02045       0.01597       0.02166       0.02184
## Bl.cromatin           0.02148       0.01795       0.01424       0.02188
## Epith.c.size          0.01174       0.00988       0.00862       0.01322
## Mitoses               0.00375       0.00369       0.00264       0.00309
##                 mtry3_tree500 mtry5_tree500 mtry2_tree1000 mtry3_tree1000
## Bare.nuclei           0.09912       0.12428        0.08173        0.10028
## Cell.size             0.08533       0.09090        0.07789        0.08554
## Cell.shape            0.06512       0.04597        0.06259        0.05926
## Cl.thickness          0.02603       0.02168        0.02631        0.02481
## Marg.adhesion         0.01934       0.01954        0.01889        0.01953
## Normal.nucleoli       0.01479       0.02030        0.01995        0.01649
## Bl.cromatin           0.01881       0.01527        0.02050        0.01920
## Epith.c.size          0.01095       0.00931        0.01401        0.01186
## Mitoses               0.00321       0.00302        0.00335        0.00319
##                 mtry5_tree1000
## Bare.nuclei            0.12140
## Cell.size              0.09109
## Cell.shape             0.04381
## Cl.thickness           0.02269
## Marg.adhesion          0.01887
## Normal.nucleoli        0.02078
## Bl.cromatin            0.01619
## Epith.c.size           0.00974
## Mitoses                0.00322
# Barplot importance per model (9 grafik, 3 x 3)
par(mfrow = c(3, 3), mar = c(7, 4, 3, 1))
for (nm in names(list.imp)) {
  barplot(list.imp[[nm]], las = 2, cex.names = 0.8,
          main = paste("VarImp -", nm),
          ylab = "Permutation Importance")
}

par(mfrow = c(1, 1))

# Barplot importance model terbaik
par(mar = c(8, 4, 3, 1))
imp.best   <- list.imp[[model.best]]
warna.bar  <- colorRampPalette(c("deeppink3", "pink"))(length(imp.best))
barplot(imp.best, las = 2,
        col = warna.bar, border = NA,
        main = paste("Variable Importance - Model Terbaik (", model.best, ")"),
        ylab = "Permutation Importance")

Berdasarkan hasil variable importance dari kesembilan model, variabel Bare.nuclei,Cell.size, dan Cell.shape merupakan tiga variabel yang paling berpengaruh dalam proses klasifikasi tumor jinak dan ganas, dengan Bare.nuclei sebagai variabel yang paling dominan. Sementara itu, variabel lainnya memiliki tingkat kepentingan yang relatif rendah, bahkan Mitoses menjadi variabel dengan pengaruh paling kecil. Perubahan jumlah pohon (num.trees) dari 200 hingga 1000 tidak menunjukkan perubahan yang berarti terhadap nilai importance, sehingga hasilnya cenderung stabil. Namun, perubahan nilai mtry memengaruhi besarnya nilai kepentingan beberapa variabel, terutama Bare.nuclei yang cenderung meningkat seiring bertambahnya nilai mtry. Pada model terbaik, yaitu mtry 2 dengan 200 pohon, ketiga variabel utama tersebut tetap menjadi variabel yang paling berpengaruh dalam menentukan hasil klasifikasi.

4.9 Visualisasi Perbandingan

warna <- c("red", "blue", "darkgreen")

# Menyiapkan data OOB Error
data.oob <- lapply(mtry.set, function(m) {
  sub <- hasil.eval[hasil.eval$mtry == m, ]
  sub <- sub[order(sub$num.trees), ]
  sub$OOB_Error
})

# Membuat grafik
matplot(trees.set, do.call(cbind, data.oob),
        type = "b", pch = 16, lty = 1,
        col = warna, lwd = 2,
        xlab = "num.trees",
        ylab = "OOB Error",
        main = "OOB Error: mtry x num.trees")

legend("topright",
       legend = paste("mtry =", mtry.set),
       col = warna, pch = 16, lwd = 2, bty = "n")

Berdasarkan hasil evaluasi, nilai OOB Error terendah sebesar 0,0271 diperoleh pada kombinasi mtry= 3 dengan 200 pohon dan mtry = 5 dengan 1000 pohon. Sementara itu, berdasarkan nilai F1-Score pada data testing, model terbaik diperoleh pada kombinasi mtry = 2 dengan 200 pohon, yaitu sebesar 0,972. Hasil ini menunjukkan bahwa model tersebut memiliki kemampuan klasifikasi paling baik dibandingkan kombinasi parameter lainnya. Selain itu, penambahan jumlah pohon pada mtry = 2 justru diikuti sedikit penurunan nilai F1-Score. Dengan demikian, kombinasi mtry = 2 dan num.trees = 200 dipilih sebagai model terbaik karena menghasilkan nilai F1-Score tertinggi pada data testing.

BAB V KESIMPULAN

5.1 Kesimpulan

Berdasarkan praktikum yang telah dilakukan, metode Random Forest dan Double Random Forest merupakan metode ensemble learning berbasis Decision Tree yang menggabungkan beberapa pohon keputusan untuk menghasilkan prediksi yang lebih baik. Random Forest membangun sejumlah pohon keputusan menggunakan sampel data dan pemilihan variabel secara acak, sedangkan Double Random Forest mengembangkan pendekatan tersebut melalui dua tahap pembentukan model untuk meningkatkan kemampuan prediksi.

Implementasi metode Random Forest dan Double Random Forest dapat dilakukan menggunakan bahasa pemrograman R dengan bantuan beberapa paket pendukung. Kedua metode tersebut dapat diterapkan pada permasalahan klasifikasi untuk memprediksi kelas suatu observasi maupun regresi untuk memprediksi nilai numerik. Dalam penerapannya, diperlukan penyesuaian parameter model agar proses pembentukan pohon keputusan dapat berjalan dengan baik dan menghasilkan prediksi yang optimal.

Evaluasi performa model dapat dilakukan dengan menggunakan beberapa ukuran, seperti Accuracy, Precision, Recall, Specificity, dan F1-Score untuk klasifikasi, serta ukuran kesalahan prediksi untuk regresi. Selain itu, nilai Out-of-Bag (OOB) error dapat digunakan untuk memperkirakan tingkat kesalahan model selama proses pelatihan tanpa memerlukan data validasi tambahan. Melalui hasil evaluasi tersebut, performa Random Forest dan Double Random Forest dapat dianalisis dan dibandingkan untuk mengetahui kemampuan masing-masing metode dalam menghasilkan prediksi.

Berdasarkan hasil penerapan Random Forest pada data BreastCancer, diperoleh sembilan kombinasi parameter berdasarkan variasi nilai mtry dan num.trees. Hasil evaluasi menunjukkan bahwa model dengan mtry = 2 dan num.trees = 200 memberikan performa terbaik pada data testing, dengan nilai Accuracy sebesar 98,04% dan F1-Score sebesar 97,22%. Sementara itu, nilai OOB error terendah sebesar 2,71% diperoleh pada beberapa kombinasi parameter lainnya. Hasil variable importance juga menunjukkan bahwa Bare.nuclei, Cell.size, dan Cell.shape merupakan variabel yang paling berpengaruh dalam proses klasifikasi.

DAFTAR PUSTAKA

Direktorat Jenderal Pendidikan Tinggi, Riset, dan Teknologi. (n.d.). Modul Ajar Kecerdasan Buatan Lanjut: Evaluasi Model Machine Learning. LMS SPADA Indonesia. https://lmsspada.kemdiktisaintek.go.id/mod/resource/view.php?id=156825

Fransiska, H. (2026). Modul Praktikum Machine Learning dan Modern Prediction. Bengkulu: Universitas Bengkulu.

Habibi, R., Fahira, & Dwiyanti, Z. A. (2023). Prediksi diagnosa kehamilan menggunakan algoritma C4.5 dan Random Forest. Penerbit Buku Pedia.

Istiana, N., & Mustafiril, A. (2023). Perbandingan Metode Klasifikasi pada Data dengan Imbalance Class dan Missing Value. Jurnal Informatika, 101-108.

Jollyta, D., Prihandoko, Hajjah, A., Haerani, E., & Siddik, M. (2023). Algoritma klasifikasi untuk pemula: Solusi Python dan RapidMiner. Deepublish Digital.

Mola, S. A., Rumlaklak, N. D., & Polly, D. P. (2024). Analisis sentimen dengan metode Random Forest. Kaizen Media Publishing.

Romahdoni, M. R. (2024). Mengenal algoritma Random Forest: Cara mudah menerapkan machine learning di bisnis UMKM. Penerbit Serasi Media Teknologi.

Saputri, T. A., Firmansyah, A. U., & Purnomo, H. (2025). Menguasai teknik dasar machine learning. Wawasan Ilmu.