Gradient Boosting و XGBoost
الموديل اللي بيكسب أغلب مسابقات Kaggle على الجداول.
الفكرة: كل شجرة بتصلح غلط اللي قبلها
في الـ Random Forest الشجر بتشتغل بالتوازي وكل واحدة لوحدها. في الـ Boosting الشجر بتشتغل ورا بعض: أول شجرة صغيرة تتوقع، والتانية تتعلم من غلطات الأولى بس، والتالتة من غلطات التانية، وهكذا. زي طالب بيحل امتحان، وكل مرة يذاكر بس الأسئلة اللي غلط فيها.
و«Gradient» في الاسم لأن كل شجرة جديدة بتمشي في اتجاه الـ gradient عشان تقلل الـ loss. نفس الفكرة اللي اتعلمناها في المرحلة ٣.
pip install xgboost
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.
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 بيكسب غالباً، بس متفترضش ده، قيس.