Introduction to Data Sciences
Classification I : Predicting
| Kontak | \(\downarrow\) |
| valensiusjimy27@gmail.com | |
| https://www.instagram.com/its_bangjeki/ | |
| RPubs | https://rpubs.com/valensiusjimy/ |
| Nama | Valensius Jimy |
| NIM | 20214920005 |
 Pada kesempatan kali ini akan terfokus pada langkah untuk melakukan data yang bersifat prediksi yang berarti bahwa memberikan informasi melalui data yang tersedia. Dalam melakukan prediksi data ini, hal yang perlu dipahami adalah tentang cara untuk klasifikasi kelas. Sebagai contohnya adalah ketika seorang tenaga medis ingin memberikan keputusan kepada pasiennya yang positif covid dan negatif covid. Dan untuk menentukan apakah pasiennya positif atau negatif, maka dokter tersebut dapat melihat dari riwayat pasien sebelumnya yang artinya melihat gejala yang ada dengan pasien masa lalunya. Jika memiliki banyak kesamaan, maka dapat dimasukkan ke kelas positif dan sebaliknya.
 Ternyata untuk membuat sebuah klasifikasi terdapat banyak sekali metode yang dapat digunakan, tetapi yang lebih sering digunakan dan lebih mudah dipahami adalah metode K-Nearest Neighbors yang merupakan suatu agoritma yang digunakan untuk membuat keputusan klasifikasi dengan mencari jarak terdekat suatu objek yang sedang diteliti dengan objek lain terdekatnya. Dan metode ini sangat sering digunakan oleh banyak peneliti di dunia.
 Namun, ketika sedang merancang sebuah klasifikasi, seringkali menemukan sebuah masalah yang umum terjadi dan ini kadang membuat sedikit rasa bingun untuk menentukan keputusannya. Masalah ini disebut sebagai Binary Classification, dari namanya saja sudah dapat diketahui bahwa terdapat dua kelas objek yang muncul, sebagai contohnya adalah ketika awalnya terdapat dua kelas objek, yaitu positif dan negatif. Lalu, hasilnya adalah positif ternyata menghasilkan kelas lainnya seperti positif covid atau positif influenza.
Latar Belakang Data
 Berikut ini adalah pengaplikasian dalam hal prediksi data dengan bahasa pemrograman R di aplikasi Rstudio. Untuk datanya kita ambil data set dari Digitized Breast Cancer image Features yang disusun oleh Dr. William H. Wolberg, W.Nick Street, dan Olvi L. Pada data ini akan menggambarkan sampel tumor dengan keterangan ganas atau tidak dengan pengukuran tekstur nukleus, perimeter dan lainnya. Contoh ini adalah salah satu contoh yang begitu banyak untuk menggambarkan dunia data analis karena lewat data ini kita dapat belajar untuk menganalisa dan memprediksi tentang tumor itu ganas atau tidak.
Import dan Explorasi Data
 Untuk tahap paling awal sekali, kita harus import data karena tanpa import data kita tidak akan bisa untuk mengeksplor dan menganalisa data. Ketika data itu sudah dipanggil, maka harus juga membersihkan data karena tidak semua data itu sudah bersih dan langsung dapat diolah, maka kita harus melakukan yang namanya pengendalian data. Dalam hal ini, kita membutuhkan bantuan library tidyverse untuk melakukan analisis.
