LightGBM with scikit-learn
This example uses the bundled diabetes regression dataset and LightGBM's current callback API. Training, early-stopping validation, and final test observations are disjoint.
1. Fit with a validation callback
import lightgbm as lgb
from sklearn.datasets import load_diabetes
from sklearn.metrics import mean_absolute_error, r2_score, root_mean_squared_error
from sklearn.model_selection import train_test_split
X, y = load_diabetes(return_X_y=True)
X_development, X_test, y_development, y_test = train_test_split(
X,
y,
test_size=0.20,
random_state=42,
)
X_train, X_valid, y_train, y_valid = train_test_split(
X_development,
y_development,
test_size=0.20,
random_state=42,
)
model = lgb.LGBMRegressor(
objective="regression",
n_estimators=500,
learning_rate=0.03,
num_leaves=15,
min_child_samples=15,
subsample=0.9,
colsample_bytree=0.9,
reg_lambda=1.0,
random_state=42,
n_jobs=1,
verbosity=-1,
)
model.fit(
X_train,
y_train,
eval_X=X_valid,
eval_y=y_valid,
eval_metric="l2",
callbacks=[
lgb.early_stopping(stopping_rounds=20, verbose=False),
lgb.log_evaluation(period=0),
],
)
prediction = model.predict(X_test)
print("Best iteration:", model.best_iteration_)
print("Test MAE:", round(mean_absolute_error(y_test, prediction), 2))
print("Test RMSE:", round(root_mean_squared_error(y_test, prediction), 2))
print("Test R-squared:", round(r2_score(y_test, prediction), 3))
assert X_train.shape[0] + X_valid.shape[0] + X_test.shape[0] == X.shape[0]
assert prediction.shape == y_test.shape
assert 0 < model.best_iteration_ <= model.n_estimators
2. Why no scaler appears
Axis-aligned tree splits do not need standardized inputs. Scaling would not make this LightGBM model more valid and would add another learned artifact. If a combined pipeline contains a scale-sensitive component, fit that transformation only within its training fold.
3. Tuning and early stopping
The callback watches the validation set and chooses best_iteration_; therefore the validation set is part of model selection. Do not replace it with the test set. Fixed eval_X and eval_y passed through GridSearchCV.fit do not create fold-specific stopping data. During cross-validated tuning, either search a fixed n_estimators or explicitly create stopping data inside each training fold.
4. Evaluation and serving
MAE, RMSE, and emphasize different error properties; retain a domain-relevant metric and inspect residuals and subgroups. Persist feature order and types, category metadata where applicable, missing-value policy, best_iteration_, and the exact LightGBM build.