บทความนี้แอดเขียนอธิบาย interface การสร้าง machine learning โมเดลใน R ด้วย package caret (ย่อมาจาก Classification And REgression Training) ส่วนตัวแอดใช้ caret เป็นประจำใน workflow
- สร้างโมเดลได้มากกว่า 200+ โมเดลแบบ supervised learning
- ทรงพลัง มีฟังชั่นในการเตรียมข้อมูล, resampling, metrics ครบครัน
- และเหตุผลสำคัญที่สุดคือ caret มันเขียนง่ายมากจริงๆ (เทียบกับ framework อื่นๆ)
เปิด RStudio ขึ้นมาแล้วติดตั้ง package ด้วยโค้ดด้านล่าง เราใช้ library mlbench ด้วยเพื่อโหลด example dataset สำหรับบทความนี้
## install caret and mlbench for datasets
install.packages("caret")
install.packages("mlbench")
library(caret)
library(mlbench)
dataset ที่เราจะใช้ในบทความนี้ชื่อว่า PimaIndiansDiabetes
โดย target ที่เราต้องการทำนายคือคอลัมน์ diabetes
(pos/ neg) มีสอง classes i.e. binary classification
## load diabetes data
## binary classification problem
data("PimaIndiansDiabetes")
df <- PimaIndiansDiabetes
str(df)
Basic ML Pipeline
การเทรน machine learning สามารถแบ่งเป็น 3 ขั้นตอน
- prepare dataset/ train test split – แบ่งข้อมูลเป็น train 80% test 20%
- train model – ตัวอย่างวันนี้เราใช้ K-Nearest Neighbors
- test model – นำโมเดลไปทำนาย unseen data
## [1] split dataset into train and test
set.seed(99)
n <- nrow(df)
id <- sample(1:n, 0.8*n, replace=FALSE)
train_df <- df[id, ]
test_df <- df[-id, ]
พอเรา split data เสร็จแล้ว เราจะใช้ฟังชั่น train()
ของ caret ในการเทรนโมเดล KNN โดยฟังชั่นนี้มี 3 required arguments ได้แก่ formula, data และ method (i.e. ชื่อโมเดลที่เราต้องการเทรน)
Note – default resampling technique ของฟังชั่น train()
คือ bootstrap i.e. มีการสุ่มตัวอย่างซ้ำ 25 รอบ ใน full script section ของบทความนี้แอดมีเขียนโค้ดตัวอย่างฟังชั่น trainControl()
เพื่อเปลี่ยน resampling เป็น k-fold cross validation กำหนด k=5
## [2] train model
set.seed(99)
knn_model <- train(diabetes ~ ., data = train_df, method = "knn")
print(knn_model)

caret จะสุ่มค่า K หรือ hyperparameter ของ KNN ว่า K เท่าไหร่ที่จะทำให้ train accuracy มีค่าสูงที่สุด จากผลลัพธ์ด้านบน caret เลือก K=9 (acc = 0.7265) สำหรับ final model ของเรา
ขั้นตอนสุดท้ายคือการทำ prediction กับ test_df โดยฟังชั่นที่เราใช้ใน R คือ predict()
ตรงๆเลย ฟังชั่นนี้รับสอง required arguments คือโมเดลที่เราเทรนและ newdata เสร็จแล้วคำนวณค่า overall accuracy ด้วยฟังชั่น mean(predict == actual)
ตามตัวอย่างด้านล่าง
## [3] test model
p <- predict(knn_model, newdata = test_df)
mean(p == test_df$diabetes)
train accuracy = 0.7265 และ test accuracy = 0.7077 การเทรนโมเดลของเราเสร็จสมบูรณ์ โมเดลค่อนข้าง good fit ดูง่ายๆจากค่า accuracy ของ train vs. test ที่ไม่ต่างกันมาก (ปกติ test จะได้ค่าลดลงมานิดหน่อย)
Note – ค่า accuracy ที่นักเรียนรันได้บน laptop ตัวเองอาจจะต่างกับตัวอย่างนี้นิดหน่อยเพราะว่า seed ของคอมพิวเตอร์แต่ละเครื่องไม่เท่ากัน
Confusion Matrix
นอกจากค่า overall accuracy ที่เราคำนวณด้วยโค้ดด้านบน เราสามารถสร้าง confusion matrix ด้วยฟังชั่น table(predict, actual)
เพื่อคำนวณ metrics อื่นๆ เช่น precision, recall, F1-score ได้ง่ายๆ
## we can evaluate model with confusion matrix
table(p, test_df$diabetes, dnn = c("predicted", "actual") )
Full Script
R script ทั้งหมดที่เราสอนในบทความนี้ นักเรียนสามารถ copy ไปรันใน RStudio ได้เลย โค้ดไลน์ที่ 26-27 เราสามารถเปลี่ยน bootstrap resampling เป็น k-fold cross validation ด้วย argument trControl
## install caret and mlbench for datasets | |
install.packages("caret") | |
install.packages("mlbench") | |
library(caret) | |
library(mlbench) | |
## load diabetes data | |
## binary classification problem | |
data("PimaIndiansDiabetes") | |
df <- PimaIndiansDiabetes | |
str(df) | |
## [1] split dataset into train and test | |
set.seed(99) | |
n <- nrow(df) | |
id <- sample(1:n, 0.8*n, replace=FALSE) | |
train_df <- df[id, ] | |
test_df <- df[–id, ] | |
## [2] train model | |
set.seed(99) | |
knn_model <- train(diabetes ~ ., data = train_df, method = "knn") | |
print(knn_model) | |
## optional train with cross-validation | |
## knn_model <- train(diabetes ~ ., data = train_df, method = "knn", | |
## trControl = trainControl(method = "cv", number = 5)) | |
## [3] test model | |
p <- predict(knn_model, newdata = test_df) | |
mean(p == test_df$diabetes) | |
## we can evaluate model with confusion matrix | |
table(p, test_df$diabetes, dnn = c("predicted", "actual") ) |
Appendix
เราสามารถเขียน wrap โค้ดที่ใช้ในการแบ่ง train_df และ test_df เป็นฟังชั่น train_test_split
ตามตัวอย่างด้านล่าง ไลน์สุดท้ายจะ return output ออกมาเป็น list ของสอง datasets
## write train_test_split function
train_test_split <- function(data, train_size) {
set.seed(99)
n <- nrow(data)
id <- sample(1:n, train_size*n, replace=FALSE)
train_df <- data[id, ]
test_df <- data[-id, ]
## return a list of two datasets
list(train = train_df, test = test_df)
}
ทดลองใช้งานฟังชั่น ลองตั้งค่า train_size = 0.75 สร้าง object list_data เสร็จแล้วใช้วิธีการ subset แบบนี้ list_data[[1]]
และ list_data[[2]]
เพื่อสร้าง train_df และ test_df ตามลำดับ
## test function
list_data <- train_test_split(PimaIndiansDiabetes, train_size = 0.75)
str(list_data)
train_df <- list_data[[1]]
test_df <- list_data[[2]]
I’m here to help! ถ้ามีคำถามเกี่ยวกับบทความนี้ ทักแชทมาคุยกับเราได้เลยที่ m.me/datarockie
Leave a Reply