Algoritma K-Nearest Neighbors (KNN) dengan R

K-nearest Neighbors KNN R
K-nearest Neighbors KNN R

Konsep K-Nearest Neighbors (KNN)

K-Nearest Neighbors (KNN) merupakan metode populer dalam bidang machine learning. Konsep dasar algoritma KNN adalah mencari k-nearest neighbors atau k tetangga terdekat dari suatu observasi berdasarkan jarak euclidean ataupun ukuran jarak lainnya. KNN umumnya digunakan untuk pemodelan klasifikasi namun dapat digunakan juga pada pemodelan regresi.

Dalam model klasifikasi, algoritma KNN menghitung jarak antara amatan yang akan diklasifikasikan dengan dataset yang sudah memiliki label kelas, dan memilih k tetangga terdekat dengan amatan tersebut berdasarkan jarak tersebut. Setelah itu, dari k tetangga tersebut, dilihat kelas apa yang paling banyak (mayoritas) menjadi tetangga terdekatnya. Hasil akhir yaitu mengklasifikasikan amatan tersebut masuk ke dalam kelas mayoritas yang diperoleh.

Prinsip Dasar dan Proses KNN

  • Jarak: KNN mengukur kesamaan antara data dengan menghitung jarak antara titik data dalam ruang fitur. Jarak ini dapat diukur menggunakan berbagai metrik, seperti Euclidean, Manhattan, atau Minkowski distance.
  • K-Neighbors: “K” dalam KNN menunjukkan jumlah tetangga terdekat yang akan digunakan untuk membuat prediksi. Algoritma ini memeriksa label k tetangga terdekat suatu titik data dan menentukan label mayoritas sebagai prediksi.

Langkah-Langkah KNN

  1. Menentukan Parameter k: Pemilihan nilai k adalah bagian kritis dari algoritma KNN. Nilai k yang terlalu kecil dapat menyebabkan model rentan terhadap noise, sedangkan nilai k yang besar dapat mengaburkan batas keputusan yang sebenarnya.
  2. Menghitung Jarak: Algoritma menghitung jarak antara titik data yang akan diprediksi dengan semua titik data dalam set pelatihan.
  3. Menentukan Tetangga Terdekat: Algoritma memilih k tetangga terdekat berdasarkan jarak yang dihitung sebelumnya.
  4. Menentukan Kelas Prediksi: kelas mayoritas dari tetangga terdekat digunakan sebagai prediksi untuk titik data yang dipertanyakan.
Ilustrasi K Nearest Neighbors (KNN)
Ilustrasi K Nearest Neighbors (KNN)

Ilustrasi di atas menunjukkan data historis mengenai karakteristik anak ayam yang baru menetas menurut dua kriteria yaitu tinggi dan bobot. Warna biru menunjukkan anak ayam betina dan orange anak ayam jantan. Secara visual dapat dilihat bahwa kecenderungan anak ayam jantan memiliki bobot dan tinggi yang lebih besar dibandingkan anak ayam betina. Pertanyaannya adalah jika kita memiliki 3 anak ayam yang baru menetas (misal amatan denganw arna merah), dan belum diketahui jenis kelaminnya bagaimana kita dapat memprediksi jenis kelamin dari ketiga anak ayam tersebut.

Penentuan kelas prediksi pada algoritma KNN diukur dari kedekatan jarak data baru tersebut dengan tetangga terdekatnya. Sebagai contoh, berdasarkan k=3 tetangga terdekat, anak ayam a kemungkinan akan diprediksi sebagai pejantan karena tiga tetangga terdekatnya adalah pejantan. Begitu pula anak ayam b akan diprediksi sebagai betina. Untuk anak ayam c, 2 dari 3 tetangga terdekatnya adalah pejantan maka akan diprediksi sebagai pejantan.

Untuk memperoleh model KNN yang baik, parameter penting yang perlu ditentukan adalah nilai k, atau jumlah tetangga terdekat yang akan digunakan. Nilai k tentu saja akan berbeda tergantung dari permasalahan dan data yang dihadapi. Penentuan nilai k optimal ini dapat dilakukan melalui proses tuning hyperparameter.

Penyiapan Data

Dataset yang digunakan memiliki format csv sehingga kita dapat membacanya menggunakan fungsi read.csv. Peubah respon atau kelas pada dataset tersimpan pada kolom quality dengan nilai LOW atau HIGH. Sementara kolom lainnya seluruhnya bertipe numerik.

R

data <- read.csv("wine-quality-binary.csv")

str(data)
# OUTPUT

