Introduction to Data Science
Email          : calvin.riswandi@student.matanauniversity.ac.id
RPubs         : https://rpubs.com/Calvinriswandy/
Jurusan      : Statistika
Address     : ARA Center, Matana University Tower
             Jl. CBD Barat Kav, RT.1, Curug Sangereng, Kelapa Dua, Tangerang, Banten 15810.
Anggota Kelompok
Statistika 2021 1. Ferdinand Nathaniel Widjaya 2. Calvin Riswandi 3. Sausan Ramadhani
Chapter 6 (Classification 2)
Latar Belakang
di chapter ini kita melanjutkan pengenalan permodelan prediktif dengan klasifikasi. Jadi, di bab sebelumnya kita membahas tentang bagai mana cara memproses data, sekarang kita akan berfokus pada mengevaluasi akurasi dan cara meningkatkan akura si dalam pengklasifikasian.
Evaluasi akurasi
Dalam membuat suatu pengklasifikasian, hasil prediksi tidak akan selalu 100%. Contohnya Biopsi yang di lakukan pada pasien, tujuannya untuk mengetahui jenis tumor yang di derita pasien. Untuk menentukannya kita harus melakukan pengklasifikasian untuk memutuskan apakah tumor yang diderita jinak atau ganas.Namun, kita tetap memerlukan beberapa sampel untuk melakukan klasifikasi. Caranya adalah dengan membagi data menjadi training set dan test set dan menggunakan training set saat membuat classifier.Lalu untuk mengeveluasi akurasi classifiernya, pertama kita pisahkan label yang sebenarnya dari test set, dan gunakan classifier untuk memprediksi labelnya yang ada di test set. Jika prediksi cocok dengan label maka untuk pengamatan diset pengujian, kita akan memiliki beberapa keyakinan bahwa pengklasifikasian yang kita lakukan mungkin akurat.
Randomness dan seeds
Di chapter ini analisis data kita akan lebih sering menggunakan data yang acak. Setiap kali kita membuat suatu keputusan dalam analisis kita harus adil dan tidak memihak siapa pun.
set.seed(1)
random_numbers <- sample(0:9, 10, replace=TRUE)
random_numbers## [1] 8 3 6 0 1 6 1 2 0 4
kita bisa lihat bahwa random_numbers adalah daftar 10 angka dari 0 hingga 9, jika kita menjalankan fungsi lagi akan menghasilkan nilai random lainnya.
random_numbers <- sample(0:9, 10, replace=TRUE)
random_numbers## [1] 4 9 5 9 6 8 4 4 8 8
random_numbers <- sample(0:9, 10, replace=TRUE)
random_numbers## [1] 4 4 1 9 8 0 3 2 5 9
Jika, kita memilih nilai seeds yang berbeda, kita akan memperoleh nilai acak yang berbeda pula.
set.seed(4235)
random_numbers <- sample(0:9, 10, replace=TRUE)
random_numbers## [1] 8 3 1 4 6 8 8 4 1 7
random_numbers <- sample(0:9, 10, replace=TRUE)
random_numbers## [1] 3 7 8 2 8 8 6 3 3 8
Evakuasi akurasi menggunakan tidymodels
library(tidyverse)## Warning: package 'tidyverse' was built under R version 4.1.2
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5 v purrr 0.3.4
## v tibble 3.1.4 v dplyr 1.0.7
## v tidyr 1.2.0 v stringr 1.4.0
## v readr 2.0.1 v forcats 0.5.1
## Warning: package 'tidyr' was built under R version 4.1.2
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(tidymodels)## Warning: package 'tidymodels' was built under R version 4.1.2
## Registered S3 method overwritten by 'tune':
## method from
## required_pkgs.model_spec parsnip
## -- Attaching packages -------------------------------------- tidymodels 0.1.4 --
## v broom 0.7.9 v rsample 0.1.1
## v dials 0.1.0 v tune 0.1.6
## v infer 1.0.0 v workflows 0.2.4
## v modeldata 0.1.1 v workflowsets 0.1.0
## v parsnip 0.1.7 v yardstick 0.0.9
## v recipes 0.1.17
## Warning: package 'dials' was built under R version 4.1.2
## Warning: package 'infer' was built under R version 4.1.2
## Warning: package 'modeldata' was built under R version 4.1.2
## Warning: package 'parsnip' was built under R version 4.1.2
## Warning: package 'recipes' was built under R version 4.1.2
## Warning: package 'rsample' was built under R version 4.1.2
## Warning: package 'tune' was built under R version 4.1.2
## Warning: package 'workflows' was built under R version 4.1.2
## Warning: package 'workflowsets' was built under R version 4.1.2
## Warning: package 'yardstick' was built under R version 4.1.2
## -- Conflicts ----------------------------------------- tidymodels_conflicts() --
## x scales::discard() masks purrr::discard()
## x dplyr::filter() masks stats::filter()
## x recipes::fixed() masks stringr::fixed()
## x dplyr::lag() masks stats::lag()
## x yardstick::spec() masks readr::spec()
## x recipes::step() masks stats::step()
## * Learn how to get started at https://www.tidymodels.org/start/
# set the seed
set.seed(1)
# load data
cancer <- read_csv("C:/Users/5/Documents/Semester2/Input/unscaled_wdbc.csv") |>
# convert the character Class variable to the factor datatype
mutate(Class = as_factor(Class)) ## Rows: 569 Columns: 12
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (1): Class
## dbl (11): ID, Radius, Texture, Perimeter, Area, Smoothness, Compactness, Con...
##
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# create scatter plot of tumor cell concavity versus smoothness,
# labeling the points be diagnosis class
perim_concav <- cancer |>
ggplot(aes(x = Smoothness, y = Concavity, color = Class)) +
geom_point(alpha = 0.5) +
labs(color = "Diagnosis") +
scale_color_manual(labels = c("Malignant", "Benign"),
values = c("orange2", "steelblue2")) +
theme(text = element_text(size = 12))
perim_concavmembuat test split atau train
cancer_split <- initial_split(cancer, prop = 0.75, strata = Class)
cancer_train <- training(cancer_split)
cancer_test <- testing(cancer_split)
glimpse(cancer_train)## Rows: 426
## Columns: 12
## $ ID <dbl> 8510426, 8510653, 8510824, 857373, 857810, 858477, 8~
## $ Class <fct> B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B~
## $ Radius <dbl> 13.540, 13.080, 9.504, 13.640, 13.050, 8.618, 10.170~
## $ Texture <dbl> 14.36, 15.71, 12.44, 16.34, 19.31, 11.79, 14.88, 20.~
## $ Perimeter <dbl> 87.46, 85.63, 60.34, 87.21, 82.61, 54.34, 64.55, 54.~
## $ Area <dbl> 566.3, 520.0, 273.9, 571.8, 527.2, 224.5, 311.9, 221~
## $ Smoothness <dbl> 0.09779, 0.10750, 0.10240, 0.07685, 0.08060, 0.09752~
## $ Compactness <dbl> 0.08129, 0.12700, 0.06492, 0.06059, 0.03789, 0.05272~
## $ Concavity <dbl> 0.066640, 0.045680, 0.029560, 0.018570, 0.000692, 0.~
## $ Concave_Points <dbl> 0.047810, 0.031100, 0.020760, 0.017230, 0.004167, 0.~
## $ Symmetry <dbl> 0.1885, 0.1967, 0.1815, 0.1353, 0.1819, 0.1683, 0.27~
## $ Fractal_Dimension <dbl> 0.05766, 0.06811, 0.06905, 0.05953, 0.05501, 0.07187~
glimpse(cancer_test)## Rows: 143
## Columns: 12
## $ ID <dbl> 84501001, 846381, 84799002, 849014, 852763, 853401, ~
## $ Class <fct> M, M, M, M, M, M, M, B, M, M, M, B, B, B, B, B, B, M~
## $ Radius <dbl> 12.460, 15.850, 14.540, 19.810, 14.580, 18.630, 16.7~
## $ Texture <dbl> 24.04, 23.95, 27.54, 22.15, 21.53, 25.11, 21.59, 18.~
## $ Perimeter <dbl> 83.97, 103.70, 96.73, 130.00, 97.41, 124.80, 110.10,~
## $ Area <dbl> 475.9, 782.7, 658.8, 1260.0, 644.8, 1088.0, 869.5, 5~
## $ Smoothness <dbl> 0.11860, 0.08401, 0.11390, 0.09831, 0.10540, 0.10640~
## $ Compactness <dbl> 0.23960, 0.10020, 0.15950, 0.10270, 0.18680, 0.18870~
## $ Concavity <dbl> 0.22730, 0.09938, 0.16390, 0.14790, 0.14250, 0.23190~
## $ Concave_Points <dbl> 0.085430, 0.053640, 0.073640, 0.094980, 0.087830, 0.~
## $ Symmetry <dbl> 0.2030, 0.1847, 0.2303, 0.1582, 0.2252, 0.2183, 0.18~
## $ Fractal_Dimension <dbl> 0.08243, 0.05338, 0.07077, 0.05395, 0.06924, 0.06197~
bisa kita lihat training set nya berisi 426 observasi,sedangkan test set berisi 143 observasi.
cancer_proportions <- cancer_train |>
group_by(Class) |>
summarize(n = n()) |>
mutate(percent = 100*n/nrow(cancer_train))
cancer_proportionsbisa kita lihat dengan menggunakan group_by kita bisa melihat presentase sebanyak 63% Benign dan 37% adalah malingnant.Ini menunjukkan bahwa proporsi kelas secara kasar dipertahankan saat membagi data.
Praproses Data
Pertimbangan tambahan yang perlu kita ambil saat melakukan ini adalah bahwa kita harus membuat praprosesor standarisasi hanya dengan menggunakan data pelatihan.Karena, saat menggunakan K-nearest neighbors sensitif terhadap skala prediktor dan kita harus melakukan proses awal untuk membuatnya menjadi standar. Berikut kami membuat prediksi hanya menggunakan training data dengan menggunakan cancer_train.
cancer_recipe <- recipe(Class ~ Smoothness + Concavity, data = cancer_train) |>
step_scale(all_predictors()) |>
step_center(all_predictors())
cancer_recipe## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
##
## Operations:
##
## Scaling for all_predictors()
## Centering for all_predictors()
melatih pengklasifikasian
sekarang kita akan membagi dari data asli menjadi training set dan test sets. kita akan membuat K-nearest neighbors classifier hanya dengan menggunakan training sets. pertama, kita harus membuat spesifikasi model, lalu menggabungkan spesifikasi model dengan recipe menjadi workflow,dan terakhir menggunakan fit dengan training data cancer_train untuk membuat classifier
knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 3) |>
set_engine("kknn") |>
set_mode("classification")
knn_fit <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
fit(data = cancer_train)
knn_fit## == Workflow [trained] ==========================================================
## Preprocessor: Recipe
## Model: nearest_neighbor()
##
## -- Preprocessor ----------------------------------------------------------------
## 2 Recipe Steps
##
## * step_scale()
## * step_center()
##
## -- Model -----------------------------------------------------------------------
##
## Call:
## kknn::train.kknn(formula = ..y ~ ., data = data, ks = min_rows(3, data, 5), kernel = ~"rectangular")
##
## Type of response variable: nominal
## Minimal misclassification: 0.1150235
## Best kernel: rectangular
## Best k: 3
memprediksi label yang ada di test sets
cancer_test_predictions <- predict(knn_fit, cancer_test) |>
bind_cols(cancer_test)
cancer_test_predictionsmenghitung akurasi
cancer_test_predictions |>
metrics(truth = Class, estimate = .pred_class) |>
filter(.metric == "accuracy")confusion <- cancer_test_predictions |>
conf_mat(truth = Class, estimate = .pred_class)
confusion## Truth
## Prediction M B
## M 39 6
## B 14 84
Analisis kinerja secara kritis
Tingkat AKurasi 86% sudah cukup tinggi, apakah bisa lebih akurat lagi? Umumnya, level akurasi ditentukan oleh aplikasi prediksi tersebut. Jika ingin memprediksikan klasifikasi tumor dengan level aurasi 99% mungkin masih kurang akurat ditambah jika ada faktor Error dan kesalahan yang dibuat oleh AI. Efeknya adalah kesalahan penanganan dan pengobatan pada pengidap tumor yang menerima treatment, seperti Pasien dengan kelas Malignant yang dilabeli Benign tidak menerima pengobatan seperti yang harusnya seorang pengidap tumor Malignant jalani.
KNN juga dipengaruhi oleh Kelas Mayoritas, setelah menginput data seperti diatas kita berharap agar KNN dapat memiliki prediksi yang akurat , bisa dilihat proporsi data cancer data proportions
cancer_proportionsBenign merupakan kelas mayoritas di dataset tersebut, expectationnya adalah KNN memiliki accuracy diatas persentase kelas mayoritas (63%) yang ternyata bisa lebih akurat daripada harapan (86%). Tapi efek kelas mayoritas tersebut mempengaruhi beberapa Malignant Tumors yang salah di Diagnosis menjadi Benign sebanyak 14 dari 53 data (26%) error rate yang cukup besar apalagi mempengaruhi pennanganan medis dan nyawa seseorang.
Tuning the classifier
Kebanyakan Machine Learning dan statistics memiliki Parameter, sebuah batasan yang kita pilih untuk menentukan model bekerja. Di KNN kita memilih parameter K untuk menentukan berapa banyak neighbor yang masuk dalam kelas. Beda nilai K beda juga hasil prediksi.
Bagaimana cara memilih nilai K yang paling efektif untuk memaksimalkan peformance dari data classifier yang kita punya? Menggunakan metode Split yang sama seperti sebelumnya lalu melakukan step-by-step sampai mendapatkan parameter yang tepat untuuk melakukan klasifikasi.
P.S. : Jangan menyentuh apa yang ada di Test Set selama proses tuning, gunakan Test Set saat proses pengujian
Cross-validation
Pertama, kita melakkan perbandingan dari hasil setiap nilai dari K dan memilih yang paling cocok dengan menggunakan Training Set (Validation set) Berbeda dengan sebelumnya, kita hanya membuat single split dari data. Karena in the end hanya ada 1 classifier yang akan digunakan. Tapi selama proses tuning, kita bebas menciptakan banyak classifier dengan berbagai faktor untuk menentukan parameter value yang paling tepat dan akurasi yang lebih baik .
Contohnya, kita akan menguji 5 splits atau hitungan yang berbeda selama proses tuning dan membandingkan dengan yang hanya 1 kali splits. Mulai dengan Single Split
# create the 25/75 split of the training data into training and validation
cancer_split <- initial_split(cancer_train, prop = 0.75, strata = Class)
cancer_subtrain <- training(cancer_split)
cancer_validation <- testing(cancer_split)
# recreate the standardization recipe from before
# (since it must be based on the training data)
cancer_recipe <- recipe(Class ~ Smoothness + Concavity,
data = cancer_subtrain) |>
step_scale(all_predictors()) |>
step_center(all_predictors())
# fit the knn model (we can reuse the old knn_spec model from before)
knn_fit <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
fit(data = cancer_subtrain)
# get predictions on the validation data
validation_predicted <- predict(knn_fit, cancer_validation) |>
bind_cols(cancer_validation)
# compute the accuracy
acc <- validation_predicted |>
metrics(truth = Class, estimate = .pred_class) |>
filter(.metric == "accuracy") |>
select(.estimate) |>
pull()
acc## [1] 0.8598131
Dalam Sekali hitung atau dengan sekali split, akurasi berada di 88%. Kita lakukan ulang coding tersebt sebanyak 4 kali untuk mendapatkan 5 jenis data dengan 5 level akurasi berbeda : 88.8%, 86.9%, 83.2%, 88.8%, 87.9% . Nilai Akurasi tersebut tidaklah jauh berbeda dengan yang lainnya, kelimanya hanyalah estimasi nilai akurasi dari Classifier yang kita miliki dengan rata-rata 87%.
Dalam prakteknya, kita tidak menggunakan random splits, tapi meggunakan procedure split dimana satu data/amatan hanya muncul satu kali di Validation Set atau Test Set. Taktik ini bernama Cross-Validation. Dimana kita meng-split data menjadi C bagian sama besar dan menggunakan 1 bagian msebagai Validation Set dan Sisanya sebagai Training Set
Dengan R, Cross-Validation 5 Splits bisa dilakulkan dengan package tidymodels dengan function vfold_cv yang membagi data kita mnenjadi v bagian. Lalu strata untuk membedakan label memastikan masing-masing splits memiliki proporsi yang sama dengan label atau kelasnta `
cancer_vfold <- vfold_cv(cancer_train, v = 5, strata = Class)
cancer_vfoldLalu menggunakan fit_resamples untuk melakukan cross validation di tiap splits
# recreate the standardization recipe from before
# (since it must be based on the training data)
cancer_recipe <- recipe(Class ~ Smoothness + Concavity,
data = cancer_train) |>
step_scale(all_predictors()) |>
step_center(all_predictors())
# fit the knn model (we can reuse the old knn_spec model from before)
knn_fit <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
fit_resamples(resamples = cancer_vfold)## Warning: package 'kknn' was built under R version 4.1.2
knn_fitMenggunakan collect_metrics untuk mendapatkan agregate dari mean dan standard error setiap classifier. Nilai accuracy akan tampil di accuracy di kolom .metric . Mean (mean) dijadikan sebagai perkiraan akurasi dan standard error (std_err) menyatakan nilai error dari Mean. Jika Mean 0.88 dan Standard Error 0.02 maka nilai akurasinya berkisar antara 86%-90% Untuk smentara, kita bisa mengabaikan baris roc_auc
knn_fit |>
collect_metrics() Kita bisa melakukan dengan berbagai jumlah splits yang pastinya meningkatkan average akurasi tapi semakin memberatkan system dan waktu proses semakin lama. DAlam melakukan hak ini, perhatikan ukuran dan jumlah data juga kemampuan hardware dan algoritma. Biasanya nilai C adalah 5 atau 10. Contoh Cross-Validation dengan 10 Splits
cancer_vfold <- vfold_cv(cancer_train, v = 10, strata = Class)
vfold_metrics <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
fit_resamples(resamples = cancer_vfold) |>
collect_metrics()
vfold_metricsParameter Value Selection
Di tahap sebelumnyaa, setelah perhitungan diestimasikan tingkat akurasi dari classifier tersebut sekitar 89% Dalam kondisi tertentu, itu sudah cukup tapi untuk data Cancer yang berhubungan dengan resiko tinggi bahkan sampai melibatkan Nyawa seseorang, kit aperlu meningkatkan tingkat akurasinya.
Untuk menongkatkan level akurasinya, kita bisa menentukan parameter jumlah neighbor, K. Dengan metode Cross-Validation kta bisa menentukan akurasi dari masing-masing nilai K dalam range yang ditentukan lalu memilih K yang punya akurasi terbaik. tidymodels menyediakan function yang bisa digunakan yaitu tune()
knn_spec <- nearest_neighbor(weight_func = "rectangular",
neighbors = tune()) |>
set_engine("kknn") |>
set_mode("classification")Menggunakan tune_grid untuk mencocokkan model tiap nilai K. Pertama-tama buat dataframe neighbor variabel yang terdapat squence dari nilai K dalam dataframe bernama k_vals dari 1-100 dengan kelipatan 5 lalu memasukkan data ke grid dalam tune_grid
k_vals <- tibble(neighbors = seq(from = 1, to = 100, by = 5))
knn_results <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
tune_grid(resamples = cancer_vfold, grid = k_vals) |>
collect_metrics()
accuracies <- knn_results |>
filter(.metric == "accuracy")
accuraciesMenggunakan plot, kita bisa melihat nilai K mana yang memberikan tingkat akurasi paling tinggi
accuracy_vs_k <- ggplot(accuracies, aes(x = neighbors, y = mean)) +
geom_point() +
geom_line() +
labs(x = "Neighbors", y = "Accuracy Estimate") +
theme(text = element_text(size = 12))
accuracy_vs_kK=41 memiliki akurasi tertinggi sebesar 89,17% dan nilai K antara 30 sampai 60 bisa menjadi pilihan yang cocokk. Tapi apa yang ada di plot tersebut hanyalah estimasi, bukan brarti classifiernya akan super akurat dengan nilai K sekian. Yang dicari adalah
- Akurasi yang Optimal supaya model classifiernya akan akurat
- Jike nilai K diganti dengan nilai K yang berbeda sedikit (Misalnya menjumlahkan atau mengurangi dengan angka kecil) tidak merubah tingkat akurasi secara signifikan
- Tidak terlalu memakan banyak effort (Cost, Resources dll)
Kita mengetahui bahwa K=41 memnerikan tingkat akurasi tertinggi dan tidak memiliki perbedaan signifikan jika diganti sedikit (Poin 2) dan tidak terlalu memakan banyak Cost di proses komputasi (poin 3 ). Maka dipilihlah K=41
Under/Overfitting
Apa yang terjadi jika nilai K semakin membersar ? Akurasi akan menurun. Dengan grid di tune_grid menampilkan plot dengan nilai K dari 1 sampai jumlah total amatan dalam dataset.
k_lots <- tibble(neighbors = seq(from = 1, to = 385, by = 10))
knn_results <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
tune_grid(resamples = cancer_vfold, grid = k_lots) |>
collect_metrics()## ! Fold01: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold02: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold03: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold04: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold05: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold06: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold07: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold08: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold09: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
## ! Fold10: preprocessor 1/1, model 1/1: 381 samples were requested but there were 3...
accuracies <- knn_results |>
filter(.metric == "accuracy")
accuracy_vs_k_lots <- ggplot(accuracies, aes(x = neighbors, y = mean)) +
geom_point() +
geom_line() +
labs(x = "Neighbors", y = "Accuracy Estimate") +
theme(text = element_text(size = 12))
accuracy_vs_k_lotsUnderfitting : Semakin meningkat nilai K, maka semakin banyak data yang salah masuk kelas, perbatasan antara klasifikasi Benign dan Malignant menjadi tidak jelas, dimana semakin banyak amatan yang malah masuk kelas mayoritas.
Overfitting : Ketika nilai K menurun, dan karena Data yang angkanya berbeda-beda, Classifier akan menyamakan kelasnya dengan amatan yang didekatnya, membuat batas dimana Klasifikasi menjadi tidak jelas atau berantakan.
Summary
Algoritma Klasifikasi seperti K-Nearest Neighbor membandingkan data dengan amatan terdekatnya lalu mengklasifikan kelasnya. Mengevaluasi tingkat akurasi dari classifier bisa dengan Split Training Set dan test set atau dengan melakukan Cross-Validation.
Cara Kerja K-Nearest Neighbor dari tidymodels
- Menggunakan
initial_splituntuk membagi data menjadi training dan test set denganstratasebagai kelas pembagi nya - Gunakan
vfold_cvuntuk split data untuk melakukan cross-validation - Mmebuat
recipeyang menspesifikasi class labels dan prediktonya serta melakukan preprocessing data. Masukkan Training Data sebagaidatadi recipe. - Membuat
nearest_neighbormodel denganneighbor = true () - Menggabungkan Recipe dan Model ke
workflow()dengantune_griduntuk mengestimasi nilai akurasi dari nilai K - Memilih nilai K dengan Akurasi tertinggi
- membuat model baru untuk mencari Parameter
- Evaluasi nilai akurasi yang terlah diestimasi dengan
predict
Plus Side K -nearest neighbors classification + Algoritma yang Simple + Membutuhkan asumsi seperti apa bentukannyadata + Bekerja untuk klasifikasi binary (2) dan multi class
Down Side dari K-nearest neighbors classification - Melambat ketika Datanya Besar - Tidak terlalu optimal dengan jumlah predictor yang besar - Tidak terlalu optimal apabila proporsi kelas tidak sama.
Predictor variable selection
Anda bisa memilih variabel apapun dari data sebagai variabel yang akan digunakan untuk memprediksi. Semakin banyak predictor bukan berarti semakin akurat jika memilih Predictor yang salah bisa merusak klasifikasi yang ada.
The effect of irrelevant predictors
Sebagai contoh, di data Breast cancer akan menggunakan variabel predictor yaitu Smoothness Concavity dan Perimeter dengan menambahkan Data angka random 0 dan 1 yang dusebut sebagai irrelevant1 dan Irrelevant2
cancer_irrelevant = cancer
cancer_irrelevant$Irrelevant1 = sample(c(0,1), replace=TRUE, size=569)
cancer_irrelevant$Irrelevant2 = sample(c(0,1), replace=TRUE, size=569)
cancer_irrelevant$Irrelevant3 = sample(c(0,1), replace=TRUE, size=569)cancer_irrelevant |>
select(Class, Smoothness, Concavity, Perimeter, Irrelevant1, Irrelevant2)cancer_irrelevantSelanjutnya, membuat KNN dengan melibatkan variabel-variabel tersebut. Semakin banyak Irrelevant variables, semakin turun pula nilai akurasi dari classifier tersebut karena kehadiran variabel tersebut menghadirkan influence yang bisa merusak jumlah neighbor yang mempernaruhi proses dan hasil klasifikasi.
Finding a good subset of predictors
Bagaimana memilih variabel yang cocok untuk melakukan klasifikasi? Bisa menggunakan proses visualisasii data untuk menunjukkan kira-kira mana variabel yang relevan untuk digunakan.
Cara pertama dengan menggunakan semua subset yang mungkin, melakukan proses trial dan error berulang kali sampai mendapatkan klasifikasi yang terbaik. Disebut juga best subset selection (Beale, Kendall, and Mann 1967; Hocking and Leslie 1967) Kelemahannya adalah memperlambat kinerja system dan cenderung menghabiskan banyak waktu serta biaya, karena kita menggunakan semua kombinasi yang mungkin terjaid. Contohnya ada 3 variabel (A,B,C) maka kita melakuan subset and trial sebanyak 7 kali (A,B,C AB, AC, BC, ABC)
Cara Kedua bisa dengan membuat model klasifikasi lalu menambahkan satu-persatu variabel disebut juga forward selection (Eforymson 1966; Draper and Smith 1966) Dimulai dengan membuat model dengan jumlah predictor = 0 lalu menambahkan satu persatu variabel tersebut ke dalam model sampai menghasilkan model yanhg memiliki tingkat akurasi tertinggi.
Forward selection in R
Di R tepatnya tidyverse tidak ada cara yang fully automatic dalam melakukan ini. Tapi bisa dengan manual, pertama-tama select untuk mengekstrak predictors.
cancer_subset <- cancer_irrelevant |>
select(Class,
Smoothness,
Concavity,
Perimeter,
Irrelevant1,
Irrelevant2,
Irrelevant3)
names <- colnames(cancer_subset |> select(-Class))
cancer_subsetMenggunakan fungsi paste untuk menciptakan model. Lalu collapse akan menentukan paste apa yang harus ditaruh di antara items . Untuk membuat formula =nya
example_formula <- paste("Class", "~", paste(names, collapse="+"))
example_formula## [1] "Class ~ Smoothness+Concavity+Perimeter+Irrelevant1+Irrelevant2+Irrelevant3"
Lalu, membuat code dimana akan mencari prediktor terbaik untuk dipakai di model akhir. Setiap predictor dibuatkan model formula, dimasukkan ke recipe , membuat workflow dengan K-NN classifier menggunakan Cross-Validation dengan 5 Splits lalu mencatat nilai estimasi akurasinya.
# create an empty tibble to store the results
accuracies <- tibble(size = integer(),
model_string = character(),
accuracy = numeric())
# create a model specification
knn_spec <- nearest_neighbor(weight_func = "rectangular",
neighbors = tune()) |>
set_engine("kknn") |>
set_mode("classification")
# create a 5-fold cross-validation object
cancer_vfold <- vfold_cv(cancer_subset, v = 5, strata = Class)
# store the total number of predictors
n_total <- length(names)
# stores selected predictors
selected <- c()
# for every size from 1 to the total number of predictors
for (i in 1:n_total) {
# for every predictor still not added yet
accs <- list()
models <- list()
for (j in 1:length(names)) {
# create a model string for this combination of predictors
preds_new <- c(selected, names[[j]])
model_string <- paste("Class", "~", paste(preds_new, collapse="+"))
# create a recipe from the model string
cancer_recipe <- recipe(as.formula(model_string),
data = cancer_subset) |>
step_scale(all_predictors()) |>
step_center(all_predictors())
# tune the KNN classifier with these predictors,
# and collect the accuracy for the best K
acc <- workflow() |>
add_recipe(cancer_recipe) |>
add_model(knn_spec) |>
tune_grid(resamples = cancer_vfold, grid = 10) |>
collect_metrics() |>
filter(.metric == "accuracy") |>
summarize(mx = max(mean))
acc <- acc$mx |> unlist()
# add this result to the dataframe
accs[[j]] <- acc
models[[j]] <- model_string
}
jstar <- which.max(unlist(accs))
accuracies <- accuracies |>
add_row(size = i,
model_string = models[[jstar]],
accuracy = accs[[jstar]])
selected <- c(selected, names[[jstar]])
names <- names[-jstar]
}
accuracies