Machine learning (pembelajaran mesin) adalah cabang kecerdasan buatan yang memungkinkan komputer mempelajari pola dari data dan menggunakannya untuk membuat prediksi atau keputusan tanpa harus diprogram secara eksplisit untuk setiap aturan. Pada pembelajaran terawasi (supervised learning), model dilatih menggunakan data yang telah memiliki respons, baik berupa nilai numerik (regresi) maupun kategori (klasifikasi) (Fransiska, 2026). Seiring perkembangan teknologi digital, jumlah dan kompleksitas data terus meningkat sehingga mendorong lahirnya model-model prediksi yang semakin beragam, mulai dari model sederhana yang mengasumsikan hubungan linear hingga model yang mampu mengenali pola nonlinear yang sulit diidentifikasi secara manual. Salah satu algoritma klasifikasi yang paling sederhana dan banyak digunakan adalah K-Nearest Neighbor (k-NN), yaitu algoritma berbasis instance yang menentukan kelas suatu data berdasarkan kelas mayoritas dari tetangga terdekatnya (Zubairi dkk., 2025).
Algoritma k-NN termasuk metode non-parametrik karena tidak mengasumsikan bentuk distribusi data tertentu dan tidak membentuk model eksplisit pada tahap pelatihan, melainkan menyimpan seluruh data latih dan menunda komputasi hingga ada data baru yang akan diprediksi (Fransiska, 2026). Kinerja k-NN sangat dipengaruhi oleh dua hal, yaitu skala variabel dan pemilihan nilai \(k\). Karena kedekatan data dihitung menggunakan jarak, variabel dengan rentang nilai yang besar dapat mendominasi perhitungan sehingga diperlukan normalisasi (Fatah & Sujatmiko, 2026). Nilai \(k\) yang terlalu kecil membuat model sensitif terhadap derau (noise), sedangkan nilai \(k\) yang terlalu besar membuat batas keputusan terlalu halus dan informasi lokal hilang (Zubairi dkk., 2025).
class dan caret?ggplot2?class dan
caret.ggplot2.Adapun batasan masalah yang ditentukan pada penelitian ini, yaitu
melakukan pemodelan klasifikasi terhadap data medis riil Wisconsin
Breast Cancer Database yang dimuat melalui paket
mlbench. Tujuan pemodelan adalah mendeteksi secara akurat
apakah tumor payudara tergolong jinak (benign) atau ganas
(malignant). Instruksi pengerjaan meliputi: (1) memuat dataset
dengan perintah data(BreastCancer, package = "mlbench");
(2) melakukan tahapan pra-pemrosesan data; (3) membagi data menjadi 70%
data latih dan 30% data uji dengan inisialisasi
set.seed(12323); (4) melakukan pemodelan klasifikasi k-NN
untuk nilai \(k \in \{3, 5, 7, 9,
11\}\); dan (5) menyusun tabel perbandingan metrik evaluasi
(Accuracy, Sensitivity, Specificity) serta
menyimpulkan nilai \(k\) paling optimal
dengan mempertimbangkan pentingnya meminimalkan kesalahan diagnosis sel
kanker ganas (False Negative).
Algoritma K-Nearest Neighbors (k-NN) pertama kali digagas oleh Fix dan Hodges (1951) sebagai metode klasifikasi non-parametrik, dan landasan teoritis konvergensinya dibuktikan oleh Cover dan Hart (1967). Berbeda dengan algoritma parametrik yang mengasumsikan bentuk distribusi data tertentu, k-NN termasuk instance-based learning atau lazy learning, yaitu tidak membentuk fungsi perantara pada tahap pelatihan melainkan menyimpan seluruh data latih dan menunda komputasi hingga terdapat data baru yang hendak diprediksi (Fransiska, 2026).
Diberikan himpunan data latih \(D = \{(x_1, y_1), (x_2, y_2), \dots, (x_n, y_n)\}\) dengan \(x_i \in \mathbb{R}^p\) merupakan vektor fitur berdimensi \(p\) dan \(y_i \in \{1, 2, \dots, C\}\) adalah label kelas. Untuk suatu data uji dengan vektor fitur \(x_0\), algoritma mengidentifikasi himpunan \(N_k(x_0)\) yang memuat \(k\) tetangga terdekat dari \(x_0\) berdasarkan ukuran jarak tertentu. Estimasi probabilitas posterior bahwa \(x_0\) tergolong ke kelas \(j\) adalah proporsi kelas \(j\) di antara tetangga terdekatnya (Fransiska, 2026):
\[ \hat{P}(Y = j \mid X = x_0) = \frac{1}{k} \sum_{i \in N_k(x_0)} I(y_i = j) \]
dengan \(I(\cdot)\) merupakan fungsi indikator yang bernilai 1 jika \(y_i = j\) dan 0 jika sebaliknya. Keputusan klasifikasi diambil berdasarkan suara terbanyak (majority voting):
\[ \hat{G}(x_0) = \underset{j \in \{1, 2, \dots, C\}}{\arg\max} \; \hat{P}(Y = j \mid X = x_0) \]
Cover dan Hart (1967) membuktikan bahwa ketika ukuran sampel \(n \to \infty\), probabilitas kesalahan tetangga terdekat tunggal (\(k = 1\)), yang dinotasikan \(R\), dibatasi oleh probabilitas kesalahan pengklasifikasi Bayes optimal \(R^*\) (Fransiska, 2026):
\[ R^* \le R \le R^*\left(2 - \frac{C}{C - 1}R^*\right) \le 2R^* \]
Artinya, secara asimtotik tingkat kesalahan aturan tetangga terdekat paling buruk tidak lebih dari dua kali lipat kesalahan pengklasifikasi Bayes.
Pemilihan nilai hiperparameter \(k\) mengendalikan keseimbangan antara bias dan varians (Fransiska, 2026). Nilai \(k\) kecil (misalnya \(k = 1\)) membuat batas keputusan sangat rumit dengan bias rendah tetapi varians tinggi, sehingga model sangat sensitif terhadap derau dan rentan overfitting. Sebaliknya, nilai \(k\) besar membuat batas keputusan sangat halus (oversmoothing) dengan varians rendah tetapi bias tinggi, sehingga model berpotensi underfitting karena keputusan lokal terdistorsi oleh kelas mayoritas secara global. Pemilihan \(k\) sebaiknya menyeimbangkan bias dan varians serta mempertimbangkan distribusi kelas (Fatah & Sujatmiko, 2026).
Pada klasifikasi biner, nilai \(k\) umumnya dipilih ganjil untuk menghindari kemungkinan jumlah suara yang sama pada proses voting. Nilai \(k\) yang optimal dapat dicari dengan membandingkan beberapa kandidat nilai \(k\) berdasarkan metrik evaluasi, misalnya \(k = 3, 5, 7\), atau melalui kurva tingkat kesalahan terhadap nilai \(k\) (Abrar dkk., 2023).
Jarak antara dua titik observasi \(x = (x_1, \dots, x_p)^\top\) dan \(y = (y_1, \dots, y_p)^\top\) dalam ruang fitur dapat dihitung dengan berbagai metrik jarak yang dirangkum pada Tabel 1 (Fransiska, 2026). Jarak Euclidean merupakan yang paling umum digunakan karena sederhana dan mudah dipahami (Zubairi dkk., 2025).
Tabel 1. Metrik Jarak pada k-NN
| Metrik Jarak | Rumus | Keterangan |
|---|---|---|
| Euclidean (\(L_2\)) | \(d(x, y) = \sqrt{\sum_{i=1}^{p}(x_i - y_i)^2}\) | Metrik geometris paling umum untuk variabel numerik kontinu |
| Manhattan (\(L_1\)) | \(d(x, y) = \sum_{i=1}^{p}\lvert x_i - y_i \rvert\) | Jumlah selisih mutlak; lebih tangguh terhadap pencilan |
| Minkowski (\(L_m\)) | \(d(x, y) = \left(\sum_{i=1}^{p}\lvert x_i - y_i \rvert^m\right)^{1/m},\; m \ge 1\) | Generalisasi; \(m = 1\) menghasilkan Manhattan dan \(m = 2\) menghasilkan Euclidean |
| Mahalanobis | \(d(x, y) = \sqrt{(x - y)^\top \Sigma^{-1}(x - y)}\) | Memperhitungkan matriks kovarians sehingga mengoreksi korelasi dan perbedaan skala |
| Hamming | \(d(x, y) = \frac{1}{p}\sum_{i=1}^{p} I(x_i \ne y_i)\) | Untuk data biner atau kategorik kualitatif |
Karena jarak Euclidean dan Manhattan menghitung selisih numerik secara langsung, variabel dengan rentang nilai besar akan mendominasi perhitungan jarak; tanpa normalisasi, fitur berdimensi besar merusak kinerja k-NN. Pada klasifikasi penyakit liver, penerapan normalisasi min-max terbukti meningkatkan akurasi k-NN dibandingkan percobaan tanpa normalisasi (Abrar dkk., 2023). Dua teknik penskalaan yang umum adalah (Fransiska, 2026):
\[ x_{scaled} = \frac{x - x_{min}}{x_{max} - x_{min}} \]
\[ z = \frac{x - \mu}{\sigma} \]
Jenis data yang digunakan dalam penelitian ini adalah data
kuantitatif, yaitu data berbentuk angka yang dapat diolah dan dianalisis
secara statistik. Sumber data yang digunakan adalah data medis riil
Wisconsin Breast Cancer Database (BreastCancer)
yang dimuat melalui paket mlbench pada perangkat lunak R,
sesuai dengan arahan modul praktikum (Fransiska, 2026). Dataset ini
terdiri dari 699 pengamatan dengan satu variabel pengenal
(Id), sembilan variabel prediktor hasil pemeriksaan sel
yang dinilai pada skala 1 sampai 10, dan satu variabel respons berupa
diagnosis tumor (Class) yang terdiri atas dua kelas, yaitu
jinak (benign) dan ganas (malignant).
Tabel 3. Variabel Penelitian
| No | Variabel | Keterangan | Tipe Data | Peran |
|---|---|---|---|---|
| 1 | Id | Nomor identitas sampel | Kategorik | Tidak digunakan |
| 2 | Cl.thickness | Ketebalan gumpalan sel (clump thickness) | Ordinal (1–10) | Prediktor |
| 3 | Cell.size | Keseragaman ukuran sel | Ordinal (1–10) | Prediktor |
| 4 | Cell.shape | Keseragaman bentuk sel | Ordinal (1–10) | Prediktor |
| 5 | Marg.adhesion | Daya rekat tepi sel (marginal adhesion) | Ordinal (1–10) | Prediktor |
| 6 | Epith.c.size | Ukuran sel epitel tunggal | Ordinal (1–10) | Prediktor |
| 7 | Bare.nuclei | Inti sel tanpa sitoplasma (bare nuclei) | Kategorik (1–10) | Prediktor |
| 8 | Bl.cromatin | Kromatin yang halus (bland chromatin) | Kategorik (1–10) | Prediktor |
| 9 | Normal.nucleoli | Nukleolus normal | Kategorik (1–10) | Prediktor |
| 10 | Mitoses | Tingkat pembelahan sel (mitosis) | Kategorik (1–10) | Prediktor |
| 11 | Class | Diagnosis tumor: benign (jinak) atau malignant (ganas) | Kategorik | Respons |
class
untuk algoritma k-NN, caret untuk confusion
matrix, ggplot2 untuk visualisasi,
mlbench untuk dataset, dan knitr untuk
menampilkan tabel.data(BreastCancer, package = "mlbench") dan memeriksa
struktur serta sebaran kelasnya.Id, menghapus pengamatan yang memuat missing
value, mengubah variabel respons menjadi faktor dan prediktor
menjadi numerik, serta menormalisasi prediktor dengan
Min-Max.set.seed(12323).knn() untuk
nilai \(k\) = 3, 5, 7, 9, dan 11.confusionMatrix() dengan kelas positif
malignant.Tahap awal adalah memanggil package yang dibutuhkan, yaitu
class untuk algoritma k-NN, caret untuk
confusion matrix, ggplot2 untuk visualisasi,
mlbench untuk dataset, dan knitr untuk
menampilkan tabel. Kemudian dataset BreastCancer dimuat
melalui paket mlbench dan diperiksa struktur serta sebaran
kelasnya.
library(class)
library(caret)
library(ggplot2)
library(mlbench)
library(knitr)
data(BreastCancer, package = "mlbench") # Memuat dataset
bc <- BreastCancer
str(bc) # Menampilkan struktur variabel## '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 ...
## 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
##
## benign malignant
## 458 241
Interpretasi:
Berdasarkan hasil pemeriksaan, dataset BreastCancer
terdiri atas 699 pengamatan dan 11 variabel, yaitu satu variabel
pengenal (Id), sembilan variabel prediktor, dan satu
variabel respons (Class). Kesembilan prediktor tersimpan
sebagai faktor atau faktor terurut (skala 1 sampai 10), bukan numerik,
sehingga perlu diubah menjadi numerik sebelum digunakan pada perhitungan
jarak. Variabel respons terdiri atas dua kelas dengan jumlah pengamatan
benign = 458, malignant = 241, sehingga kelas benign lebih
banyak daripada kelas malignant (proporsi malignant
sekitar 34,48%).
Pra-pemrosesan dilakukan dalam beberapa tahap, yaitu memeriksa
missing value, menghapus variabel Id karena hanya
berupa pengenal, menghapus pengamatan yang memuat missing
value, mengubah variabel respons menjadi faktor dan seluruh
prediktor menjadi numerik, kemudian menormalisasi prediktor menggunakan
Min-Max sesuai fungsi pada modul.
## Id Cl.thickness Cell.size Cell.shape Marg.adhesion
## 0 0 0 0 0
## Epith.c.size Bare.nuclei Bl.cromatin Normal.nucleoli Mitoses
## 0 16 0 0 0
## Class
## 0
# 2. Menghapus variabel Id (hanya pengenal, bukan prediktor)
bc$Id <- NULL
# 3. Menghapus pengamatan yang memuat missing value
bc <- na.omit(bc)
# 4. Respons menjadi faktor dan prediktor menjadi numerik
bc$Class <- droplevels(as.factor(bc$Class))
bc[, 1:9] <- lapply(bc[, 1:9], function(x) as.numeric(as.character(x)))
str(bc)## 'data.frame': 683 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 ...
## - attr(*, "na.action")= 'omit' Named int [1:16] 24 41 140 146 159 165 236 250 276 293 ...
## ..- attr(*, "names")= chr [1:16] "24" "41" "140" "146" ...
##
## benign malignant
## 444 239
##
## benign malignant
## 0.6500732 0.3499268
miss_df <- data.frame(Variabel = names(BreastCancer),
Missing = as.integer(colSums(is.na(BreastCancer))))
kable(miss_df, align = "lc",
caption = "Tabel 4. Jumlah Missing Value pada Setiap Variabel Sebelum Pra-pemrosesan")| Variabel | Missing |
|---|---|
| Id | 0 |
| Cl.thickness | 0 |
| Cell.size | 0 |
| Cell.shape | 0 |
| Marg.adhesion | 0 |
| Epith.c.size | 0 |
| Bare.nuclei | 16 |
| Bl.cromatin | 0 |
| Normal.nucleoli | 0 |
| Mitoses | 0 |
| Class | 0 |
# Mendefinisikan fungsi normalisasi Min-Max
min_max_norm <- function(x) {
return((x - min(x)) / (max(x) - min(x)))
}
# Menerapkan normalisasi pada 9 variabel prediktor (kolom 1 sampai 9)
bc_norm <- as.data.frame(lapply(bc[1:9], min_max_norm))
bc_norm$Class <- bc$Class # Menggabungkan kembali label kelas
summary(bc_norm) # Ringkasan statistik setelah normalisasi## Cl.thickness Cell.size Cell.shape Marg.adhesion
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.1111 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000
## Median :0.3333 Median :0.0000 Median :0.0000 Median :0.0000
## Mean :0.3825 Mean :0.2390 Mean :0.2461 Mean :0.2034
## 3rd Qu.:0.5556 3rd Qu.:0.4444 3rd Qu.:0.4444 3rd Qu.:0.3333
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.0000
## Epith.c.size Bare.nuclei Bl.cromatin Normal.nucleoli
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.1111 1st Qu.:0.0000 1st Qu.:0.1111 1st Qu.:0.0000
## Median :0.1111 Median :0.0000 Median :0.2222 Median :0.0000
## Mean :0.2483 Mean :0.2827 Mean :0.2717 Mean :0.2077
## 3rd Qu.:0.3333 3rd Qu.:0.5556 3rd Qu.:0.4444 3rd Qu.:0.3333
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.0000
## Mitoses Class
## Min. :0.00000 benign :444
## 1st Qu.:0.00000 malignant:239
## Median :0.00000
## Mean :0.06702
## 3rd Qu.:0.00000
## Max. :1.00000
Interpretasi:
Pemeriksaan missing value (Tabel 4) menunjukkan bahwa
variabel yang memuat data hilang adalah Bare.nuclei dengan total 16
nilai hilang. Setelah variabel Id dihapus dan pengamatan
yang memuat missing value dibuang, data berkurang dari 699
menjadi 683 pengamatan (16 pengamatan dihapus). Pada data yang telah
bersih, kelas benign berjumlah 444 pengamatan (65,01%) dan
kelas malignant berjumlah 239 pengamatan (34,99%), sehingga
data tidak seimbang secara moderat dan akurasi saja tidak cukup untuk
menilai model. Seluruh prediktor telah berupa numerik dengan rentang
nilai 1 sampai 10. Setelah normalisasi Min-Max, seluruh
prediktor berada pada rentang 0 sampai 1 (minimum 0 dan maksimum 1).
Karena seluruh prediktor aslinya sudah berskala sama (1 sampai 10),
dominasi satu variabel terhadap jarak sebenarnya relatif kecil;
normalisasi tetap diterapkan sesuai prosedur modul agar seluruh fitur
berkontribusi seimbang pada perhitungan jarak (Fatah & Sujatmiko,
2026).
Data dibagi menjadi 70% data latih dan 30% data uji menggunakan
pengambilan sampel acak dengan set.seed(12323) (NPM
ganjil). Matriks fitur prediktor dan vektor label kelas dipisahkan agar
sesuai dengan masukan fungsi knn().
set.seed(12323)
# Mengambil indeks sampel acak sebesar 70% dari total data
train_indices <- sample(seq_len(nrow(bc_norm)), size = round(0.70 * nrow(bc_norm)))
# Memisahkan matriks fitur prediktor
train_x <- bc_norm[train_indices, 1:9]
test_x <- bc_norm[-train_indices, 1:9]
# Memisahkan vektor label kelas
train_y <- bc_norm[train_indices, 10]
test_y <- bc_norm[-train_indices, 10]
cat("Dimensi Data Latih (Train):", nrow(train_x), "baris,", ncol(train_x), "fitur\n")## Dimensi Data Latih (Train): 478 baris, 9 fitur
## Dimensi Data Uji (Test) : 205 baris, 9 fitur
dist_df <- data.frame(
Kelas = levels(bc_norm$Class),
Latih = as.integer(table(train_y)),
Uji = as.integer(table(test_y))
)
dist_df$Persen_Latih <- dist_df$Latih / sum(dist_df$Latih) * 100
dist_df$Persen_Uji <- dist_df$Uji / sum(dist_df$Uji) * 100
kable(dist_df, digits = 2, align = "c",
format.args = list(decimal.mark = ","),
caption = "Tabel 5. Sebaran Kelas pada Data Latih dan Data Uji")| Kelas | Latih | Uji | Persen_Latih | Persen_Uji |
|---|---|---|---|---|
| benign | 315 | 129 | 65,9 | 62,93 |
| malignant | 163 | 76 | 34,1 | 37,07 |
Interpretasi:
Berdasarkan hasil pembagian data, dari 683 pengamatan diperoleh 478 data latih (69,99%) dan 205 data uji (30,01%), masing-masing dengan 9 fitur. Data latih digunakan sebagai gudang tetangga (algoritma k-NN tidak melatih parameter), sedangkan data uji digunakan untuk mengukur kemampuan model pada data baru. Pada Tabel 5, proporsi kelas malignant pada data latih sebesar 34,10% dan pada data uji sebesar 37,07%; kedua proporsi relatif mirip sehingga pembagian acak cukup mewakili sebaran kelas pada data asli. Pada data uji terdapat 76 tumor ganas, sehingga setiap satu tumor ganas yang terlewat (false negative) menurunkan sensitivitas sekitar 1,32 poin.
Pemodelan k-NN dilakukan menggunakan fungsi knn() dari
paket class dengan masukan data latih (train),
data uji (test), label data latih (cl), dan
jumlah tetangga (k). Nilai \(k\) yang dibandingkan adalah 3, 5, 7, 9,
dan 11 (seluruhnya ganjil untuk menghindari voting seri pada
klasifikasi biner). set.seed(12323) dipanggil sebelum
setiap pemodelan karena knn() memutus voting seri
secara acak. Evaluasi menggunakan confusionMatrix() dengan
kelas positif malignant sehingga sensitivitas mengukur
kemampuan mendeteksi tumor ganas.
# k = 3
set.seed(12323)
prediksi_k3 <- knn(train = train_x, test = test_x, cl = train_y, k = 3)
head(prediksi_k3, 10) # 10 prediksi pertama## [1] benign benign malignant benign benign benign malignant
## [8] malignant benign benign
## Levels: benign malignant
# Confusion matrix dan statistik evaluasi (kelas positif: malignant)
cm_k3 <- confusionMatrix(data = prediksi_k3, reference = test_y, positive = "malignant")
cm_k3## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 126 0
## malignant 3 76
##
## Accuracy : 0.9854
## 95% CI : (0.9578, 0.997)
## No Information Rate : 0.6293
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9689
##
## Mcnemar's Test P-Value : 0.2482
##
## Sensitivity : 1.0000
## Specificity : 0.9767
## Pos Pred Value : 0.9620
## Neg Pred Value : 1.0000
## Prevalence : 0.3707
## Detection Rate : 0.3707
## Detection Prevalence : 0.3854
## Balanced Accuracy : 0.9884
##
## 'Positive' Class : malignant
##
Interpretasi:
Berdasarkan hasil klasifikasi menggunakan metode K-Nearest Neighbor (KNN) dengan \(k=3\), dari 205 data uji sebanyak 202 data berhasil diklasifikasikan dengan benar, yaitu 126 data benign dan 76 data malignant. Sementara itu, terdapat 3 data benign yang salah diprediksi sebagai malignant dan tidak terdapat kesalahan false negative. Model menghasilkan accuracy sebesar 98,54%, sensitivity 100%, specificity 97,67%, positive predictive value 96,20%, dan Kappa 0,9689. Hasil ini menunjukkan bahwa model memiliki kinerja klasifikasi yang sangat baik karena mampu mendeteksi seluruh data malignant dengan tingkat ketepatan prediksi yang tinggi.
# k = 5
set.seed(12323)
prediksi_k5 <- knn(train = train_x, test = test_x, cl = train_y, k = 5)
head(prediksi_k5, 10) # 10 prediksi pertama## [1] benign benign malignant benign benign benign malignant
## [8] malignant benign benign
## Levels: benign malignant
# Confusion matrix dan statistik evaluasi (kelas positif: malignant)
cm_k5 <- confusionMatrix(data = prediksi_k5, reference = test_y, positive = "malignant")
cm_k5## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 126 1
## malignant 3 75
##
## Accuracy : 0.9805
## 95% CI : (0.9508, 0.9947)
## No Information Rate : 0.6293
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9584
##
## Mcnemar's Test P-Value : 0.6171
##
## Sensitivity : 0.9868
## Specificity : 0.9767
## Pos Pred Value : 0.9615
## Neg Pred Value : 0.9921
## Prevalence : 0.3707
## Detection Rate : 0.3659
## Detection Prevalence : 0.3805
## Balanced Accuracy : 0.9818
##
## 'Positive' Class : malignant
##
Interpretasi:
Berdasarkan hasil klasifikasi KNN dengan \(k=5\), dari 205 data uji sebanyak 201 data berhasil diklasifikasikan dengan benar, yaitu 126 data benign dan 75 data malignant. Sementara itu, terdapat 3 data benign yang salah diprediksi sebagai malignant dan 1 data malignant yang salah diprediksi sebagai benign. Model menghasilkan accuracy sebesar 98,05%, sensitivity 98,68%, specificity 97,67%, positive predictive value 96,15%, dan Kappa 0,9584. Hasil ini menunjukkan bahwa model memiliki kinerja klasifikasi yang sangat baik. Namun, performanya sedikit lebih rendah dibandingkan \(k=3\), karena akurasi menurun dan terdapat satu data malignant yang tidak terdeteksi (false negative).
# k = 7
set.seed(12323)
prediksi_k7 <- knn(train = train_x, test = test_x, cl = train_y, k = 7)
head(prediksi_k7, 10) # 10 prediksi pertama## [1] benign benign malignant benign benign benign malignant
## [8] malignant benign benign
## Levels: benign malignant
# Confusion matrix dan statistik evaluasi (kelas positif: malignant)
cm_k7 <- confusionMatrix(data = prediksi_k7, reference = test_y, positive = "malignant")
cm_k7## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 125 2
## malignant 4 74
##
## Accuracy : 0.9707
## 95% CI : (0.9374, 0.9892)
## No Information Rate : 0.6293
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9376
##
## Mcnemar's Test P-Value : 0.6831
##
## Sensitivity : 0.9737
## Specificity : 0.9690
## Pos Pred Value : 0.9487
## Neg Pred Value : 0.9843
## Prevalence : 0.3707
## Detection Rate : 0.3610
## Detection Prevalence : 0.3805
## Balanced Accuracy : 0.9713
##
## 'Positive' Class : malignant
##
Interpretasi:
Berdasarkan hasil klasifikasi KNN dengan \(k=7\), dari 205 data uji sebanyak 199 data berhasil diklasifikasikan dengan benar, yaitu 125 data benign dan 74 data malignant. Sementara itu, terdapat 4 data benign yang salah diprediksi sebagai malignant dan 2 data malignant yang salah diprediksi sebagai benign. Model menghasilkan accuracy sebesar 97,07%, sensitivity 97,37%, specificity 96,90%, positive predictive value 94,87%, dan Kappa 0,9376. Hasil ini menunjukkan bahwa model memiliki kinerja klasifikasi yang sangat baik, tetapi mengalami penurunan performa dibandingkan \(k=3\) dan \(k=5\), yang ditandai dengan penurunan akurasi serta bertambahnya jumlah kesalahan klasifikasi.
# k = 9
set.seed(12323)
prediksi_k9 <- knn(train = train_x, test = test_x, cl = train_y, k = 9)
head(prediksi_k9, 10) # 10 prediksi pertama## [1] benign benign malignant benign benign benign malignant
## [8] malignant benign benign
## Levels: benign malignant
# Confusion matrix dan statistik evaluasi (kelas positif: malignant)
cm_k9 <- confusionMatrix(data = prediksi_k9, reference = test_y, positive = "malignant")
cm_k9## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 125 2
## malignant 4 74
##
## Accuracy : 0.9707
## 95% CI : (0.9374, 0.9892)
## No Information Rate : 0.6293
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9376
##
## Mcnemar's Test P-Value : 0.6831
##
## Sensitivity : 0.9737
## Specificity : 0.9690
## Pos Pred Value : 0.9487
## Neg Pred Value : 0.9843
## Prevalence : 0.3707
## Detection Rate : 0.3610
## Detection Prevalence : 0.3805
## Balanced Accuracy : 0.9713
##
## 'Positive' Class : malignant
##
Interpretasi:
Berdasarkan hasil klasifikasi menggunakan metode K-Nearest Neighbor (KNN) dengan \(k=9\), dari 205 data uji sebanyak 199 data berhasil diklasifikasikan dengan benar, yaitu 125 data benign dan 74 data malignant. Sementara itu, terdapat 4 data benign yang salah diprediksi sebagai malignant dan 2 data malignant yang salah diprediksi sebagai benign. Model menghasilkan accuracy sebesar 97,07%, sensitivity 97,37%, specificity 96,90%, positive predictive value 94,87%, dan Kappa 0,9376. Hasil ini menunjukkan bahwa model memiliki kinerja klasifikasi yang sangat baik, tetapi belum mengalami peningkatan dibandingkan \(k=7\) karena seluruh nilai evaluasi dan jumlah kesalahan klasifikasinya sama.
# k = 11
set.seed(12323)
prediksi_k11 <- knn(train = train_x, test = test_x, cl = train_y, k = 11)
head(prediksi_k11, 10) # 10 prediksi pertama## [1] benign benign malignant benign benign benign malignant
## [8] malignant benign benign
## Levels: benign malignant
# Confusion matrix dan statistik evaluasi (kelas positif: malignant)
cm_k11 <- confusionMatrix(data = prediksi_k11, reference = test_y, positive = "malignant")
cm_k11## Confusion Matrix and Statistics
##
## Reference
## Prediction benign malignant
## benign 125 2
## malignant 4 74
##
## Accuracy : 0.9707
## 95% CI : (0.9374, 0.9892)
## No Information Rate : 0.6293
## P-Value [Acc > NIR] : <2e-16
##
## Kappa : 0.9376
##
## Mcnemar's Test P-Value : 0.6831
##
## Sensitivity : 0.9737
## Specificity : 0.9690
## Pos Pred Value : 0.9487
## Neg Pred Value : 0.9843
## Prevalence : 0.3707
## Detection Rate : 0.3610
## Detection Prevalence : 0.3805
## Balanced Accuracy : 0.9713
##
## 'Positive' Class : malignant
##
Interpretasi:
Berdasarkan hasil klasifikasi menggunakan metode K-Nearest Neighbor (KNN) dengan \(k=11\), dari 205 data uji sebanyak 199 data berhasil diklasifikasikan dengan benar, yaitu 125 data benign dan 74 data malignant. Sementara itu, terdapat 4 data benign yang salah diprediksi sebagai malignant dan 2 data malignant yang salah diprediksi sebagai benign. Model menghasilkan accuracy sebesar 97,07%, sensitivity 97,37%, specificity 96,90%, positive predictive value 94,87%, dan Kappa 0,9376. Hasil ini menunjukkan bahwa model memiliki kinerja klasifikasi yang sangat baik, tetapi belum mengalami peningkatan performa dibandingkan \(k=7\) dan \(k=9\), karena seluruh nilai evaluasi dan jumlah kesalahan klasifikasinya sama.
Hasil kelima model disusun dalam satu tabel perbandingan yang memuat jumlah true positive (TP), false negative (FN), false positive (FP), true negative (TN), serta Accuracy, Sensitivity, Specificity, dan Positive Predictive Value (PPV).
k_values <- c(3, 5, 7, 9, 11)
cm_list <- setNames(list(cm_k3, cm_k5, cm_k7, cm_k9, cm_k11), as.character(k_values))
hasil_df <- do.call(rbind, lapply(k_values, function(k) {
e <- ekstrak_cm(cm_list[[as.character(k)]])
data.frame(k = k, TP = e$TP, FN = e$FN, FP = e$FP, TN = e$TN,
Accuracy = e$Acc, Sensitivity = e$Sens,
Specificity = e$Spec, PPV = e$PPV)
}))
kable(hasil_df, digits = 4, align = "c",
format.args = list(decimal.mark = ","),
caption = "Tabel 6. Perbandingan Metrik Evaluasi k-NN untuk Setiap Nilai k pada Data Uji")| k | TP | FN | FP | TN | Accuracy | Sensitivity | Specificity | PPV |
|---|---|---|---|---|---|---|---|---|
| 3 | 76 | 0 | 3 | 126 | 0,9854 | 1,0000 | 0,9767 | 0,9620 |
| 5 | 75 | 1 | 3 | 126 | 0,9805 | 0,9868 | 0,9767 | 0,9615 |
| 7 | 74 | 2 | 4 | 125 | 0,9707 | 0,9737 | 0,9690 | 0,9487 |
| 9 | 74 | 2 | 4 | 125 | 0,9707 | 0,9737 | 0,9690 | 0,9487 |
| 11 | 74 | 2 | 4 | 125 | 0,9707 | 0,9737 | 0,9690 | 0,9487 |
Interpretasi:
Berdasarkan Tabel 6, akurasi pada data uji berkisar antara 97,07% sampai 98,54%, sensitivitas berkisar antara 97,37% sampai 100,00%, dan spesifisitas berkisar antara 96,90% sampai 97,67%. Jumlah false negative untuk \(k\) = 3, 5, 7, 9, dan 11 berturut-turut adalah 0, 1, 2, 2, 2, sedangkan jumlah false positive berturut-turut 3, 3, 4, 4, 4. Jumlah false negative terkecil sebesar 0 diperoleh pada \(k\) = 3, dan akurasi tertinggi sebesar 98,54% diperoleh pada \(k\) = 3. Karena data uji berjumlah 205 pengamatan, satu kesalahan klasifikasi mengubah akurasi sekitar 0,49 poin, sehingga selisih antar nilai \(k\) perlu dibaca dengan hati-hati.
long_df <- data.frame(
k = rep(hasil_df$k, 3),
Metrik = rep(c("Accuracy", "Sensitivity", "Specificity"), each = nrow(hasil_df)),
Nilai = c(hasil_df$Accuracy, hasil_df$Sensitivity, hasil_df$Specificity)
)
ggplot(long_df, aes(x = k, y = Nilai, color = Metrik, shape = Metrik)) +
geom_line(linewidth = 1.1) +
geom_point(size = 3) +
scale_x_continuous(breaks = k_values) +
scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
labs(
title = "Pengaruh Nilai k terhadap Kinerja Klasifikasi k-NN",
subtitle = paste0("Data Uji Wisconsin Breast Cancer (n = ", n_uji, ")"),
x = "Jumlah Tetangga Terdekat (k)",
y = "Nilai Metrik"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5),
panel.grid.minor = element_blank()
)Interpretasi:
Kurva di atas memperlihatkan perubahan akurasi, sensitivitas, dan spesifisitas terhadap nilai \(k\). Garis yang relatif mendatar menunjukkan bahwa kinerja model tidak banyak berubah ketika \(k\) dinaikkan dari 3 hingga 11, sedangkan perubahan yang tajam menunjukkan bahwa model sensitif terhadap pilihan \(k\). Apabila sensitivitas menurun pada \(k\) yang lebih besar, hal itu menandakan model mulai lebih condong ke kelas mayoritas (benign) sehingga lebih banyak tumor ganas yang terlewat; sebaliknya, penurunan spesifisitas menandakan lebih banyak tumor jinak yang salah diprediksi ganas.
err_df <- data.frame(
k = rep(hasil_df$k, 2),
Jenis = rep(c("False Negative (ganas diprediksi jinak)",
"False Positive (jinak diprediksi ganas)"), each = nrow(hasil_df)),
Jumlah = c(hasil_df$FN, hasil_df$FP)
)
ggplot(err_df, aes(x = factor(k), y = Jumlah, fill = Jenis)) +
geom_col(position = position_dodge(width = 0.8), width = 0.7) +
geom_text(aes(label = Jumlah), position = position_dodge(width = 0.8), vjust = -0.4, size = 3.5) +
scale_fill_manual(values = c("#d95f02", "#2b5c8f")) +
labs(
title = "Jumlah Kesalahan Klasifikasi menurut Nilai k",
x = "Jumlah Tetangga Terdekat (k)",
y = "Jumlah Kesalahan",
fill = NULL
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "bottom",
panel.grid.minor = element_blank()
)Interpretasi:
Diagram batang memisahkan dua jenis kesalahan. False negative (batang jingga) adalah tumor ganas yang diprediksi jinak dan merupakan kesalahan paling berbahaya karena pasien tidak segera mendapat penanganan, sedangkan false positive (batang biru) adalah tumor jinak yang diprediksi ganas, yang umumnya berujung pada pemeriksaan lanjutan. Pada nilai \(k\) = 3, jumlah false negative paling sedikit yaitu 0.
Penentuan nilai \(k\) optimal. Karena kesalahan diagnosis sel ganas (false negative) paling merugikan secara klinis, pemilihan \(k\) memakai urutan kriteria berikut: (1) jumlah false negative terkecil (sensitivitas tertinggi); jika terdapat beberapa nilai \(k\) yang sama, dipilih (2) akurasi tertinggi, kemudian (3) spesifisitas tertinggi, dan terakhir (4) \(k\) terbesar karena batas keputusan yang lebih halus lebih tahan terhadap derau (varians lebih rendah). Berdasarkan kriteria tersebut, nilai \(k\) paling optimal adalah \(k\) = 3, dengan false negative sebanyak 0, sensitivitas 100,00%, spesifisitas 97,67%, akurasi 98,54%, dan PPV 96,20%. Nilai k tersebut unggul secara tegas berdasarkan kriteria yang digunakan. Nilai k optimal ini juga termasuk nilai k dengan akurasi tertinggi, sehingga tidak ada pertentangan antara kriteria klinis (meminimalkan false negative) dan akurasi keseluruhan. Tidak ada tumor ganas yang terlewat pada model ini.
K-Nearest Neighbors (k-NN) adalah metode klasifikasi non-parametrik dalam supervised learning yang tidak mengasumsikan bentuk distribusi data tertentu. Algoritma ini termasuk instance-based learning atau lazy learning, yaitu tidak membentuk model eksplisit pada tahap pelatihan, melainkan menyimpan seluruh data latih dan menunda komputasi hingga ada data baru yang akan diprediksi. Secara matematis, untuk suatu data uji \(x_0\) algoritma mencari himpunan \(N_k(x_0)\) yang berisi \(k\) tetangga terdekat, menghitung probabilitas posterior kelas \(j\) sebagai proporsi kelas tersebut di antara tetangganya, lalu menetapkan kelas dengan probabilitas terbesar melalui majority voting. Prinsip kerjanya adalah menghitung jarak data uji ke seluruh data latih, mengurutkannya, mengambil \(k\) data terdekat, kemudian menentukan kelas berdasarkan suara terbanyak.
Penskalaan fitur (feature scaling) penting dipahami karena k-NN bekerja berdasarkan metrik jarak seperti Euclidean dan Manhattan yang menghitung selisih numerik secara langsung, sehingga variabel dengan rentang nilai besar akan mendominasi perhitungan jarak dan variabel berskala kecil kehilangan pengaruhnya. Akibatnya tetangga terdekat yang terpilih menjadi bias terhadap variabel berskala besar dan kinerja model menurun. Oleh karena itu, pra-pemrosesan wajib menyertakan penskalaan, yaitu normalisasi Min-Max yang mengubah nilai ke interval \([0, 1]\) atau standarisasi Z-Score yang mengubah data menjadi berrata-rata 0 dan berstandar deviasi 1, sehingga seluruh fitur memberi kontribusi yang seimbang pada perhitungan jarak.
Algoritma k-NN dapat diimplementasikan secara terstruktur di R
menggunakan pustaka class dan caret melalui
tahapan yang berurutan. Tahapan tersebut adalah memuat data,
pra-pemrosesan (menangani missing value, mengubah tipe data,
dan menormalisasi prediktor), membagi data menjadi data latih dan data
uji dengan set.seed() agar hasil dapat direproduksi,
memisahkan matriks fitur dan vektor label, membentuk model dengan fungsi
knn() yang memerlukan data latih, data uji, label latih,
dan nilai \(k\), kemudian mengevaluasi
hasil prediksi menggunakan fungsi confusionMatrix() dari
paket caret.
Performa model klasifikasi dievaluasi dengan confusion matrix, yaitu tabel yang membandingkan kelas aktual dan kelas prediksi sehingga menghasilkan True Positive, True Negative, False Positive, dan False Negative. Dari tabel tersebut dihitung akurasi (proporsi seluruh prediksi yang benar), sensitivitas (kemampuan mendeteksi kasus positif), spesifisitas (kemampuan mengenali kasus negatif), dan Positive Predictive Value (proporsi prediksi positif yang benar). Pada kasus diagnosis medis, jenis kesalahan tidak bernilai sama, sehingga akurasi saja tidak cukup dan sensitivitas perlu diperhatikan agar kasus positif yang sebenarnya tidak terlewat (false negative).
Eksplorasi optimasi hiperparameter nilai \(k\) dilakukan dengan membangun model untuk
beberapa kandidat nilai \(k\), lalu
membandingkan metrik evaluasinya pada data uji, biasanya dengan
perulangan (looping) yang menyimpan hasil ke dalam tabel. Nilai
\(k\) perlu dipilih dengan
memperhatikan kompromi bias dan varians: \(k\) yang terlalu kecil rentan
overfitting karena sensitif terhadap derau, sedangkan \(k\) yang terlalu besar rentan
underfitting karena batas keputusan terlalu halus. Hasil
perbandingan divisualisasikan dengan paket ggplot2 melalui
kurva hubungan nilai \(k\) dan metrik
kinerja (misalnya geom_line() dan
geom_point()), sehingga nilai \(k\) optimal dapat ditentukan secara visual
dan terukur sesuai tujuan analisis.
Berdasarkan hasil pemodelan k-NN pada data Wisconsin Breast
Cancer yang telah dibersihkan (683 pengamatan; 478 data latih dan
205 data uji dengan set.seed(12323)), kelima nilai \(k\) (3, 5, 7, 9, dan 11) menghasilkan
akurasi antara 97,07% sampai 98,54%, sensitivitas antara 97,37% sampai
100,00%, dan spesifisitas antara 96,90% sampai 97,67%. Dengan
mempertimbangkan pentingnya meminimalkan false negative, nilai
\(k\) paling optimal adalah \(k\) = 3 dengan 0 false negative,
sensitivitas 100,00%, spesifisitas 97,67%, dan akurasi 98,54%. Perbedaan
kinerja antar nilai k relatif kecil sehingga k-NN cukup stabil terhadap
pilihan k pada data ini, namun pilihan k tetap perlu mengutamakan false
negative yang paling sedikit. Dengan demikian, k-NN dengan data yang
dinormalisasi mampu membedakan tumor jinak dan ganas dengan baik, dan
model sebaiknya dipakai sebagai alat bantu skrining yang tetap perlu
didukung pemeriksaan klinis.
Pada praktikum Machine Learning berikutnya, disarankan agar praktikan
lebih teliti dalam memasukkan dan mengolah data menggunakan RStudio,
terutama dalam penggunaan sintaks serta interpretasi hasil k-NN. Untuk
penelitian selanjutnya, pemilihan nilai \(k\) dapat dilakukan dengan validasi silang
(misalnya melalui fungsi train() pada paket
caret) agar lebih stabil, pembagian data dapat dibuat
berstrata agar proporsi kelas terjaga, evaluasi dapat dilengkapi kurva
ROC dan AUC, serta kinerja k-NN dapat dibandingkan dengan metode lain
seperti Random Forest atau Artificial Neural
Network.
Abrar, I. N., Abdullah, A., & Sucipto. (2023). Klasifikasi penyakit liver menggunakan metode elbow untuk menentukan K optimal pada algoritma K-Nearest Neighbor (K-NN). Jurnal SISFOKOM (Sistem Informasi dan Komputer), 12(2), 218–228.
Fatah, Z., & Sujatmiko, M. H. (2026). Analisis kinerja dan akurasi algoritma K-Nearest Neighbor pada dataset heart disease. JAMASTIKA, 5(1), 252–258.
Fransiska, H. (2026). Modul Praktikum Machine Learning. Universitas Bengkulu.
Perkasa, A. A., Zendrato, E. S., Pratama, I., & Simamora, H. (2026). Klasifikasi laju pertumbuhan penduduk antar provinsi di Indonesia menggunakan metode K-Nearest Neighbor. MATHunesa: Jurnal Ilmiah Matematika, 14(2), 271–278.
Zubairi, A., Hermanto, Santoso, H., Samad, A., & Homaidi, A. (2025). Implementasi algoritma K-Nearest Neighbor untuk penentuan status kanker. JUSTIFY: Jurnal Sistem Informasi Ibrahimy, 3(2), 115–121.