'data.frame':	1143 obs. of  13 variables:
 $ id                  : int  1 2 3 4 5 6 7 8 9 10 ...
 $ fixed.acidity       : num  7.4 7.8 7.8 11.2 7.4 7.4 7.9 7.3 7.8 6.7 ...
 $ volatile.acidity    : num  0.7 0.88 0.76 0.28 0.7 0.66 0.6 0.65 0.58 0.58 ...
 $ citric.acid         : num  0 0 0.04 0.56 0 0 0.06 0 0.02 0.08 ...
 $ residual.sugar      : num  1.9 2.6 2.3 1.9 1.9 1.8 1.6 1.2 2 1.8 ...
 $ chlorides           : num  0.076 0.098 0.092 0.075 0.076 0.075 0.069 0.065 0.073 0.097 ...
 $ free.sulfur.dioxide : num  11 25 15 17 11 13 15 15 9 15 ...
 $ total.sulfur.dioxide: num  34 67 54 60 34 40 59 21 18 65 ...
 $ density             : num  0.998 0.997 0.997 0.998 0.998 ...
 $ pH                  : num  3.51 3.2 3.26 3.16 3.51 3.51 3.3 3.39 3.36 3.28 ...
 $ sulphates           : num  0.56 0.68 0.65 0.58 0.56 0.56 0.46 0.47 0.57 0.54 ...
 $ alcohol             : num  9.4 9.8 9.8 9.8 9.4 9.4 9.4 10 9.5 9.2 ...
 $ quality             : chr  "LOW" "LOW" "LOW" "HIGH" ...

Dari struktur di atas dapat pula kita lihat terdapat kolom id. kolom ini hanya berisi urutan data dari 1, 2… sampai 1143 sesuai banyaknya data dan bukanlah peubah yang berkaitan dengan kelas data sehingga bisa kita hapus saja. Kita juga sebaiknya merubah tipe dari peubah respon menjadi factor. Hal ini nantinya dapat mempermudah pengukuran pada proses-proses selanjutnya.

Pada kode di bawah ini, kita juga menampilkan banyaknya data serta komposisinya menurut peubah quality. Dari total 1143 observasi, terdapat 621 yang masuk sebagai kelas "HIGH" dan 522 sebagai kelas "LOW". Berdasarkan proporsinya kedua kelas relatif seimbang yaitu dengan komposisi sekitar 54% data dengan kelas "HIGH" berbanding 46% data dengan kelas "LOW".

R

# menghapus kolom `id`
data$id <- NULL

# mengubah tipe kolom `quality` menjadi factor
data$quality <- as.factor(data$quality)

# melihat jumlah dan komposisi masing-masing kategori
quality <- data.frame(table(data$quality))

quality$Prop <- round(quality$Freq/sum(quality$Freq), 3)

print(quality)
# OUTPUT

  Var1 Freq  Prop
1 HIGH  621 0.543
2  LOW  522 0.457

Pembagian Data Latih dan Data Uji

Membagi data menjadi data latih dan data uji merupakan tahapan penting dalam algoritma machine learning termasuk KNN. Pembagian ini diperlukan agar algoritma dapat diuji menggunakan data yang belum pernah dilihat selama proses pelatihan. Pada saat pelatihan, data yang digunakan hanya data latih saja. Adapun data uji nantinya digunakan untuk mengukur performa algoritma. Hal ini penting agar pengukuran performa lebih “fair” karena menggunakan data baru yang belum pernah digunakan untuk proses pelatihan.

Pembagian data pada bahasa R dapat dilakukan menggunakan fungsi createDataPartition dari pustaka caret. Proporsi banyaknya data untuk pelatihan dan pengujian dapat ditentukan dengan mengatur parameter p. Pada contoh ini, kita akan menggunakan 70% dataset sebagai data latih dan 30% sisanya menjadi data uji.

R

# Membagi data sebagai data Latih dan data uji

library(caret)

set.seed(100)  # mengatur seed tertentu untuk hasil yang dapat direproduksi

# data latih = 70%, data uji = 30%
trainIndex <- createDataPartition(data$quality, p = 0.70, list = FALSE, times = 1)

# Buat data latih dan data uji berdasarkan indeks yang dihasilkan
data.train <- data[trainIndex, ]
data.test <- data[-trainIndex, ]

# melihat komposisi setiap kelas pada data train dan test
cbind("train" = table(data.train$quality), "test" = table(data.test$quality))
# OUTPUT

	train	test
HIGH	435	186
LOW	366	156

Features Scaling

KNN merupakan model berbasis jarak sehingga ukuran jarak merupakan hal penting. Perbedaan skala data antar fitur akan mempengaruhi performa model yang dihasilkan. Untuk menghindari hal tersebut, disarankan untuk selalu melakukan scaling terhadap fitur, khususnya ketika perbedaan skala sangat besar. Metode scaling yang dapat digunakan salah satunya adalah normalisasi (MinMax Scaling), yaitu membuat setiap fitur memiliki nilai minimum 0 dan maksimum 1.

