الدرس 6 من 9

Gradient Boosting و XGBoost

الموديل اللي بيكسب أغلب مسابقات Kaggle على الجداول.

الفكرة: كل شجرة بتصلح غلط اللي قبلها

في الـ Random Forest الشجر بتشتغل بالتوازي وكل واحدة لوحدها. في الـ Boosting الشجر بتشتغل ورا بعض: أول شجرة صغيرة تتوقع، والتانية تتعلم من غلطات الأولى بس، والتالتة من غلطات التانية، وهكذا. زي طالب بيحل امتحان، وكل مرة يذاكر بس الأسئلة اللي غلط فيها.

و«Gradient» في الاسم لأن كل شجرة جديدة بتمشي في اتجاه الـ gradient عشان تقلل الـ loss. نفس الفكرة اللي اتعلمناها في المرحلة ٣.

terminal
pip install xgboost
xgb.py
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
from xgboost import XGBClassifier

df = pd.read_csv("churn.csv")
df["yearly"] = (df["contract"] == "yearly").astype(int)
features = ["tenure", "bill", "complaints", "data_gb", "yearly"]
X_train, X_test, y_train, y_test = train_test_split(
    df[features], df["churned"], test_size=0.2,
    random_state=42, stratify=df["churned"])

model = XGBClassifier(
    n_estimators=300,       # number of trees
    learning_rate=0.05,     # how much each tree corrects (step size!)
    max_depth=3,            # small trees
    random_state=42,
)
model.fit(X_train, y_train)
print("F1 (churned):", round(f1_score(y_test, model.predict(X_test)), 3))

مقارنة عادلة بين الموديلات

كل موديلات scikit-learn (و XGBoost) ليها نفس الشكل: fit و predict. فتقدر تقارنهم في loop واحد. وهنستخدم ROC-AUC: رقم بيقيس الموديل بيرتب العملاء صح قد إيه من الأعلى احتمالاً للأقل، من غير ما يتأثر بالـ threshold.

compare.py
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score
from xgboost import XGBClassifier

df = pd.read_csv("churn.csv")
df["yearly"] = (df["contract"] == "yearly").astype(int)
features = ["tenure", "bill", "complaints", "data_gb", "yearly"]
X_train, X_test, y_train, y_test = train_test_split(
    df[features], df["churned"], test_size=0.2,
    random_state=42, stratify=df["churned"])

models = {
    "Logistic Regression": LogisticRegression(max_iter=1000),
    "Decision Tree": DecisionTreeClassifier(max_depth=4, random_state=42),
    "Random Forest": RandomForestClassifier(300, min_samples_leaf=5, random_state=42),
    "XGBoost": XGBClassifier(n_estimators=300, learning_rate=0.05,
                             max_depth=3, random_state=42),
}
for name, m in models.items():
    m.fit(X_train, y_train)
    auc = roc_auc_score(y_test, m.predict_proba(X_test)[:, 1])
    print(f"{name:20} AUC = {auc:.3f}")

مفاجأة؟ أبسط موديل كسب! ده لأن العلاقات في الداتا دي أغلبها بسيطة ومستقيمة، فالـ Logistic Regression كفاية جداً، والموديلات المعقدة مش لاقية حاجة زيادة تتعلمها. وده بالظبط سبب إنك دايماً تبدأ بـ baseline بسيط. في داتا حقيقية فيها علاقات معقدة (زي أغلب مسابقات Kaggle) XGBoost بيكسب غالباً، بس متفترضش ده، قيس.

💡 إمتى تستخدم إيه؟داتا جدولية (صفوف وأعمدة زي Excel)؟ ابدأ بـ Logistic Regression كـ baseline، وبعدين جرب Random Forest و XGBoost. صور أو نصوص أو صوت؟ ده ملعب الـ Deep Learning في المرحلة الجاية.
الدرس اللي فات