Introduction to Data Science
Tugas 3 Chapter 5 Classification I: Training & Predicting
| Kontak | : \(\downarrow\) |
| naftaligunawan@gmail.com | |
| https://www.instagram.com/nbrigittag/ | |
| RPubs | https://rpubs.com/naftalibrigitta/ |
5.1 Overview
Dalam bab ini, kita akan lebih fokus pada klasifikasi data, baik yang menggunakan satu atau lebih variabel untuk memprediksi nilai variabel kategoris yang diminati.
Dan di bab ini akan membahas dasar-dasar klasifikasi, bagaimana melakukan praproses data agar sesuai untuk digunakan dalam pengklasifikasi, dan bagaimana menggunakan data yang diamati untuk membuat prediksi.
5.2 Chapter Learning Objectives
Setelah mempelajari sampai akhir bab, para pembaca diharapkan bisa melakukan hal-hal dibawah ini, antara lain :
Mengenali situasi di mana pengklasifikasi akan sesuai untuk membuat prediksi.
Menjelaskan apa yang dimaksud dengan kumpulan data pelatihan dan bagaimana data tersebut digunakan dalam klasifikasi.
Menafsirkan hasil yang keluar (output) dari classifier.
Menghitung dengan tangan, jarak garis lurus (Euclidean) antara titik-titik pada grafik ketika ada dua variabel prediktor.
Menjelaskan K-Algoritma klasifikasi tetangga terdekat.
Melakukan K-klasifikasi tetangga terdekat di R menggunakan
tidymodels.Menggunakan
recipe (resep)untuk melakukan praproses data agar terpusat, diskalakan, dan seimbang.Menggabungkan praproses dan pelatihan model menggunakan
workflow.
5.3 The Classification Problem
Ada banyak kemungkinan metode yang dapat kita gunakan untuk memprediksi kelas/label kategoris untuk suatu observasi. Dalam buku ini, kita akan fokus pada yang banyak digunakan K-algorithem neighbor terdekat (Fix and Hodges 1951; Cover and Hart 1967).
Dalam studi masa depan, kita mungkin akan menemukan pohon keputusan, mesin vektor pendukung (SVM), regresi logistik, jaringan saraf, dan banyak lagi.
5.4 Exploring a Data Set
Pada tugas ini, saya akan impor dataset wdbc.csv, isi dari dataset nya mengenai data kanker payudara. Setiap barisnya mempunyai sampel gambar tumor pada kankernya, dan diagnosis nya (Tumor Jinak dan Tumor Ganas) serta pengukuran nya.
Pada dasarnya, ketika kita ingin mendiagnosa sesuatu tumor, dibutuhkan cara yang detail dan akurat sehingga hasilnya juga akurat. Kita tidak bisa memprediksi atau mendiagnosa sebuah tumor hanya dengan penglihatan kita saja. Pasti hasilnya tidak akurat. Maka dari itu, perlu dilakukan diagnosa tumor yang lebih akurat agar kita mengetahui tumor tersebut bersifat jinak atau justru bersifat ganas.
5.4.1 Loading the cancer data
Pertama-tama, seperti biasa kita harus mengimport data csv yang berada di file komputer atau laptop kita.
library(tidyverse)
cancer <- read.csv("C:/Users/Naftali Brigitta/Documents/Kampus/PDS/wdbc.csv", sep=",")
cancer5.4.2 Describing the variables in the cancer data set
Setelah mengimport data, kita akan mengecek data. Ternyata data kita memiliki banyak kolom dengan posisi menyamping dibandingkan posisi menurun. Untuk melakukan hal ini, kita perlu menggunakan fungsi glimpse untuk mempermudah kita dalam melihat dataset nya.
glimpse(cancer)## Rows: 569
## Columns: 12
## $ ID <int> 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~
Note : Berikut beberapa kolom yang ada di dalam data. Kolom-kolom itu, antara lain :
1. ID: Nomor Identitas
2. Class: untuk menunjukkan Jenis diagnosa nya (bersifat jinak atau ganas)
3. Radius: untuk menunjukkan rata-rata jarak dari pusat ke titik-titik pada keliling
4. Texture: untuk menunjukkan standar deviasi nilai skala abu-abu
5. Perimeter: untuk menunjukkan panjang kontur sekitarnya
6. Area: untuk menunjukkan area di dalam kontur
7. Smoothness: untuk menunjukkan variasi lokal dalam panjang radius
8. Compactness: untuk menunjukkan rasio keliling kuadrat dan luas
9. Concavity: untuk menunjukkan Kecekungannya
10. Concave_points: untuk menunjukkan jumlah bagian cekung dari kontur
11. Symmetry: untuk menunjukkan seberapa mirip inti ketika dicerminkan
12. Fractal_Dimension: untuk menunjukkan seberapa kasar kelilingnya
Dari data di atas kita bisa melihat bahwa kolom Class merupakan bentuk dalam Character. Karena dalam kondisi ini kolom Class merupakan kolom dari jenis yang mewakili data, makanya kita perlu mengubah menjadi factor dengan menggunakan fungsi as_factor.
cancer <- cancer |>
mutate(Class = as_factor(Class))
glimpse(cancer)## Rows: 569
## Columns: 12
## $ ID <int> 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~
Untuk melihat kategori yang ada di dalam kolom Class, kita menggunakan fungsi pull untuk mengesktrak 1 kolom, lalu fungsi levels untuk melihat kategori apa saja yang ada di dalam kolom itu. Dan hasil yang dapat kita lihat, yaitu terdapat kategori M dan B dalam kolom Class.
cancer |>
pull(Class) |>
levels()## [1] "M" "B"
5.4.3 Exploring the cancer data
Untuk mengetahui frekuensi dari tiap kolom Class, yaitu mengetahui data menunjukkan berapa jumlah tumor ganas dan berapa jumlah tumor jinak nya. Kita akan menggunakan fungsi group_by.Setelah itu, kita juga perlu mengetahui presentase setiap jenis tumor nya, kita akan mengkalkulasikan dengan memakai fungsi count, dimana kita akan membagi frekuensi jenis tumor dengan kolom yang dikali dengan 100.
num_obs <- nrow(cancer)
cancer |>
group_by(Class) |>
summarize(
count = n(),
percentage = n() / num_obs * 100
)Untuk langkah selanjutnya, kita memulai membuat grafik scatterplot nya, dimana kita akan memplot variabel Perimeter dan Concavity.
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("orange", "blue")) +
theme(text = element_text(size = 12))
perim_concavHasil dari grafik di atas, dapat disimpulkan bahwa sebaran bawah kiri menunjukkan sebaran jenis tumor Jinak atau Benign (berwarna biru) yang memiliki nilai kecekungan dan keliling yang rendah. Sedangkan jika kita perhatikan pada sebaran kanan atas, sebaran tersebut menunjukkan tumor jenis Ganas atau Malignant (berwarna orange) yang memiliki tingkatan yang tinggi.
5.5 Classification with K-nearest neighbors
Untuk membuat prediksi kita lebih kuat, kita perlu melakukan langkah pengklasifikasian atau metode K-Nearest Neighbor. Untuk mengetahui penggunaannya, mari kita coba langkah-langkah dibawah ini :
5.5.1 Distance Between Points
Pada langkah ini, kita akan mencoba membuat grafik, agar kita mengetahui hubungan antara perimeter dengan concavity nya. Yang berwarna orange berarti diagnosis Malignant dan berwarna biru untuk diagnosis Benign. Dibawah ini, kita menggunakan grafik scatterplot agar lebih mudah untuk melihat hasil dari jenis diagnosis nya.
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:5) # take the first 5 rows5.5.2 More Than Two Explanatory Variables
Pada langkah ini, kita kita menggunakan rumus yang lebih banyak dimensi. Saat ini kita ingin menghitung 3 variabel, yaitu Perimeter, Concavity, and Symmetry. Pada contoh sebelumnya, kita hanya menggunakan 2 variabel yang menjumlahkan selisih kuadrat antara kedua variabelnya, dan kemudian di akar kuadratkan.
Sekarang, mari kita coba menghitung untuk mencari K=5 neighbors ketika kita memiliki 3 prediktor dibawah ini.
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:5) # take the first 5 rows5.5.3 Summary of K-nearest Neighbors Algorithm
Berdasarkan K=5 dengan 3 prediktor yang kita pakai di atas, kita mendapatkan pengamatan baru hasil dari pengklasifikasian yang menunjukkan K-nearest neighbors adalah kelas Malignant, yaitu data berwarna orange, yang merupakan tumor jenis ganas.
5.6 K-nearest neighbors with tidymodels
Pada langkah di bawah ini, kita ingin menampilkan data yang berisi kolom Class, Perimeter, Concavity untuk memfokuskan pengklasifikasian pada K-Nearest Neighbors. Kita akan menggunakan fungsi select untuk menampilkan kolom yang ingin kita tampilkan di bawah ini.
library(tidymodels)
cancer_train <- cancer |>
select(Class, Perimeter, Concavity)
cancer_trainPada langkah di bawah ini kita akan memulai untuk membuat model klasifikasi K-nearest neighbors nya dengan menggunakan fungsi nearest_neighbor, dimana K nya adalah 5. Kita memakai rectangular sebagai jarak garis lurusnya. Kemudian kita akan menggunakan fungsi Set_engine yang berguna untuk menentukan model apa yang ingin kita pakai dalam mengklasifikasi, dan fungsi set_mode dengan classification yang berguna untuk melakukan klasifikasi.
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
Pada tahap selanjutnya, yang perlu kita lakukan adalah perlu menyesuaikan pemodelan dengan dataset nya terlebih dahulu menggunakan fungsi fit. Pada langkah ini, kita juga menentukan variabel apa yang akan kita jadikan target dan prediktor. Kita akan menjadikan variabel Class sebagai target serta perimeter dan concavity menjadi predictor.
knn_fit <- knn_spec |>
fit(Class ~ Perimeter + Concavity, data = cancer_train)Kita juga dapat menggunakan sintaks singkatan menggunakan titik (.), yaitu Class ~ ., untuk menunjukkan bahwa kita ingin menggunakan setiap variabel kecuali Class sebagai prediktor dalam model.
knn_fit <- knn_spec |>
fit(Class ~ ., data = cancer_train)
knn_fit## parsnip model object
##
## Fit time: 20ms
##
## 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
Pada langkah dibawah ini, kita akan memprediksi datanya, dengan menggunakan fungsi predict() yaitu untuk memprediksi data yang ingin kita prediksi. Hasilnya akan menunjukkan hasil klasifikasi yang memprediksi adanya pengamatan baru sebagai M atau tipe tumor yang ganas.
new_obs <- tibble(Perimeter = 0, Concavity = 3.5)
predict(knn_fit, new_obs)5.7 Data preprocessing with tidymodels
5.7.1 Centering and scaling
Untuk menghitung skala dan pusat data kita, kita perlu menemukan hasil dari mean variabel (rata-rata, yang mengkuantifikasi nilai “pusat” dari serangkaian angka) dan standar deviasi (angka yang mengukur seberapa tersebar nilai nya).
Kita akan menggunakan variabel Area, Smoothness, dan Class. Sekarang, kita akan memakai dataset unscaled_wdbc.csv.
Seperti biasa, kita akan membuat variabel Class menjadi factor.
unscaled_cancer <- read.csv("C:/Users/Naftali Brigitta/Documents/Kampus/PDS/unscaled_wdbc.csv", sep = ",") |>
mutate(Class = as_factor(Class)) |>
select(Class, Area, Smoothness)
unscaled_cancerKita dapat melihat data di atas yang tidak berskalakan dan tidak terpusat , terlihat bahwa perbedaan antara nilai untuk pengukuran area jauh lebih besar daripada untuk kehalusan. Untuk mengetahui apakah berpengaruh pada prediksi, kita akan membuat plot pencar dari kedua prediktor ini (diwarnai oleh diagnosis). Pertama kita perlu membakukan kumpulan data memakai unscaled_cancer dengan model lebih rapih.
uc_recipe <- recipe(Class ~ ., data = unscaled_cancer)
print(uc_recipe)## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
Kita dapat menambahkan langkah penskalaan memakai step_scale dan langkah pemusatan memakai step_center, untuk semua prediktor sehingga masing-masing memiliki rata-rata 0 dan standar deviasi 1. Dalam bagian ini, kita akan memisahkan step_scale dan step_center untuk menekankan secara konseptual bahwa ada dua langkah yang terjadi. Fungsi persiapan menyelesaikan resep dengan menggunakan data unscaled_cancer untuk menghitung apa pun yang diperlukan, sedangkan untuk menjalankan resep kita memakai rata-rata kolom dan simpangan baku.
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]
Ketika kita mau menambahkan langkah menuju ke recipe, kita harus menentukan kolom mana yang ingin kita tambahkan. Di sini kita menggunakan fungsi all_predictors() untuk menentukan bahwa setiap langkah harus diterapkan ke semua variabel prediktor. Namun, ada juga argumen serta sintaks lain yang dapat digunakan dan memiliki fungsi sebagai berikut:
1. all_nominal() dan all_numeric(): untuk menententukan semua variabel kategori atau semua numerik.
2. all_predictors() dan all_outcomes(): untuk menententukan semua prediktor atau semua variabel target.
3. Area, Smoothness: untuk menententukan variabel Area dan Smoothness.
4. Class: untuk menententukan semuanya kecuali variabel class.
Pada langkah sebelumnya, kita sudah menghitung statistik data dengan input data ke recipe. Tetapi datanya nya belum terskala dan terpusat. Agar data benar-benar berskala dan berpusat datanya, kita akan menggunakan fungsi bake().
scaled_cancer <- bake(uc_recipe, unscaled_cancer)
scaled_cancer5.7.2 Balancing
Masalah lain dalam kumpulan data untuk mengklasifikasi adalah ketidakseimbangan kelas, yaitu ketika satu label jauh lebih umum daripada yang lain. Karena saat melakukan K-nearest neighbors kita menggunakan label titik terdekat untuk memprediksi label titik baru.
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("orange", "blue")) +
theme(text = element_text(size = 12))
rare_plotPada kode di bawah ini, tujuannya sama-sama untuk balancing data. Sekarang, kita akan melakukan balance data dengan melakukan oversampling lass nya. Kita akan menggunakan library themis dalam menggunakan fungsi step_upsample.
library(themis)## Warning: package 'themis' was built under R version 4.1.2
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())Dan seperti yang bisa kita lihat pada hasil di atas, bahwa Class M dan B telah seimbang.
5.8 Putting it together in a workflow
Library tidymodels packages juga menyediakan workflow, yaitu cara untuk menyatukan beberapa langkah analisis data tanpa banyak kode yang diperlukan untuk langkah perantara. Mari kita coba, mulai dari awal dengan data unscaled_wdbc.csv. Pertama, kita akan memuat data, membuat model, dan menentukan resep bagaimana data harus diproses sebelumnya :
# load the unscaled cancer data
# and make sure the target Class variable is a factor
unscaled_cancer <- read_csv("C:/Users/Naftali Brigitta/Documents/Kampus/PDS/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.
# create the KNN model
knn_spec <- nearest_neighbor(weight_func = "rectangular", neighbors = 7) |>
set_engine("kknn") |>
set_mode("classification")
# create the centering / scaling recipe
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("orange", "blue")) +
theme(text = element_text(size = 12))
wkflw_plot