Introduction to Data Science
TUGAS 3 : Classification and Predicting
Kontak | : \(\downarrow\) |
: ferd.widjaya@gmail.com | |
: https://www.instagram.com/ferd_nw/ | |
RPubs | : https://rpubs.com/ferdnw/ |
What is Classification ?
Dalam statistika, klasifikasi adalah engidentifikasi yang mana dari kumpulan kategori (sub-populasi) yang menjadi suatu bahan observasi baru, berdasarkan kumpulan data pelatihan yang berisi observasi (atau contoh) yang keanggotaan kategorinya diketahui. Contohnya adalah menetapkan email tertentu ke kelas “spam” atau “non-spam”. Bisa Juga dalam dunia medis untuk mengetahui kondisi atau gejala tertentu berdasarkan karakteristiknya.
Basically, Classification adalah mengelompokkan atau membagi-bagi data yang dimiliki dengan memperhatikan suatu faktor yang menjadi acuan kita dalam membedakan dan mengelompokkan data tersebut.
Kali ini, Clasification dilakukan dengan menggunakan KNN (K-Nearest Neighbour) adalah sebuah algoritma pelatihan untuk mengklasifikasikan suatu data baru berdasarkan kategori mayoritas banyaknya K data pelatihan yang terdekat dengannya (nearest neighbor). Tujuan utama dari algoritma ini adalah untuk mengklasifikasikan suatu obyek baru berdasarkan atribut dan sampel pelatihan.
KNN dapat membantu mengklasifikasikan data yang dimiliki sesuai dengan faktor yang kita tentukan, contohnya adalah permasalahan mengenai Karakteristik Kanker yang bisa diklasifikasikan Ganas atau Jinak di Dataset berikut
Exploring Data Set
Data yang di impor dan explore adalah dataset yang bernama wdbc.csv
dimana isinya tentang data kanker payudara. Setiap barisnya memiliki sampel gambaran tumor pada kankernya, dan juga diagnosis nya (Jinak dan Ganas) serta pengukuran nya.
Jika ingin melakukan sebuah diagnosa terhadap suatu penyakit, dibutuhkan cara yang detail sehingga hasilnya bisa akurat. Seorang dokter Tidak bisa mendiagnosa sebuah penyakit hanya dengan feeling saja. Salah Diagnosa bisa mengakibatkan salah penanganan dan pengobatan yang malah bisa memperparah penyakit atau yang lebih fatal. Ada berbagai pertimbangan dan pengecekan yang dilakukan dalam mendiagnosa penyakit agar hasilnya lebih akurat juga klasifikasi penyakit tersebut bersifat jinak atau justru bersifat ganas.
Import Data
library(tidyverse)
<- read.csv("https://raw.githubusercontent.com/UBC-DSCI/introduction-to-datascience/master/data/wdbc.csv")
cancer cancer
Describing the Variables
Setelah kita mengimpor dataset yang kita inginkan, alangkah baiknya bila kita mengetahui data yang memiliki banyak kolom dengan posisi menyamping dibandingkan posisi menurun. Untuk melakukan hal ini, kita perlu menggunakan fungsi glimpse
agar memudahkan 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
: Disini terdapat beberapa kolom yang ada di dalam data. Kolom-kolom itu adalah 1. ID: Nomor Identitas Pasien
2. Class: Diagnosa (Ganas dan Jinak)
3. Radius: rata-rata jarak dari pusat ke titik-titik pada keliling
4. Texture: standar deviasi nilai skala abu-abu
5. Perimeter: seberapa panjang kontur sekitarnya
6. Area: besarnya area di dalam kontur
7. Smoothness: variasi lokal dalam panjang radius
8. Compactness: rasio keliling kuadrat dan luas
9. Concavity: Kecekungannya
10. Concave_points: jumlah bagian cekung dari kontur
11. Symmetry: seberapa mirip inti ketika dicerminkan
12. Fractal_Dimension: menunjukkan seberapa kasar kelilingnya
Dari data di atas kita bisa melihat bahwa kolom Class
adalah character. Karena dalam kondisi ini kolom Class
merupakan kolom dari jenis yang akan kita analisis dari data, maka dari itu kita perlu mengubah menjadi factor dengan 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 perlu menggunakan fungsi pull
untuk mengesktrak 1 kolom lalu fungsi levels
untuk melihat kategori apa saja yang ada di dalam kolom itu. Dan seperti yang kita lihat, terdapat kategori M dan B dalam kolom Class.
|>
cancer pull(Class) |>
levels()
## [1] "M" "B"
Exploring the Dataset
Kita juga perlu untuk mengetahui frekuensi dan proporsi dari kolom Class agar kita mengetahui data menunjukkan berapa jumlah tumor ganas dan berapa jumlah tumor jinak nya. Dalam hal ini kita menggunakan fungsi group_by
.Setelah itu, kita juga perlu mengetahui presentase setiap jenis tumor nya, disini kita bisa kalkulasikan dengan menggunakan count
yang dimana kita akan membagi frekuensi jenis tumor dengan kolom yang dikali dengan 100.
<- nrow(cancer)
num_obs |>
cancer group_by(Class) |>
summarize(
count = n(),
percentage = n() / num_obs * 100
)
Langkah selanjutnya, membuat grafik scatterplot nya.Dengan memplot variabel Perimeter dan Concavity.
<- cancer |>
perim_concav 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", "cyan")) +
theme(text = element_text(size = 12))
perim_concav
Seperti pada grafik di atas, sebaran jenis tumor jinak atau Benign yang memiliki nilai kecekungan dan keliling yang rendah, dilihat dari letak sebarannya di bawah kiri. Sedangkan pada sebaran kanan atas, menunjukkan tumor jenis ganas atau Malignant yang memiliki tingkatan yang tinggi.
Classification with K-Nearest Neighbour (KNN)
Untuk membuat prediksi yanglebih kuat dan akurat , kita perlu untuk melakukan langkah pengklasifikasian atau metode K-Nearest Neighbor. Step by step dalam KNN
Distance Between Points
Langkah selanjutnya, kita perlu mencoba membuat grafiknya agar kita mengetahui hubungan antara perimeter dengan concavity nya. Warna kuning berarti diagnosis Malignant dan warna hijau untuk diagnosis Benign. Disini kita menggunakan grafik scatterplot agar lebih mudah untuk melihat jenis diagnosis nya.
<- 0
new_obs_Perimeter <- 3.5
new_obs_Concavity |>
cancer select(ID, Perimeter, Concavity, Class) |>
mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 +
- new_obs_Concavity)^2)) |>
(Concavity arrange(dist_from_new) |>
slice(1:5) # take the first 5 rows
More than two explanatory variables
Pada langkah ini menggunakan rumus dengan lebih banyak dimensi. Seperti dalam peritungan kita ingin menghitung 3 variabel. yaitu perimeter, concavity, dan symmetry. Pada contoh sebelumnya, kita hanya menggunakan 2 variabel yang menjumlahkan selisih kuadrat antara kedua variabelnya, dan kemudian di akar kuadratkan.
Mari kita coba hitung untuk mencari K=5 neighbors ketika kita memiliki 3 prediktor dibawah ini.
<- 0
new_obs_Perimeter <- 3.5
new_obs_Concavity <- 1
new_obs_Symmetry
|>
cancer select(ID, Perimeter, Concavity, Symmetry, Class) |>
mutate(dist_from_new = sqrt((Perimeter - new_obs_Perimeter)^2 +
- new_obs_Concavity)^2 +
(Concavity - new_obs_Symmetry)^2)) |>
(Symmetry arrange(dist_from_new) |>
slice(1:5) # take the first 5 rows
Summarize
Berdasarkan K=5 dgn 3 prediktor yang kita pakai di atas, pengamatan baru menghasilkan pengklasifikasian yan menunjukkan kelas malignant.
KNN with tidymodels
Langkah berikut ini kita ingin menampilkan data yang berisi kolom Class, Perimeter, Concavity saja untuk memfokuskan pengklasifikasian pada K-Nearest Neighbors. Kita menggunakan fungsi select
untuk menampilkan kolom yang ingin kita tampilkan.
library(tidymodels)
<- cancer |>
cancer_train select(Class, Perimeter, Concavity)
cancer_train
Pada step ini , mulailah untuk membuat model klasifikasi KNN nya dengan menggunakan fungsi nearest_neighbor
. dimana K nya adalah 5. Kita juga memakai jarak garis lurus berupa rectangular. Lalu Set_engine
digunakan untuk menentukan model apa yang akan dipakai dalam mengklasifikasi. dan set_mode
dengan classification untuk melakukan klasifikasi.
<- nearest_neighbor(weight_func = "rectangular", neighbors = 5) |>
knn_spec set_engine("kknn") |>
set_mode("classification")
knn_spec
## K-Nearest Neighbor Model Specification (classification)
##
## Main Arguments:
## neighbors = 5
## weight_func = rectangular
##
## Computational engine: kknn
Disini mengguakan library kknn
untuk melakukan klasifikasi KNN. Langkah pertama adalah menyesuaikan pemodelan dengan dataset nya menggunakan fungsi fit. Di langkah ini kita juga harus menentukan variabel apa yang diinginkan untuk dijadikan target dan prediktor. Pada kali ini, kita akan menjadikan variabel Class sebagai target serta perimeter dan concavity menjadi predictor.
library(kknn)
## Warning: package 'kknn' was built under R version 4.1.2
<- knn_spec |>
knn_fit fit(Class ~ Perimeter + Concavity, data = cancer_train)
Kita juga dapat menggunakan sintaks singkatan menggunakan titik, Class ~ ., untuk menunjukkan bahwa kita ingin menggunakan setiap variabel kecuali Class sebagai prediktor dalam model.
<- knn_spec |>
knn_fit fit(Class ~ ., data = cancer_train)
knn_fit
## parsnip model object
##
## Fit time: 31ms
##
## 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
Di sini Anda dapat melihat ringkasan model terlatih terakhir. Ini menegaskan bahwa mesin komputasi yang digunakan untuk melatih model adalah kknn::train.kknn.
Pada langkah dibawah ini, kita akan memprediksi datanya. Kira menggunakan fungsi predict()
untuk memprediksi data yang ingin kita prediksi. Dan ketika kita run, kita bisa melihat hasilnya. Hasilnya menunjukkan hasil klasifikasi yang memprediksi adanya pengamatan baru sebagai M atau tipe ganas.
<- tibble(Perimeter = 0, Concavity = 3.5)
new_obs predict(knn_fit, new_obs)
Akan tetapi, sebuah prediksi tidaklah 100% benar, selalu ada ruang untuk kesalahan. Prediksi pengklasifikasi mungkin besar kemungkinannya untuk benar, maka dari itu tidak ada salahnya akan membuat prediksi kita lebih akurat untuk memperbesar peluang benar.
Data preprocessing with tidymodels
Centering and scaling
Untuk melakukan scaling dan pemusatan data, kita perlu mean dari variabel kita (rata-rata, yang mengkuantifikasi nilai “pusat” dari serangkaian angka) dan standar deviasi (angka yang mengukur seberapa tersebar nilai). Untuk setiap nilai variabel yang diamati, kita kurangi mean (yaitu, pusatkan variabel) dan bagi dengan standar deviasi (yaitu, skala variabel). Ketika kita melakukan ini, data dikatakan terstandarisasi, dan semua variabel dalam kumpulan data akan memiliki rata-rata 0 dan simpangan baku 1. Metode ini mirip dengan menghitung Zscores, atau jarak penyebaran data tersebut dari pusatnya.
Kita akan menggunakan variabel Area, Smoothness, dan Class dalam dataset unscaled_wdbc.csv
.
Seperti tadi, kita menjadikan variabel Class menjadi factor
<- read.csv("https://raw.githubusercontent.com/UBC-DSCI/introduction-to-datascience/master/data/unscaled_wdbc.csv") |>
data.unscaled mutate(Class = as_factor(Class)) |>
select(Class, Area, Smoothness)
data.unscaled
Melihat data yang unscaled dan uncentered ,TErlihat bahwa perbedaan antara nilai untuk pengukuran area jauh lebih besar daripada untuk kehalusan. Apakah ini akan memengaruhi prediksi? Untuk mengetahuinya, scatter dari dua prediktor ini (diwarnai oleh diagnosis) untuk data tidak standar yang baru saja kami muat, dan versi standar dari data yang sama. Tapi pertama-tama, kita perlu membakukan kumpulan data unscaled_cancer dengan model rapi.
<- recipe(Class ~ ., data = data.unscaled)
uc_recipe print(uc_recipe)
## Recipe
##
## Inputs:
##
## role #variables
## outcome 1
## predictor 2
lakukan penskalaan (step_scale) dan pemusatan (step_center) untuk semua prediktor sehingga masing-masing memiliki rata-rata 0 dan standar deviasi 1. Perhatikan bahwa cleanverse sebenarnya menyediakan step_normalize, yang melakukan pemusatan dan penskalaan dalam satu langkah resep ; dalam buku 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 (di sini, unscaled_cancer) untuk menghitung apa pun yang diperlukan untuk menjalankan resep (dalam hal ini, 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 ingin menambahkan langkah menuju ke recipe. 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()
: tentukan semua variabel kategori atau semua numerik
2. all_predictors()
dan all_outcomes()
: tentukan semua prediktor atau semua variabel target
3. Area, Smoothness
: tentukan variabel Area dan Smoothness
4. Class
: tentukan semuanya kecuali variabel Class
Anda dapat menemukan set lengkap semua langkah dan fungsi pemilihan variabel di halaman referensi resep.
Pada langkah sebelumnya, kita telah menghitung statistik data dengan input data ke recipe. Tetapi datanya nya belum terskala dan terpusat. Untuk benar-benar menskalakan dan memusatkan datanya, kita gunakan fungsi bake()
<- bake(uc_recipe, data.unscaled)
scaled_cancer scaled_cancer
Balancing
Masalah potensial lain dalam kumpulan data untuk pengklasifikasi adalah ketidakseimbangan kelas, yaitu ketika satu label jauh lebih umum daripada yang lain (outliers). Karena saat melakukan KNN menggunakan label titik terdekat untuk memprediksi label titik baru, jika ada lebih banyak titik data dengan satu label secara keseluruhan, algoritme lebih cenderung memilih label itu secara umum (bahkan jika “pola” dari data menunjukkan sebaliknya), Merusak pola predictionnya.
<- bind_rows(
rare_cancer filter(cancer, Class == "B"),
|> filter(Class == "M") |> slice_head(n = 3)
cancer |>
) select(Class, Perimeter, Concavity)
<- rare_cancer |>
rare_plot 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("darkgoldenrod2", "lightgreen")) +
theme(text = element_text(size = 12))
rare_plot
Dalam kode berikut ini, tujuannya untuk balancing data. Tapi dengan melakukan oversampling Class nya. Disini kita akan menggunakan library themis
dalam menggunakan fungsi step_upsample
.
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
<- recipe(Class ~ ., data = rare_cancer) |>
ups_recipe 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]
<- bake(ups_recipe, rare_cancer)
upsampled_cancer
|>
upsampled_cancer group_by(Class) |>
summarize(n = n())
Dan seperti yang bisa kita lihat, Class dari M dan B telah seimbang.
Putting it together in a workflow
Library tidymodels
juga menyediakan workflow. Kali ini kita akan melakukan analisis dengan langkah yang tidak perlu kode yang banyak. Disini kita akan menggunakan dataset 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
<- read_csv("https://raw.githubusercontent.com/UBC-DSCI/introduction-to-datascience/master/data/unscaled_wdbc.csv") |>
unscaled_cancer 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
<- nearest_neighbor(weight_func = "rectangular", neighbors = 7) |>
knn_spec set_engine("kknn") |>
set_mode("classification")
# create the centering / scaling recipe
<- recipe(Class ~ Area + Smoothness, data = unscaled_cancer) |>
uc_recipe step_scale(all_predictors()) |>
step_center(all_predictors())
Sekarang, menempatkan langkah-langkah ini dalam alur kerja menggunakan fungsi add_recipe dan add_model, dan terakhir menggunakan fungsi fit untuk menjalankan seluruh alur kerja pada data unscaled_cancer. Perhatikan perbedaan lain dari sebelumnya di sini:
<- workflow() |>
knn_fit 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
<- tibble(Area = c(500, 1500), Smoothness = c(0.075, 0.1))
new_observation <- predict(knn_fit, new_observation)
prediction
prediction
Library tidymodels
juga menyediakan workflow. Kali ini kita akan melakukan analisis dengan langkah yang tidak perlu kode yang banyak. Disini kita akan menggunakan
# create the grid of area/smoothness vals, and arrange in a data frame
<- seq(min(unscaled_cancer$Area),
are_grid max(unscaled_cancer$Area),
length.out = 100)
<- seq(min(unscaled_cancer$Smoothness),
smo_grid max(unscaled_cancer$Smoothness),
length.out = 100)
<- as_tibble(expand.grid(Area = are_grid,
asgrid Smoothness = smo_grid))
# use the fit workflow to make predictions at the grid points
<- predict(knn_fit, asgrid)
knnPredGrid
# bind the predictions as a new column with the grid points
<- bind_cols(knnPredGrid, asgrid) |>
prediction_table 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("darkgoldenrod2", "lightgreen")) +
theme(text = element_text(size = 12))
wkflw_plot