RuleFit

Basic

RuleFit | กฎ + โมเดลเชิงเส้นกับ L1

まとめ
  • RuleFit สกัดกฎ if-then จากต้นไม้ แล้วรวมกับฟีเจอร์เชิงตัวเลขเดิมและฝึกด้วยโมเดลเชิงเส้นแบบ L1
  • กฎจับปฏิสัมพันธ์และ threshold ส่วนเทอมเชิงเส้นเก็บแนวโน้มภาพรวม ทำให้ทั้งแม่นและตีความได้
  • ปรับ max_rules, ความลึก/จำนวนต้นไม้ และพารามิเตอร์ boosting ตามความเหมาะสม พร้อมใช้ cross-validation
  • แสดงกฎที่สำคัญและแปลงเป็นภาษาธุรกิจก่อนสื่อสารกับผู้ใช้งาน

1. แนวคิด (พร้อมสมการ) #

  1. สกัดกฎ: เส้นทางจากรากถึงใบไม้กลายเป็นฟีเจอร์ไบนารี (r_j(x) \in {0,1})
  2. เพิ่มเทอมเชิงเส้น (z_k(x)) สำหรับฟีเจอร์ต่อเนื่อง
  3. ฝึกโมเดลเชิงเส้นแบบ L1:

$$ \hat{y}(x) = \beta_0 + \sum_j \beta_j r_j(x) + \sum_k \gamma_k z_k(x) $$

L1 ทำให้โมเดลเบาบาง เหลือเฉพาะกฎ/เทอมที่สำคัญจริง

2. ชุดข้อมูล (OpenML: house_sales) #

ตัวอย่างราคาบ้านใน King County (OpenML data_id=42092) เลือกเฉพาะคอลัมน์เชิงตัวเลขเพื่อความชัดเจน

import japanize_matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

dataset = fetch_openml(data_id=42092, as_frame=True)
X = dataset.data.select_dtypes("number").copy()
y = dataset.target.astype(float)

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

3. ฝึก RuleFit #

Python implementation: christophM/rulefit

from rulefit import RuleFit
import warnings
warnings.simplefilter("ignore")

rf = RuleFit(max_rules=200, tree_random_state=27)
rf.fit(X_train.values, y_train.values, feature_names=list(X_train.columns))

pred_tr = rf.predict(X_train.values)
pred_te = rf.predict(X_test.values)

def report(y_true, y_pred, name):
    rmse = mean_squared_error(y_true, y_pred, squared=False)
    mae  = mean_absolute_error(y_true, y_pred)
    r2   = r2_score(y_true, y_pred)
    print(f"{name:8s}  RMSE={rmse:,.0f}  MAE={mae:,.0f}  R2={r2:.3f}")

report(y_train, pred_tr, "Train")
report(y_test,  pred_te, "Test")

4. ดูกฎที่สำคัญ #

rules = rf.get_rules()
rules = rules[rules.coef != 0].sort_values(by="importance", ascending=False)
rules.head(10)
  • rule: เงื่อนไข if-then (type=linear หมายถึงเทอมเชิงเส้น)
  • coef: ค่าสัมประสิทธิ์ (หน่วยเดียวกับเป้าหมาย)
  • support: สัดส่วนตัวอย่างที่เข้าเงื่อนไข
  • importance: คะแนนที่รวมขนาดค่าสัมประสิทธิ์และสัดส่วนตัวอย่าง

5. ตรวจสอบด้วยการแสดงผล #

plt.figure(figsize=(6, 5))
plt.scatter(X_train["sqft_above"], y_train, s=10, alpha=0.5)
plt.xlabel("sqft_above")
plt.ylabel("price")
plt.title("Relationship between sqft_above and price")
plt.grid(alpha=0.3)
plt.show()
rule_mask = X["sqft_living"].le(3935.0) & X["lat"].le(47.5315)

applicable_data = np.log(y[rule_mask])
not_applicable  = np.log(y[~rule_mask])

plt.figure(figsize=(8, 5))
plt.boxplot([applicable_data, not_applicable],
            labels=["Rule satisfied", "Rule not satisfied"])
plt.ylabel("log(price)")
plt.title("Price distribution by rule satisfaction")
plt.grid(alpha=0.3)
plt.show()

6. ข้อแนะนำเชิงปฏิบัติ #

  • จัดการ outlier (winsorization, clipping) เพื่อให้กฎเสถียร
  • รวมหมวดหมู่ที่หายากก่อนเข้ารหัส
  • หากเป้าหมายมีการกระจายเอียง ให้แปลงเช่น log(y) หรือ Box-Cox
  • เลือกจำนวนกฎและความลึกให้คนอ่านเข้าใจ และใช้ cross-validation ช่วยกำหนดเพดาน
  • สรุปกฎเด่นด้วยภาษาธุรกิจเพื่อสื่อสารกับผู้เกี่ยวข้อง

7. อ้างอิง #

  • Friedman, J. H., & Popescu, B. E. (2008). Predictive Learning via Rule Ensembles. The Annals of Applied Statistics, 2(3), 916–954.
  • Christoph Molnar. (2020). Interpretable Machine Learning. https://christophm.github.io/interpretable-ml-book/rulefit.html