import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from sklearn.ensemble import GradientBoostingRegressor
พื้นฐาน Gradient Boosting #
Gradient Boosting ทั่วไปกว่า AdaBoost โดยใช้ “กราดิเอนต์ของฟังก์ชันสูญเสีย” เป็นตัวชี้นำในการเพิ่ม weak learner ทีละตัว เลือก loss ได้อิสระจึงนำไปใช้กับงาน regression, classification, quantile prediction ได้
1. สัญชาติญาณ: เติม residual ไปทีละน้อย #
- เริ่มจากโมเดลง่าย ๆ เช่น ค่าเฉลี่ย
- คำนวณ residual (ค่าที่เหลือ) ระหว่างคำตอบจริงกับโมเดลปัจจุบัน
- ฝึก weak learner ตัวใหม่ให้เรียน residual แล้วบวกกลับไปด้วย learning rate
- ทำซ้ำ ⇒ เหมือนเติมส่วนที่ขาดทีละนิดจนฟิตกับข้อมูล
AdaBoost เน้นเพิ่มน้ำหนักตัวอย่างที่ผิด ส่วน Gradient Boosting ใช้ “กราดิเอนต์ของ loss” เป็นตัวแก้ไข
2. สูตรแบบทั่วไป (กรณี regression) #
ให้ (L = \sum_i \ell(y_i, F(x_i)))
- โมเดลเริ่มต้น
(F_0(x) = \arg\min_c \sum_i \ell(y_i, c)) (เช่น ค่าเฉลี่ยเมื่อเป็น squared error) - รอบที่ (m):
- คำนวณ pseudo residual
(r_{im} = - \left[\frac{\partial \ell(y_i, F(x_i))}{\partial F(x_i)}\right]{F=F{m-1}}) - ฝึก weak learner (h_m(x)) ด้วย (r_{im})
- หา step size
(\rho_m = \arg\min_\rho \sum_i \ell(y_i, F_{m-1}(x_i) + \rho,h_m(x_i))) - อัปเดต
(F_m(x) = F_{m-1}(x) + \nu,\rho_m, h_m(x)) ( (\nu) = learning rate )
- คำนวณ pseudo residual
3. ตัวอย่าง: ฟิตเส้นโค้งที่ไม่เชิงเส้น #
X = np.linspace(-10, 10, 500)[:, np.newaxis]
noise = np.random.rand(X.shape[0]) * 10
y = (
(np.sin(X).ravel() + np.cos(4 * X).ravel()) * 10
+ 10
+ np.linspace(-10, 10, 500)
+ noise
)
reg = GradientBoostingRegressor(
n_estimators=50,
learning_rate=0.5,
max_depth=3,
random_state=42,
)
reg.fit(X, y)
y_pred = reg.predict(X)
plt.figure(figsize=(10, 5))
plt.scatter(X, y, c="k", marker="x", alpha=0.5, label="train data")
plt.plot(X, y_pred, c="r", label="prediction", linewidth=1.2)
plt.legend(); plt.show()
4. เปรียบเทียบ loss #
GradientBoostingRegressor รองรับหลาย loss
squared_error: ไวต่อ outlierabsolute_error: ทนต่อ outlier มากกว่าhuber: ผสมระหว่างสองแบบquantile: ใช้พยากรณ์ช่วง (prediction interval)
โค้ดเดิมมีตัวอย่างการเปรียบเทียบ loss รวมถึงรูปผลลัพธ์
5. เคล็ดลับใช้งาน #
learning_rate × n_estimatorsมีความสัมพันธ์กัน: ลด learning_rate แล้วเพิ่มจำนวนรอบเพื่อความนิ่งmax_depthของต้นไม้ย่อย (หรือmax_leaf_nodes) มีผลอย่างมาก ค่า default 3 มักให้ผลดี- ใช้
early_stoppingหรือ validation set เพื่อหยุดเมื่อสกอร์ไม่ดีขึ้น - เลือก loss ให้ตรงกับข้อมูล: มี outlier เยอะให้ลอง
huberหรือabsolute_error - ข้อมูลจำนวนมากสามารถลอง
HistGradientBoostingRegressor, XGBoost, LightGBM เพื่อประสิทธิภาพสูงกว่า
สรุป #
- Gradient Boosting คิดแบบ “เติม residual” โดยใช้กราดิเอนต์ของ loss
- เลือก loss ได้อิสระ ทำให้ใช้ในงานหลากหลาย
- ปรับ learning_rate, n_estimators, depth อย่างระมัดระวัง และใช้ early stopping
- โค้ดใน sklearn ทำให้เริ่มต้นได้เร็ว ก่อนต่อยอดไปยัง XGBoost/LightGBM/CatBoost