library(tidyverse)Kemudian, waktunya memanggil data yang akan dianalisis.
cancer <- read_csv("C:/Users/USER/Downloads/wdbc.csv")## 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.
cancer Kita dapat menggunakan glimpse untuk memudahkan mereview data frame yang kita miliki, yaitu fungsi ini dapat memperlihatkan isi pada data frame kita atau kata lainnya adalh rangkuman data frame. Hal ini memudahkan untuk mengetahui mana variabel yang perlu diubah tipe datanya.
glimpse(cancer)## Rows: 569
## Columns: 12
## $ ID <dbl> 842302, 842517, 84300903, 84348301, 84358402, 843786~
## $ Class <chr> "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M~
## $ Radius <dbl> 1.0960995, 1.8282120, 1.5784992, -0.7682333, 1.74875~
## $ Texture <dbl> -2.0715123, -0.3533215, 0.4557859, 0.2535091, -1.150~
## $ Perimeter <dbl> 1.26881726, 1.68447255, 1.56512598, -0.59216612, 1.7~
## $ Area <dbl> 0.98350952, 1.90703027, 1.55751319, -0.76379174, 1.8~
## $ Smoothness <dbl> 1.56708746, -0.82623545, 0.94138212, 3.28066684, 0.2~
## $ Compactness <dbl> 3.28062806, -0.48664348, 1.05199990, 3.39991742, 0.5~
## $ Concavity <dbl> 2.65054179, -0.02382489, 1.36227979, 1.91421287, 1.3~
## $ Concave_Points <dbl> 2.53024886, 0.54766227, 2.03543978, 1.45043113, 1.42~
## $ Symmetry <dbl> 2.215565542, 0.001391139, 0.938858720, 2.864862154, ~
## $ Fractal_Dimension <dbl> 2.25376381, -0.86788881, -0.39765801, 4.90660199, -0~
 Dari review tersebut data kita lihat bahwa Class memiliki tipe data <chr> sehingga dapat diubah ke tipe yang bersifat statistik seperti yang lainnya, yaitu dengan menggunakan as_factor.
cancer <- cancer |>
mutate(Class = as.factor(Class))
glimpse(cancer)## Rows: 569
## Columns: 12
## $ ID <dbl> 842302, 842517, 84300903, 84348301, 84358402, 843786~
## $ Class <fct> M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M, M~
## $ Radius <dbl> 1.0960995, 1.8282120, 1.5784992, -0.7682333, 1.74875~
## $ Texture <dbl> -2.0715123, -0.3533215, 0.4557859, 0.2535091, -1.150~
## $ Perimeter <dbl> 1.26881726, 1.68447255, 1.56512598, -0.59216612, 1.7~
## $ Area <dbl> 0.98350952, 1.90703027, 1.55751319, -0.76379174, 1.8~
## $ Smoothness <dbl> 1.56708746, -0.82623545, 0.94138212, 3.28066684, 0.2~
## $ Compactness <dbl> 3.28062806, -0.48664348, 1.05199990, 3.39991742, 0.5~
## $ Concavity <dbl> 2.65054179, -0.02382489, 1.36227979, 1.91421287, 1.3~
## $ Concave_Points <dbl> 2.53024886, 0.54766227, 2.03543978, 1.45043113, 1.42~
## $ Symmetry <dbl> 2.215565542, 0.001391139, 0.938858720, 2.864862154, ~
## $ Fractal_Dimension <dbl> 2.25376381, -0.86788881, -0.39765801, 4.90660199, -0~
cancer |>
pull(Class) |>
levels()## [1] "B" "M"
Dari hasil tersebut dapat kita lihat bahwa pada variabel Class hanya terdapat dua nilai yang berbeda yaitu B untuk Benign dan M untuk Malignant. Pada momen ini kita dapat menggunakan fungsi levels dan pull.
 Selanjutnya, kita akan melakukan perhitungan sederhana dan analisa sederhana untuk mengetahui persentase dari tumor yang bersifat ganas dan tidak berdasarkan data yang kita miliki. Dengan langkah sebagai berikut.
