[รีวิว] แชร์ประสบการณ์แข่ง Techjam พร้อมสอนรัน randomForest ง่ายๆใน R

เกิดมาเพิ่งเคยลงแข่งอะไรยังงี้ครั้งแรก
อาทิตย์ก่อนได้มีโอกาสแข่งรอบ audition data track (machine learning) ของงาน Techjam จัดโดย KBTG เย็นวันศุกร์ 28 ก.ค. ทางทีมงานส่ง email มาให้เราเข้าไปดาวน์โหลดไฟล์ data กับ instructions ทั้งหมด 5 ข้อ มีเวลาทำถึงคืนวันที่ 30 ก.ค.
ทุกข้อเป็น binary classification หมดเลย ให้ทาย 1/0 แค่นั้นเอง เช่น predict gender (male/female) หรือ predict churn (yes/no) พอเรา train model กับ predict test data เสร็จปุ๊ป ก็กด submit ผลการทำนายของเราขึ้นไปบนเว็บของ techjam แล้วมันจะโชว์ accuracy ว่าเราทาย test data ถูกกี่ %
ใครได้ % accuracy เยอะสุด คนนั้นเข้ารอบ
แต่ gimmick ของการแข่งรอบนี้อยู่ที่ผล accuracy ที่เราเห็นตอน submit prediction result ขึ้นไปบนเว็บนั้นเป็นแค่ 50% ของ test data และผลอีก 50% ที่เหลือทีมงาน Techjam ซ่อนไว้เพื่อใช้ในการคัดทีมที่ได้คะแนน accuracy สูงสุดเข้ารอบ final ต่อไป (จริงๆวิธีการคิดคะแนนแบบนี้เหมือนกับที่ Kaggle ใช้ในหลายๆ competition เลย)
Techjam มีวิธีการคิด final scores ที่ซับซ้อนขึ้นเล็กน้อย (ไม่ขออธิบายตรงนี้ เด๋วยาว 555) แต่ง่ายๆคือถ้าอยากจะเข้ารอบต่อไป ต้องทำ accuracy ของโมเดลเราให้ได้มากที่สุดเท่าที่จะเป็นไปได้ และต้องพยายามไม่ให้ model เรา overfit!
SOFTWARE ที่ใช้ตอนแข่ง Techjam
R version 3.4.1
RStudio version 1.0.153
Packages:
dplyr สำหรับทำ data manipulation กับ clean data
lubridate สำหรับจัดการ column ที่เป็นวันที่ (date)
caret สำหรับสร้างและทดสอบ machine learning models

