รู้จักกับ caret – ML Lib ที่ทรงพลังที่สุดของภาษา R

บทความนี้แอดเขียนอธิบาย 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 ขั้นตอน

  1. prepare dataset/ train test split – แบ่งข้อมูลเป็น train 80% test 20%
  2. train model – ตัวอย่างวันนี้เราใช้ K-Nearest Neighbors
  3. 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)
result ของการเทรนโมเดล KNN

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") )

10 ML Metrics ที่ควรรู้จัก

อ่านเพิ่มเติมเรื่อง classification metrics มีให้เลือกใช้หลายตัว เช่น accuracy, precision, recall, F1-score พร้อมสูตรคำนวณง่ายๆจากตาราง confusion matrix

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

2 thoughts on “รู้จักกับ caret – ML Lib ที่ทรงพลังที่สุดของภาษา R

  1. KNN นี้สามารถ plot ออกมาดูได้ด้วยคำสั่งอะไรหรอครับ

    1. Plot ยากเลยครับ ถ้ามี features หลายตัว อาจจะต้องเลือก feature ออกมาสองตัวก่อน แล้วทำ scatter plot ง่ายๆ

Leave a Reply