percent <- nrow(cancer)
cancer |>
group_by(Class) |>
summarize(
count = n(),
percentage = n() / percent *100
)Â Melalui hasil tersebut, kita dapat menyimpulkan bahwa banyaknya cancer yang ganas atau jinak pada data yang kita miliki memiliki hasil persentase 63% untuk kanker yang jinak dan 37% kanker yang bersifat ganas. Hasil ini dapat kita eksplor lebih jauh dan menarik dalam bentuk scatter plot untuk menvisualisasikan informasi yang lebih menarik dan detail. Dengan langkah sebagai berikut.
perim_concav <- cancer |>
ggplot(aes(x = Perimeter, y = Concavity, color = Class)) +
geom_point(alpha = 0.6) +
labs(x = "Perimeter (standardized)",
y = "Concavity (standardized)",
color = "Diagnosis") +
scale_color_manual(labels = c("Malignant", "Benign"),
values = c("red", "green")) +
theme(text = element_text(size = 12))
perim_concavdari hasil ini dapat kita lihat bahwa kanker jinak cenderung memiliki nilai kecekungan yang lebih rendah dibanding kanker ganas, makanya hasil pengamatan kanker jinak berada di sisi kiri bawah plot.
Klasifikasi Dengan k-Nearest Neighbors
 Untuk membuat sebuah prediksi untuk observasi baru pada sebuah penelitin, kita membutuhkan algoritma untuk menentukan klasifikasi. Dan pada kali ini, kita akan menggunakan algoritma K-Nearest Neighbors. Ketika ingin memprediksi suatu label pada sebuah observasi baru. K sendiri adalah angka yang harus kita pilih.
Jarak antar Titik
 Untuk mencari K nearest neighbors pada sebuah observasi, kita harus menghitung jarak dari observasi baru ke observasi yang telah ada. Nilai K dipilih berdasarkan jarak terdekat dengan objek observasi. Selanjutnya, sebagai contoh kita gunakan nilai K = 5 untuk mengklasifikasikan objek baru dengan perimeter yang bernilai 0 sampai 3.5 pada data yang kita miliki saat ini, dengan langkah sebagai berikut.
new_obs_Perimeter <- 0
new_obs_Concavity <- 3.5
cancer |>
select(ID, Perimeter, Concavity, Class) |>
mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 +
(Concavity - new_obs_Concavity)^2)) |>
arrange(dist_from_new) |>
slice(1:10) # memilih 10 baris pertamaLebih dari dua variabel yang dieksplor
 Terkadang kita membutuhkan lebih dari dua variabel yang akan dieksplor guna mencari informasi data. Sebagai contohnya adalah pada data ini kita akan mengeksplor variabel perimeter, concavity, dan symetry. Dengan langkah sebagai berikut.
new_obs_Perimeter <- 0
new_obs_Concavity <- 3.5
new_obs_Symmetry <- 1
cancer |>
select(ID, Perimeter, Concavity, Symmetry, Class) |>
mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 +
(Concavity - new_obs_Concavity)^2 +
(Symmetry - new_obs_Symmetry)^2)) |>
arrange(dist_from_new) |>
slice(1:10) # mengambil 10 baris pertamaK-nearest neighbors dengan tidymodels
 Pada proses K-nearest neighbors di R terkadang kita mendapat masalah yang ketika ingin mengendalikan kelas multiple yang lebih dari dua variabel. Dengan menggunakan tidymodels kita dapat terbantukan untuk membuat dan menggunakan model untuk pengklasifikasian. Selanjutnya, fungsi ini dapat membuat kode kita lebih simple dan akurat. Kita coba menggunakannya sekaran.