ข้อดีของ R คือมันเขียนได้เร็วมาก #และง่ายมาก เหมาะมากกับการแข่ง hackathon ที่มีเวลาจำกัดแบบ Techjam รอบนี้เลย โดยเฉพาะตอน clean data ใช้ package dplyr รัวๆ (เขียนโดย Hadley Wickham) ไม่ว่าจะเป็นการสรุปผล transaction ต่างๆจับกลุ่มตาม ID ด้วยฟังชั่น group_by() รวมถึงการ join tables ต่างๆด้วย left_join() อ่าน document การใช้งาน dplyr ได้ที่ลิ้งนี้เลย
STEPS ที่ใช้ตอนแข่ง Techjam
เอาจริง โจทย์รอบ audition ไม่ได้ยากเลย ด้วยความที่มันเป็น binary classification ทั่วๆไป ตัวเลือก algorithms ที่หยิบมาใช้ได้มีเยอะมาก ไม่ว่าจะเป็น logistic regression, decision tree, random forest, XGboost, หรือ neural network เป็นต้น
- Clean data + Basic exploratory data analysis (20%)
- Feature engineer + Feature selection (50%)
- Train model (20%)
- Test model (5%)
- Export result + Write read me file (5%)
ขั้นตอนที่ 1–2 ที่ทำความสะอาดข้อมูลและทำ feature engineer (สร้างตัวแปรใหม่) ที่จะเอาไปใช้ predict outcome ใช้เวลาเยอะมาก ประมาณ 70% ของโจทย์ข้อนั้นๆเลย พอเราได้ features ที่โอเครแล้ว ที่เหลือแค่ train test tuning เพื่อให้ได้ accuracy สูงๆ ใช้ repeated cross validation เพื่อลดปัญหา overfit และ tune ค่า parameters ต่างๆด้วย grid search หรือ random search ขึ้นอยู่กับว่าใช้ algorithms อะไรตอนเทรน อย่าง random forest ต้องใช้ grid search จะดีกว่าในการจูนค่า mtry
แก้ปัญหายากๆด้วย Randomness
หลายๆปัญหาในชีวิตแก้ได้ด้วยการสุ่ม เช่น ถ้าเราอยากจะรู้ว่าคนไทยทั่วไปชอบกินข้าวมันไก่กี่ % การสุ่มตัวอย่าง (sampling) ก็พอจะช่วยเราหาคำตอบคร่าวๆได้เหมือนกัน (estimate) ถ้าหากการสุ่มเป็นไปอย่าง random และ n ใหญ่พอ
Random Forest ก็เป็นหนึ่งใน algorithms ที่ใช้หลักการสุ่ม (random sampling) มาใช้แก้ปัญหาเหมือนกัน และน่าทึ่งที่ performance ของมันจัดได้ว่าติดอันดับต้นๆของ machine learning algorithms ที่มีอยู่ในโลกตอนนี้เลย
Random Forest คือหนึ่งใน black-box algorithms ของโลก machine learning ทุกวันนี้เลย
แต่ accuracy ที่สูงต้องแลกมากับความสามารถในการอธิบายผลที่ไม่สามารถอธิบายได้เลย (not interpretable) มันใช้หลักการสุ่มแบบแรนดอมเพื่อเลือก features ขึ้นมา split tree และสร้าง tree ต้นใหม่ไปเรื่อยๆเป็นร้อยเป็นพันต้น แล้วค่อยเฉลี่ยผล prediction ตอนจบ (หรือใช้ majority vote เพื่อหา final prediction ได้เหมือนกัน)
เขียนโค้ดรัน Random Forest ด้วย caret
ถ้าใครยังไม่ได้ install caret ก็ลงก่อนเลยใช้เวลาแป๊ปเดียว พิมพ์คำสั่ง install.packages(c("caret", "ranger")) ใน console แล้วกด enter
ranger เป็น package ใหม่ที่ใช้สำหรับรัน random forest โดยเฉพาะเลย และเป็นตัวที่ผู้สร้าง caret แนะนำให้ใช้คู่กัน (Max Kuhn สอนใน datacamp ให้ใช้แพ็คเกตนี้ เลยจำมาตลอดเลย 555+)
ลองโหลด data(Sonar) มาลองเทรน random forest ด้วย caret ตามโค้ดตัวอย่างด้านล่างได้เลย โดยคำสั่ง trainControl() ใช้สำหรับกำหนดวิธีการที่จะเทรนโมเดลของเรา เนื่องจาก target variable ของ Sonar คือ Class (Mine/Rock) เป็น binary classification เราต้องกำหนด summaryFunction = twoClassSummary และ classProbs = TRUE ใน trainControl() ด้วยเสมอ
# load dataset
library(mlbench)
data(Sonar)# load caret
library(caret)# define parameters used in training data
my_control <- trainControl(method = "repeatedcv",
number = 5,
repeats = 5,
verboseIter = TRUE,
summaryFunction = twoClassSummary,
classProbs = TRUE)# train random forest
set.seed(10)
rf_model <- train(Class ~ .,
data = Sonar,
method = "ranger",
trControl = my_control)
เสร็จแล้วกด run (ctrl + enter) ได้เลย แล้วพิมพ์ rf_model ลงไปใน console จะได้ผลหน้าตาตามรูปด้านล่าง เราทำ repeated cross validation 5 fold 5 times จูนหาค่า mtry ด้วย grid search (default option ใน caret) และเลือกใช้ mtry = 2 เพราะโมเดลได้ค่า ROC สูงที่สุดที่ 0.9274880

ถ้าอยากจะเอาโมเดล rf_model ที่เราเทรนตะกี้ไปใช้ predict dataset ใหม่ ก็แค่พิมพ์คำสั่ง predict(rf_model, newdata) ใน console ได้เลย แล้วคำนวณ accuracy, precision, recall ได้จากตาราง confusion matrix :D
ข้อดีของการใช้ caret คือถ้าวันนี้เราอยากเทรน algorithms อื่นๆที่ไม่ใช่ ranger ก็สามารถปรับโค้ดนิดเดียว เช่น เปลี่ยนจาก ranger เป็น glm (logistic regression) แค่เปลี่ยนตรง argument method ได้เลย นอกนั้นเหมือนเดิม !!
logit_model <- train(Class ~ .,
data = Sonar,
method = “glm”,
trControl = my_control)Techjam: Accuracy ไม่ใช่ทุกอย่างจริงๆ

สำหรับ performance ของโมเดล เราว่าเราก็ทำได้ดีระดับนึงแล้วนะ 555+ accuracy ของโจทย์ข้อ 1/3/4 ก็ออกมาโอเคอยู่ (Techjam บอกว่าจะคิดคะแนน final scores จาก 3/5 ข้อที่เราได้คะแนนสูงสุด) แต่ก็ยังไม่ดีพอจะเข้ารอบ Techjam ได้ #เส้าแป๊ป ._. เดาว่าโมเดลเราอาจจะ overfit เกินไปมั้ง? overfit กับ test data first 50%?
ข้อเสนอแนะสำหรับทีมงาน Techjam ถ้าจะจัดอีกครั้งปีหน้า สำหรับสาย data ควรจะมี leaderboard เหมือนของ Kaggle จะดีมากเลย แล้วเจอกันใหม่ปีหน้านะฮ๊าฟ
ปล. ตอนแข่งเราใช้ logistic regression, XGboost, random forest, SVM กับอีกหลายๆโมเดล ลองทำ stacking ensemble เหมือนกันแต่ models มัน correlated กันสูงไปเลยไม่ได้ improvement ดีเท่าที่ควร เย้ย
