01Overall Concept
ไอเดียหลัก — Regression Tree ใช้คำถามแบบใช่หรือไม่แบ่งตัวอย่างเป็นกลุ่มย่อย แล้วตอบด้วยค่าเฉลี่ยของเป้าหมายในกลุ่มนั้น เช่น บ้านพื้นที่น้อยกับบ้านพื้นที่มากอาจมีราคาเฉลี่ยต่างกัน วิธีนี้จับความสัมพันธ์ที่ไม่เป็นเส้นตรงโดยไม่ต้องกำหนดสมการโค้งล่วงหน้า
ลองนึกภาพว่า — เหมือนคู่มือประเมินราคาที่ถามว่าบ้านใหญ่กว่า 80 ตารางเมตรไหม อยู่ใกล้รถไฟฟ้าไหม เมื่อเดินตามคำถามไปถึงหน้าสุดท้าย จะพบราคาเฉลี่ยของบ้านกลุ่มนั้น
ตัวอย่างการนำไปใช้ — ประมาณราคาบ้าน ยอดขายรายสาขา เวลาส่งของ หรือใช้เป็นต้นไม้ฐานของ Random Forest และ Gradient Boosting สำหรับงาน regression
02อธิบายภาษาคนเข้าใจง่ายๆ
Decision Tree ที่ทายคลาสจะจบด้วยคำตอบอย่างแมวหรือหมา แต่ Regression Tree จบด้วยตัวเลข เช่น ราคาบ้าน 3.2 ล้านบาท โครงสร้างคำถามยังเหมือนเดิม
สมมติมีบ้านเล็กที่ราคา 2 และ 4 ล้านบาท กับบ้านใหญ่ที่ราคา 8 และ 10 ล้านบาท ถ้ารวมทั้งหมดจะทาย 6 แต่เมื่อแบ่งตามขนาด กลุ่มบ้านเล็กทาย 3 และบ้านใหญ่ทาย 9 ซึ่งใกล้ราคาจริงมากขึ้น
คอมพิวเตอร์ลองจุดแบ่งหลายตำแหน่ง แล้วเลือกตำแหน่งที่ทำให้ราคาภายในแต่ละกลุ่มใกล้กันที่สุด จากนั้นถามต่อได้อีกจนถึงความลึกหรือจำนวนตัวอย่างที่กำหนด
บ้านใหม่จะเดินตามคำถามทีละข้อจนถึงใบ แล้วรับค่าเฉลี่ยในใบนั้นเป็นราคา บ้านสองหลังในใบเดียวกันจึงได้คำตอบเท่ากัน แม้ขนาดจะต่างกันเล็กน้อย
เมื่อวาดกราฟด้วย feature เดียว เราจะเห็นเส้นเป็นขั้นบันได ไม่ใช่เส้นโค้งเรียบ ต้นไม้ลึกทำให้ขั้นถี่ขึ้น แต่อาจกำลังจำความบังเอิญของข้อมูลเก่า
ภาพจำ: แบ่งตารางออกเป็นช่องเล็ก ๆ แล้วเขียนค่าเฉลี่ยไว้ในแต่ละช่อง
03How it works
ค่อยๆ ทำไปด้วยกัน ตั้งแต่ข้อมูลแถวแรกจนถึงการตรวจคำตอบ
เตรียมตัวเลขคำตอบ
ให้ X เป็น feature เช่น พื้นที่บ้าน และ y เป็นราคาต่อหลัง แบ่ง train/test ก่อนฝึก ต้นไม้ไม่ต้องปรับสเกลเพื่อเลือก threshold แต่ข้อมูลหมวดหมู่ยังต้องแปลงให้ estimator ใช้ได้
ลองแบ่งแล้ววัดความกระจาย
สำหรับทุกจุดตัดที่เป็นไปได้ แยกแถวซ้ายกับขวา คำนวณค่าเฉลี่ย y ของแต่ละฝั่ง แล้วรวม (y − ค่าเฉลี่ยของฝั่งนั้น)² เลือกจุดตัดที่ทำให้ผลรวมนี้ต่ำที่สุด
เห็นตัวเลขจากตัวอย่างเล็ก
y=[2,4,8,10] มีค่าเฉลี่ย 6 และ SSE=40 ถ้าแบ่งเป็น [2,4] กับ [8,10] ค่าเฉลี่ยกลายเป็น 3 กับ 9 และ SSE รวมเหลือ 4 การแบ่งนี้ลด error ลง 36
ฝึกต้นไม้ด้วยเงื่อนไขหยุด
ใช้ DecisionTreeRegressor(max_depth=3, min_samples_leaf=2, random_state=42) แล้ว fit(X_train, y_train) การทำนายเดินตาม threshold จนถึงใบและคืนค่าเฉลี่ย ไม่ได้ต่อเส้นระหว่างใบ
เลือกความละเอียดที่ใช้กับข้อมูลใหม่ได้
ดู RMSE บน validation แล้วปรับ max_depth หรือ min_samples_leaf ใน Playground ค่า Test RMSE ใช้จุดที่กันไว้และไม่ได้ร่วมเลือกจุดแบ่ง ลองเทียบต้นไม้ตื้นกับลึก และระวังการทำนาย x ที่อยู่นอกช่วงฝึกซึ่งจะได้ค่าจากใบริมสุด
ข้อมูล พารามิเตอร์ และภาพรวมการคำนวณ
max_depthmin_samples_leafcriterionข้อมูลที่รับเข้ามา
X เป็นตาราง feature และ y เป็นค่าต่อเนื่อง ใช้ squared_error เป็นเกณฑ์แบ่ง
y=[2,4,8,10] → ค่าเฉลี่ย 6 · SSE=40พารามิเตอร์ที่ใช้
- max_depth
- จำกัดจำนวนชั้นของคำถาม
- min_samples_leaf
- จำนวนแถวอย่างน้อยในแต่ละใบ
- criterion
- ตัวอย่างนี้ใช้ squared_error และค่าเฉลี่ยในใบ
ผลลัพธ์ที่ได้
โครงสร้างต้นไม้และค่าตัวเลขจากใบที่ข้อมูลใหม่ตกอยู่
[2,4] → 3 · [8,10] → 9 · SSE รวม=4คำนวณทีละขั้น
- 01
ลอง threshold ของ feature เพื่อแยกซ้าย/ขวา
- 02
เลือก split ที่ลด Σ(y−ค่าเฉลี่ยใบ)² มากที่สุด
- 03
ทำซ้ำแล้วเก็บค่าเฉลี่ยไว้ในใบสุดท้าย
ควรรู้อีกนิด — การลด error ในชุดฝึกไม่รับประกันว่า test error จะลดด้วย ถ้าต้องการเส้นต่อเนื่องหรือการ extrapolate ควรเปรียบเทียบกับโมเดลอื่นและตรวจช่วงข้อมูลที่ใช้งาน
04Make it yours
# ติดตั้ง: pip install numpy scikit-learn# ดาวน์โหลด sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์import numpy as np data = np.genfromtxt("regression-tree-sample.csv", delimiter=",", skip_header=1)X = data[:, :2] from sklearn.tree import DecisionTreeRegressorfrom sklearn.metrics import mean_squared_error X = data[:, :1]y = data[:, 1]# กันทุกแถวที่ 5 ไว้ทดสอบ ตามข้อมูลสาธิตใน Playground# งานจริงควรเลือก split ให้เหมาะกับเวลา/บุคคล/กลุ่มของข้อมูลis_test = np.arange(len(X)) % 5 == 0X_train, X_test = X[~is_test], X[is_test]y_train, y_test = y[~is_test], y[is_test]model = DecisionTreeRegressor(max_depth=3, min_samples_leaf=2, random_state=42)model.fit(X_train, y_train)pred = model.predict(X_test)print("Test RMSE:", mean_squared_error(y_test, pred) ** 0.5) โค้ดเปลี่ยนตามค่าที่เลือกใน Playground · แต่ละภาษาใช้ข้อมูลตัวอย่างตามที่ระบุในโค้ด
05Learn by playing
ปรับ ความลึกสูงสุด แล้วสังเกตรูปแบบคำทำนายและตัวชี้วัดที่คำนวณใหม่ทันที
Playground เป็น implementation เพื่อการเรียนรู้ที่คำนวณในเบราว์เซอร์ ส่วนโค้ด Python ใช้ scikit-learn จึงอาจให้ค่าต่างกันเล็กน้อยจากรายละเอียดการ optimize และค่าเริ่มต้นของไลบรารี ผลนี้ไม่ใช่ benchmark บนข้อมูลจริง