library(tidymodels)cancer_train <- cancer |>
select(Class, Perimeter, Concavity)
cancer_trainselanjutnya, kita buat spesifikasi untuk algoritma ini dengan menggunakan fungsi nearest_neighbor dengan nilai K = 5 neighbors. Dengan langkah sebagai berikut ini.
knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 5) |>
set_engine("kknn") |>
set_mode("classification")
knn_spec## K-Nearest Neighbor Model Specification (classification)
##
## Main Arguments:
## neighbors = 5
## weight_func = rectangular
##
## Computational engine: kknn
agar sesuai dengan data yang kita miliki, kita perlu membuat spesifikasi model dan data dengan menggunakan fungsi fit. Pada momen ini, kita perlu menentukan variabel yang akan digunakan sebagai prediktor dan variabel yang digunakan sebagai targetnya. Kita gunakan Class sebagai target atau yang ingin kita prediksi dan perimeter dan concavity sebagai prediktor.
knn_fit <- knn_spec |>
fit(Class ~ Perimeter + Concavity, data = cancer_train)Kita dapat sintaks seperti ini untuk mencari target variabel kecuali Class. Dan kita dapat memilih prediktor dengan simbol + dan ketika ingin memilih semua untuk menjadi prediktor dengan cara ., yaitu sebagai berikut ini.
knn_fit <- knn_spec |>
fit(Class ~ ., data = cancer_train)
knn_fit## parsnip model object
##
## Fit time: 531ms
##
## Call:
## kknn::train.kknn(formula = Class ~ ., data = data, ks = min_rows(5, data, 5), kernel = ~"rectangular")
##
## Type of response variable: nominal
## Minimal misclassification: 0.07557118
## Best kernel: rectangular
## Best k: 5
dan pada akhirnya kita dapat membuat pengamatan prediksi yang baru dengan memanggil fungsi predict.
new_obs <- tibble(Perimeter = 0, Concavity = 3.5)
predict(knn_fit, new_obs)dengan menjalankan K-nearest neighbors secara manual, maka object klasifikasi baru akan menjadi malignant atau M. Dari hasil ini mungkin terlintas dalam benak kita apakah kelas malignant adalah kelas yang satu-satunya untuk pengamatan ini? Jawabannya kita tidak bisa langsung mengambil pernyataan seperti itu karena tidak memiliki diagnosis observasi. Prediksi belum tentu benar, tetapi kita bisa menghitung tingkat keakuratan hal yang kita prediksi.
Pemusatan dan Skala
 ketika menggunakan K-nearest neighbors skala setiap variabel itu sangat penting. Karena dalam melakukan klasifikasi untuk kelas suatu objek yang akan kita prediksi, jarak observasinya sangatlah berdampak. Dan untuk melakukan pemusatan dan skala data, hal yang perlu kita lakukan adalah mencari rata-rata variabel pada data dan standar deviasi. Dengan melakukan hal ini data kita dapat dikatakan memenuhi standar dan semua variabel dalam data akan memiliki rata-rata 0 dan standar deviasi 1. Kita akan menggunakan data yang telah memenuhi standar, sebagai berikut.
