บทความที่แล้วเราเขียนอธิบายขั้นตอนการสร้าง ML model ใน 4 ขั้นตอน และสอนเขียนโค้ด R สำหรับแก้ปัญหา Binary Classification (Titanic) วันนี้เราจะมาลองเขียน ML แก้ปัญหา Regression กันบ้าง
Regression Problem
แอดดาวน์โหลด dataset มาจาก Kaggle ชื่อว่า Boston (Housing Values in Suburbs of Boston) มีตัวแปรทั้งหมด 14 ตัว โดย target ที่เราต้องการทำนายคือ medv หรือราคาบ้านเฉลี่ยหน่วยเป็น $1000
ML เรียกปัญหานี้ว่า Regression เพราะ target ที่เราต้องการทำนายเป็นตัวเลขแบบ numeric/ continuous และ algorithm ที่เราจะสอนวันนี้คือ Linear Regression (อ่านบทความอธิบายเรื่อง LR ได้ในลิ้ง)
Load Data
ดาวน์โหลดข้อมูล Boston เพื่อทำตาม tutorial นี้หรือดู Notebook ของเราได้ที่นี่

เปิดโปรแกรม RStudio ขึ้นมาแล้ว import Boston.csv ด้วยฟังชั่น read.csv()
เราสามารถเรียกดู 6 แถวบนสุดของ dataframe ด้วยฟังชั่น head()
หรือดูจำนวนแถวและคอลั่มด้วยฟังชั่น dim()
โค้ดด้านล่างแอดใช้ฟังชั่น complete.cases()
เพื่อตรวจสอบว่าข้อมูลมี missing value หรือเปล่า? ถ้าออกมาเท่ากับ 1 แปลว่า clean 100%
df <- read.csv("Boston.csv")
mean(complete.cases(df)) # should be one for clean dataset
Split Data
เราใช้ฟังชั่น sample()
เพื่อสร้าง random ID สำหรับแบ่งข้อมูลเป็น train (80%) และ test (20%) ส่วนฟังชั่น set.seed()
ในไลน์แรกใช้ล็อคผลแรนดอม เพื่อนๆที่ทำตาม tutorial นี้เวลารันโค้ดจะได้ผลเหมือนในตัวอย่าง
set.seed(99)
id <- sample(1:nrow(df), size = 0.8, replace = FALSE)
train_df <- df[id, ]
test_df <- df[-id, ]
กฎเหล็กของ Machine Learning คือเราต้องแบ่งข้อมูลก่อนเทรนโมเดลเสมอ !! โดยทั่วไปเราอาจทำ split train/test ง่ายๆ หรือที่นิยมกว่าคือการแบ่งข้อมูลเป็นสามส่วน train/validate/test ทำ cross validation
Train and Validate
โค้ด 3 ไลน์ด้านล่างเขียนขึ้นเพื่อทำ task ต่อไปนี้
- line 1 สร้างโมเดล linear regression ด้วยฟังชั่น lm()
- line 2 ทำนาย test data ด้วยฟังชั่น predict()
- line 3 คำนวณค่า mean absolute error (MAE) สำหรับวัดผลโมเดล
lm_model <- lm(medv ~ ., data = train_df)
p <- predict(lm_model, newdata = test_df)
mae <- mean(abs(p - test_df$medv))
เวลาเทรนโมเดล เราต้องมี metrics ที่ใช้วัด performance ว่าโมเดลเราทำงานได้ดีหรือยัง? สำหรับ regression metric ตัวพื้นฐานคือ MAE ถ้าใครยังไม่คุ้นกับ metric นี้ อ่านเพิ่มเติมได้ที่บทความแนะนำด้านล่าง
Reusable Function
Tasks ที่เราต้องทำบ่อยๆ ปกติเราจะเขียนเป็นฟังชั่นไว้เลย ตัวอย่างด้านล่าง แอดเขียนฟังชั่น LinearRegression()
รับ 4 arguments เอาไว้เทรน Linear Regression กับข้อมูลอื่นๆได้เลย ง่ายอะไรเบอร์นี้!
Line 26-27 เราสั่งปริ้น train MAE และ test MAE เพื่อดูว่าโมเดลของเรา generalize ดีไหม i.e. เจอปัญหา overfitting หรือเปล่า ถ้า train และ test MAE มีค่าใกล้เคียงกัน ถือว่าโมเดลเราทำงานได้ OK!
## this function takes four inputs | |
## formula such as "mpg ~ wt + hp" (character) | |
## dataset | |
## train_size ratio between 0-1 (numeric) | |
## target such as "mpg" (character) | |
LinearRegression <- function(formula, data, train_size, target){ | |
## split dataset into train and test | |
set.seed(99) | |
n <- nrow(data) | |
id <- sample(1:n, size = train_size*n, replace = FALSE) | |
train_df <- data[id, ] | |
test_df <- data[–id, ] | |
## train model | |
train_form <- as.formula(formula) | |
lm_model <- lm(train_form, data = train_df) | |
## predictions | |
train_p <- predict(lm_model) | |
test_p <- predict(lm_model, newdata = test_df) | |
## evaluate and print result | |
train_mae <- mean(abs(train_p – train_df[[target]])) | |
test_mae <- mean(abs(test_p – test_df[[target]])) | |
cat("Train MAE:", train_mae) | |
cat("\nTest MAE:", test_mae) | |
} |
Awesome Work
ทดสอบฟังชั่น LinearRegression()
กับข้อมูล Boston อีกครั้ง โดยกำหนด train_size = 0.80 และใช้ตัวแปร X ทุกตัวใน dataframe ทำนาย medv จะได้ค่า test MAE เท่ากับ 3.4408 not bad!!
LinearRegression("medv ~ .", df, 0.80, "medv")
## Train MAE: 3.327476
## Test MAE: 3.4408
MAE = 3.4408 อธิบายได้ว่า linear regression ของเราโดยเฉลี่ยทำนาย medv ผิดไปประมาณ 3.4408 จุด (หน่วยเป็น $1000) tutorial นี้เรายังไม่ได้ทำ preprocessing data เช่น การ scale/ normalize features หรือการทำ log/ box cox transformation ที่ (ส่วนใหญ่) จะช่วยให้ algorithm เรียนรู้และทำนายผลได้ดีขึ้น
Leave a Reply