Core hyperparameters

XGBoost · Essentials · 12 min

Most of XGBoost's performance comes from a few parameters; knowing what each does makes tuning fast.

A small set of parameters matters most.

Learning rate and number of trees. learning_rate (eta, default 0.3) scales each tree's contribution. Smaller values need more trees (n_estimators) but usually generalise better. Typical final settings are 0.01-0.1 with hundreds to thousands of trees, chosen by early stopping.

Tree complexity.

  • max_depth (default 6): deeper trees capture more interactions but overfit faster; 3-8 is the usual range.
  • min_child_weight (default 1): the minimum sum of instance weights (hessian) in a leaf; larger values make the model more conservative.
  • gamma (min_split_loss, default 0): the minimum loss reduction needed to make a split.
  • max_leaves with grow_policy="lossguide" grows trees leaf-wise, LightGBM style.

Randomness (stochastic boosting). subsample (rows per tree) and colsample_bytree (features per tree) around 0.6-0.9 reduce overfitting and speed up training. Set random_state for reproducibility.

Regularisation. reg_lambda (L2 on leaf weights, default 1) and reg_alpha (L1, default 0) shrink leaf values.

A practical order: fix a moderate learning rate (0.05-0.1) with early stopping, tune max_depth and min_child_weight, then the sampling parameters, then regularisation, and finally lower the learning rate for the final model.

Example

from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score
from xgboost import XGBClassifier

X, y = make_classification(n_samples=1000, n_features=30, n_informative=8,
                           flip_y=0.1, random_state=0)

for params in [dict(max_depth=10, learning_rate=0.3),            # very flexible
               dict(max_depth=3, learning_rate=0.1),
               dict(max_depth=3, learning_rate=0.1, subsample=0.8,
                    colsample_bytree=0.8, min_child_weight=5)]:
    model = XGBClassifier(n_estimators=300, random_state=0, **params)
    print(round(cross_val_score(model, X, y, cv=5, scoring="roc_auc").mean(), 3), params)
# 0.932 {'max_depth': 10, 'learning_rate': 0.3}
# 0.929 {'max_depth': 3, 'learning_rate': 0.1}
# 0.925 {'max_depth': 3, 'learning_rate': 0.1, 'subsample': 0.8, ...}
# Close here: which setting wins is data-dependent, so measure with CV

Remember

  • learning_rate and n_estimators trade off: lower rate, more trees
  • max_depth, min_child_weight, gamma control tree complexity
  • subsample and colsample_bytree add randomness that reduces overfitting

Watch out for

  • Tuning n_estimators by grid search instead of using early stopping.

Check yourself

  1. Your model overfits badly. Which change makes XGBoost more conservative?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: xgboost.readthedocs.io/en/stable/parameter.html#parameters-for-tree-booster