unscaled_cancer <- read_csv("C:/Users/USER/Downloads/unscaled_wdbc.csv") |>
mutate(Class = as_factor(Class)) |>
select(Class, Area, Smoothness)## 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.
unscaled_cancerTerdapat perbedaan antara nilai area lebih besar dari nilai smoothnya. Dan untuk mengetahui apakah hal ini akan berpengaruh terhadap hasil dari prediksi, maka kita akan membuat scatter plot dari dua prediktor dari data yang tidak standar dan versi standar.
uc_recipe <- recipe(Class ~ ., data = unscaled_cancer)
print(uc_recipe)## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
uc_recipe <- uc_recipe |>
step_scale(all_predictors()) |>
step_center(all_predictors()) |>
prep()
uc_recipe## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
##
## Training data contained 569 data points and no missing data.
##
## Operations:
##
## Scaling for Area, Smoothness [trained]
## Centering for Area, Smoothness [trained]
rare_cancer <- bind_rows(
filter(cancer, Class == "B"),
cancer |> filter(Class == "M") |> slice_head(n = 3)
) |>
select(Class, Perimeter, Concavity)
rare_plot <- rare_cancer |>
ggplot(aes(x = Perimeter, y = Concavity, color = Class)) +
geom_point(alpha = 0.5) +
labs(x = "Perimeter (standardized)",
y = "Concavity (standardized)",
color = "Diagnosis") +
scale_color_manual(labels = c("Malignant", "Benign"),
values = c("orange2", "steelblue2")) +
theme(text = element_text(size = 12))
rare_plotanalisanya adalah jika kita menggunakan nilai K = 7 dan hanya dengan 3 pengamatan kanker ganas, pengklasifikasian akan selalu memprediksi bahwa kanker itu jinak tidak peduli dengan nilai cekung dan perimeternya. Ini karena dalam suara mayorit dari 7 pengamatan dan hasilnya hanya 3 yang ganas dan sisanya jinak, sehingga yang jinak sudah pasti menang.
kita dapat melihat apakah kelas kita sudah balance atau belum :
library(themis)## Warning: package 'themis' was built under R version 4.1.2
## Registered S3 methods overwritten by 'themis':
## method from
## bake.step_downsample recipes
## bake.step_upsample recipes
## prep.step_downsample recipes
## prep.step_upsample recipes
## tidy.step_downsample recipes
## tidy.step_upsample recipes
## tunable.step_downsample recipes
## tunable.step_upsample recipes
##
## Attaching package: 'themis'
## The following objects are masked from 'package:recipes':
##
## step_downsample, step_upsample
ups_recipe <- recipe(Class ~ ., data = rare_cancer) |>
step_upsample(Class, over_ratio = 1, skip = FALSE) |>
prep()
ups_recipe## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
##
## Training data contained 360 data points and no missing data.
##
## Operations:
##
## Up-sampling based on Class [trained]
upsampled_cancer <- bake(ups_recipe, rare_cancer)
upsampled_cancer |>
group_by(Class) |>
summarize(n = n())menggunakan workflow
paket tidymodels juga menyediakan workflow yang berfungsi untuk merantai bersama sebuah langkah analisis data tanpa banyak kode yang diperlukan untuk proses datanya.
unscaled_cancer <- read_csv("C:/Users/USER/Downloads/unscaled_wdbc.csv") |>
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.
knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 7) |>
set_engine("kknn") |>
set_mode("classification")
uc_recipe <- recipe(Class ~ Area + Smoothness, data = unscaled_cancer) |>
step_scale(all_predictors()) |>
step_center(all_predictors())knn_fit <- workflow() |>
add_recipe(uc_recipe) |>
add_model(knn_spec) |>
fit(data = unscaled_cancer)
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(7, data, 5), kernel = ~"rectangular")
##
## Type of response variable: nominal
## Minimal misclassification: 0.112478
## Best kernel: rectangular
## Best k: 7
new_observation <- tibble(Area = c(500, 1500), Smoothness = c(0.075, 0.1))
prediction <- predict(knn_fit, new_observation)
predictionLibrary tidymodels juga menyediakan workflow. Sekarang, kita akan melakukan analisis dengan langkah yang tidak memerlukan kode yang banyak. Dibawah ini, kita akan menggunakan :
# create the grid of area/smoothness vals, and arrange in a data frame
are_grid <- seq(min(unscaled_cancer$Area),
max(unscaled_cancer$Area),
length.out = 100)
smo_grid <- seq(min(unscaled_cancer$Smoothness),
max(unscaled_cancer$Smoothness),
length.out = 100)
asgrid <- as_tibble(expand.grid(Area = are_grid,
Smoothness = smo_grid))
# use the fit workflow to make predictions at the grid points
knnPredGrid <- predict(knn_fit, asgrid)
# bind the predictions as a new column with the grid points
prediction_table <- bind_cols(knnPredGrid, asgrid) |>
rename(Class = .pred_class)
# plot:
# 1. the colored scatter of the original data
# 2. the faded colored scatter for the grid points
wkflw_plot <-
ggplot() +
geom_point(data = unscaled_cancer,
mapping = aes(x = Area,
y = Smoothness,
color = Class),
alpha = 0.75) +
geom_point(data = prediction_table,
mapping = aes(x = Area,
y = Smoothness,
color = Class),
alpha = 0.02,
size = 5) +
labs(color = "Diagnosis",
x = "Area (standardized)",
y = "Smoothness (standardized)") +
scale_color_manual(labels = c("Malignant", "Benign"),
values = c("orange2", "steelblue2")) +
theme(text = element_text(size = 12))
wkflw_plot