Proses scaling pada R dapat menggunakan fungsi preProcess dari pustaka caret. Parameter method="range" menunjukkan scaling dengan metode normalisasi. Dapat dilihat dari output di bawah ini, bahwa fitur hasil scaling seluruhnya memiliki nilai minimum 0 dan maksimum 1.

R

# Menerapkan scaling menggunakan preProcess untuk semua fitur numerik
preproc.params <- preProcess(data.train[, -12], method = "range")

scaled.data.train <- predict(preproc.params, data.train[, -12])
scaled.data.test <- predict(preproc.params, data.test[, -12])

summary(scaled.data.train)
# OUTPUT

 fixed.acidity    volatile.acidity  citric.acid     ...      alcohol    
 Min.   :0.0000   Min.   :0.0000   Min.   :0.000    ...    Min.   :0.0000 
 1st Qu.:0.2091   1st Qu.:0.1849   1st Qu.:0.090    ...    1st Qu.:0.1846
 Median :0.2818   Median :0.2740   Median :0.260    ...    Median :0.2769  
 Mean   :0.3143   Mean   :0.2838   Mean   :0.271    ...    Mean   :0.3124  
 3rd Qu.:0.3818   3rd Qu.:0.3562   3rd Qu.:0.420    ...    3rd Qu.:0.4154
 Max.   :1.0000   Max.   :1.0000   Max.   :1.000    ...    Max.   :1.0000 

KNN dengan paket ‘class’

Untuk membuat prediksi berdasarkan algoritma KNN kita dapat menggunakan fungsi knn dari pustaka class. Fungsi knn langsung menghasilkan output berupa prediksi dari kelas pada data uji yang diberikan. Pada contoh berikut, kita melakukan prediksi data uji berdasarkan data latih dengan mengambil nilai k=5.

R

library(class)

pred.knn <- knn(train=scaled.data.train, test=scaled.data.test, 
             cl=data.train$quality, k=5)

# Menampilkan hasil prediksi
print(pred.knn)

# Evaluasi hasil prediksi pada data uji
conf_matrix <- confusionMatrix(pred.knn, data.test$quality)
print(conf_matrix)
# OUTPUT

  [1] LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  LOW  HIGH HIGH LOW 
 [16] LOW  LOW  LOW  LOW  HIGH LOW  LOW  LOW  HIGH LOW  LOW  LOW  HIGH LOW  HIGH
 [31] LOW  LOW  HIGH HIGH LOW  LOW  LOW  LOW  LOW  LOW  LOW  HIGH LOW  LOW  HIGH 
  ... ...
[301] LOW  LOW  HIGH LOW  HIGH HIGH HIGH HIGH HIGH HIGH LOW  HIGH HIGH HIGH HIGH
[316] HIGH LOW  HIGH HIGH LOW  HIGH HIGH LOW  HIGH LOW  LOW  HIGH HIGH HIGH HIGH
[331] LOW  HIGH LOW  HIGH LOW  HIGH LOW  HIGH HIGH HIGH LOW  HIGH

Levels: HIGH LOW

Confusion Matrix and Statistics

          Reference
Prediction HIGH LOW
      HIGH  136  48
      LOW    50 108
                                          
               Accuracy : 0.7135          
                 95% CI : (0.6624, 0.7608)
    No Information Rate : 0.5439          
    P-Value [Acc > NIR] : 9.525e-11       
                                          
                  Kappa : 0.4231          
                                          
 Mcnemar's Test P-Value : 0.9195          
                                          
            Sensitivity : 0.7312          
            Specificity : 0.6923          
         Pos Pred Value : 0.7391          
         Neg Pred Value : 0.6835          
             Prevalence : 0.5439          
         Detection Rate : 0.3977          
   Detection Prevalence : 0.5380          
      Balanced Accuracy : 0.7117          
                                          
       'Positive' Class : HIGH     

Berdasarkan output di atas, disajikan prediksi kelas dari data uji. Misalkan pada data uji yang pertama diprediksi masuk kelas LOW, data uji kedua masuk kelas LOW sampai dengan data uji terakhir diprediksi masuk sebagai kelas HIGH. Hasil ini selanjutnya dapat dibandingkan dengan kelas sebenarnya pada data uji melalui confusion matrix.

Secara keseluruhan, nilai akurasi prediksi sebesar 0.7135 atau algoritma KNN berhasil memprediksi benar 71,35% dari data uji. Jika dilihat menurut masing-masing kelas, dari 186 data uji dengan kelas HIGH, 136 diprediksi benar, sementara 50 salah. Hasil ini memberikan nilai sensitivity (prediksi benar kelas positif) sebesar 0.7312. Selanjutnya, dari 156 data uji dengan kelas LOW, 108 diprediksi benar dan 48 salah atau memiliki nilai spesifisitas sebesar 0.6923.

KNN dengan paket ‘caret’

Pustaka caret memiliki fungsi train yang dapat dimanfaatkan untuk melakukan iterasi berbagai nilai k. Selain melakukan iterasi, fungsi train juga memungkinkan kita melakukan validasi silang sehingga hasil yang diperoleh bisa lebih dapat dipercaya dan dapat mengurangi kecenderungan overfitting.

Kode berikut ini menunjukkan bagaimana penggunaan fungsi train untuk mencari nilai k terbaik pada algoritma KNN.

R

set.seed(100)  # mengatur seed tertentu untuk hasil yang dapat direproduksi

# proses pengukuran menggunakan k-fold cv dengan 5 fold
control = trainControl(method = "cv", number = 5)

# pencarian dilakukan untuk k=1,2,...30
grid = expand.grid(k = 1:30)

knn.grid <- train(x=scaled.data.train, 
                   y=data.train$quality, 
                   method = "knn",
                   trControl = control,
                   tuneGrid = grid)

# Menampilkan hasil model
print(knn.grid)
# OUTPUT

k-Nearest Neighbors 

801 samples
 11 predictor
  2 classes: 'HIGH', 'LOW' 

No pre-processing
Resampling: Cross-Validated (5 fold) 
Summary of sample sizes: 641, 641, 641, 641, 640 
Resampling results across tuning parameters:

  k   Accuracy   Kappa    
   1  0.7116149  0.4161999
   2  0.6629037  0.3182158
   3  0.6891693  0.3700351
   4  0.7054037  0.4034003
   5  0.7278882  0.4459112
   6  0.7191304  0.4296876
   7  0.7315994  0.4553879
   8  0.7340994  0.4596629
   9  0.7366149  0.4665516
  10  0.7291071  0.4512970
  11  0.7353649  0.4633416
  12  0.7316071  0.4548386
  13  0.7341071  0.4596765
  14  0.7428804  0.4784521
  15  0.7378571  0.4695540
  16  0.7341071  0.4616210
  17  0.7315916  0.4561245
  18  0.7390839  0.4724295
  19  0.7378416  0.4698100
  20  0.7366071  0.4671681
  21  0.7291149  0.4515492
  22  0.7303339  0.4536458
  23  0.7340683  0.4610520
  24  0.7353106  0.4632360
  25  0.7240683  0.4405751
  26  0.7365683  0.4657745
  27  0.7290761  0.4510499
  28  0.7278416  0.4488364
  29  0.7290994  0.4518120
  30  0.7378494  0.4699030

Accuracy was used to select the optimal model using the largest value.
The final value used for the model was k = 14.                    

Hasil di atas menunjukkan bahwa nilai k yang menghasilkan akurasi tertinggi berdasarkan validasi silang adalah k=14 yaitu sebesar 0.74288. Namun, perlu diingat bahwa nilai tersebut adalah berdasarkan data latih. Kita perlu mengukur performa sebenarnya menggunakan data uji seperti sebelumnya. Evaluasi pada data uji menunjukkan nilai akurasi sebesar 0,7251 sementara nilai sensitivity sebesar 0,8280 dan specificity sebesar 0,6026.

R

# Membuat prediksi untuk data uji
predictions <- predict(knn.grid, newdata = scaled.data.test)

# Evaluasi model
conf_matrix <- confusionMatrix(predictions, data.test$quality)
print(conf_matrix)
# OUTPUT

Confusion Matrix and Statistics

          Reference
Prediction HIGH LOW
      HIGH  154  62
      LOW    32  94
                                          
               Accuracy : 0.7251          
                 95% CI : (0.6746, 0.7718)
    No Information Rate : 0.5439          
    P-Value [Acc > NIR] : 4.308e-12       
                                          
                  Kappa : 0.4373          
                                          
 Mcnemar's Test P-Value : 0.00278         
                                          
            Sensitivity : 0.8280          
            Specificity : 0.6026          
         Pos Pred Value : 0.7130          
         Neg Pred Value : 0.7460          
             Prevalence : 0.5439          
         Detection Rate : 0.4503          
   Detection Prevalence : 0.6316          
      Balanced Accuracy : 0.7153          
                                          
       'Positive' Class : HIGH            
                                                          

Selamat mencoba!

API

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

Daftar Isi