pip install lightgbm★Prebuilt CPU wheels for all major platforms.conda install -c conda-forge lightgbmConda-forge build (Kalyan's usual conda flow works too).pip install lightgbm --config-settings=cmake.define.USE_GPU=ONBuild from source with OpenCL GPU support.import lightgbm as lgb★Core module — Dataset, train, cv, callbacks, plotting.from lightgbm import LGBMClassifier, LGBMRegressor, LGBMRanker★scikit-learn-compatible estimators.
lgb.Dataset(X, label=y)★Wraps data; discretizes each feature into ≤max_binbins.lgb.Dataset(X_val, y_val, reference=train_set)★Validation set must reuse training bin boundaries.lgb.Dataset(…, weight=w, init_score=s)Per-row weights and starting margins (boost from a prior model).lgb.Dataset(…, group=[10,20,40])Query-group sizes for ranking; sum(group) = n_samples.lgb.Dataset(…, params={'max_bin': 127})Binning params are Dataset-time, fixed at construction.lgb.Dataset(…, free_raw_data=False)Keep raw arrays if you'll rebuild/re-slice the Dataset later.train_set.save_binary('train.bin')Cache binned data — fastest way to reload for repeated runs.
bst = lgb.train(params, train_set, num_boost_round=100)★Core loop; returns a Booster.paramsdict wins over arguments.lgb.train(…, valid_sets=[train_set, val_set], valid_names=['train','valid'])★Track metrics per round; include train set to see the gap.lgb.train(…, callbacks=[…])★Early stopping / logging attach here (see card 15).lgb.train(…, init_model=bst_or_path)Continue training from an existing model.bst.best_iteration · bst.best_scoreSet when early stopping triggers.
LGBMRegressor(**p).fit(X, y)★Default objective'regression', metricl2.LGBMClassifier(**p).fit(X, y)★Auto-detects binary vs multiclass from y.model.fit(X, y, eval_set=[(X_val,y_val)], callbacks=[…])★Validation tracking + early stopping, sklearn style.LGBMRanker().fit(X, y, group=g, eval_group=[g_val])Ranking needs group sizes for train and each eval set.GridSearchCV(LGBMClassifier(), param_grid)Drop-in with sklearn model selection & Pipelines.model.booster_ · .best_iteration_ · .evals_result_Escape hatches to the underlying Booster and history.
bst.predict(X)★Probabilities (binary/multiclass) or values (regression).bst.predict(X, num_iteration=bst.best_iteration)★Use only trees up to the early-stopped best round.bst.predict(X, raw_score=True)Raw margin before sigmoid/softmax.bst.predict(X, pred_leaf=True)Leaf index per tree — feature-engineering / embedding trick.bst.predict(X, pred_contrib=True)SHAP values: n_features + 1 columns (last = expected value).model.predict_proba(X)★sklearn classifier: probabilities;.predict()gives labels.
num_leaves31★Max leaves per tree — the main complexity knob.max_depth-1★Depth cap (-1= none). Growth stays leaf-wise regardless.learning_rate0.1★η in the boosting update (aliaseta).num_iterations100★n_estimators(sklearn) =num_boost_round(native).boosting_type'gbdt'gbdt·dart·rf; GOSS is nowdata_sample_strategy='goss'.objective/metricTask loss and logged metric(s) — cards 12–14.
min_data_in_leaf20★The anti-overfit knob; hundreds+ for large data (aliasmin_child_samples).min_sum_hessian_in_leaf1e-3Keeps eq. 2's denominator healthy (aliasmin_child_weight).lambda_l1 / lambda_l20.0L1 zeroes small leaf outputs; L2 is λ in eqs. 2–3 (aliasesreg_alpha/reg_lambda).min_gain_to_split0.0Reject splits below this gain (aliasmin_split_gain).max_bin255Fewer bins = coarser splits = regularization + speed. Dataset-time!max_delta_step0.0Cap leaf output magnitude — stabilizes imbalanced Poisson/logistic.path_smooth0.0Shrink leaf values toward parent — helps small leaves.
feature_fraction1.0★Features sampled per tree (aliascolsample_bytree).bagging_fraction=0.8, bagging_freq=1★Row bagging every k rounds — inactive until freq > 0 (aliassubsample).feature_fraction_bynode1.0Re-sample features at every split (deeper randomness).extra_trees=TrueOne random threshold per feature — extremely-randomized variant.data_sample_strategy='goss'GOSS replaces bagging; tunetop_rate(0.2) /other_rate(0.1).neg_bagging_fraction1.0Under-sample only negatives — cheap imbalance trick (binary).
drop_rate0.1Fraction of previous trees dropped each round.max_drop50Cap on dropped trees per iteration (<=0 = no cap).skip_drop0.5Probability of skipping dropout for a round entirely.uniform_drop=TrueDrop uniformly instead of weight-proportional.lgb.early_stopping(…) + dartno effectEarly stopping is disabled under DART — budget rounds manually.
categorical_feature=['c1','c2']★By name or index; Fisher-optimal splits, ~8× faster than one-hot.df['col'].astype('category')★pandas category dtype is auto-detected; codes must be non-negative ints.max_cat_to_onehot4≤ this many categories → one-vs-rest splits instead.max_cat_threshold32Cap on category split points searched.cat_smooth / cat_l210.0Smoothing + L2 for noisy, low-count categories.min_data_per_group100Min rows per category group considered for splits.
np.nan★The missing-value convention; handled natively at split time (routed to the gain-optimal side).use_missingTrueDisable to treat NaN like any other value.zero_as_missingFalseOpt-in: treat zeros (and unrecorded sparse entries) as missing.is_enable_sparseTrueEnables EFB — bundles mutually-exclusive sparse features.enable_bundleTrueEFB switch alias; O(data×features) → O(data×bundles).
objective='regression'★L2 / MSE (aliasesl2,mse).objective='regression_l1'MAE — robust to outliers; incompatible withlinear_tree.objective='huber', alpha=0.9L2 near zero, L1 in the tails.objective='quantile', alpha=0.5Pinball loss — train one model per quantile for intervals.objective='poisson' / 'gamma' / 'tweedie'Counts / positive skewed / insurance-style;tweedie_variance_power∈ [1,2].objective='mape' / 'fair'Relative-error and Fair-loss variants.
objective='binary'★Log-loss; labels must be {0, 1}.objective='multiclass', num_class=k★Softmax;'multiclassova'= k one-vs-all binaries instead.is_unbalance=TrueAuto re-weight classes — improves recall, distorts probabilities.scale_pos_weight=neg/posManual positive-class weight; use either this or is_unbalance.objective='lambdarank' / 'rank_xendcg'Pairwise / listwise ranking; xendcg is faster, similar accuracy.lambdarank_truncation_level30Optimize NDCG@k truncation for ranking.
metric='rmse' / 'l1' / 'l2' / 'mape' / 'quantile'Regression family.metric='binary_logloss' / 'auc' / 'average_precision'★Binary family — AP is the PR-AUC.metric='multi_logloss' / 'multi_error'Multiclass family.metric='ndcg' / 'map', eval_at=[1,3,5]Ranking metrics at cutoffs.metric=['auc','binary_logloss']All logged; all checked for early stopping unlessfirst_metric_only.metric='None'Disable built-in metrics when using only a custom feval.
lgb.early_stopping(stopping_rounds=50)★Stop when no metric improves for N rounds; setsbest_iteration.lgb.early_stopping(…, first_metric_only=True, min_delta=1e-4)Watch only the first metric; require a minimum improvement.lgb.log_evaluation(period=10)★Print metrics every N rounds.lgb.record_evaluation(history)Capture metric history into a dict →plot_metric.lgb.reset_parameter(learning_rate=lambda i: 0.1*0.99**i)Schedule params per iteration (e.g. LR decay).
lgb.cv(params, train_set, nfold=5)★Dict of per-round metric mean/stdv across folds.lgb.cv(…, stratified=True, shuffle=True)Stratify classification folds (defaults).lgb.cv(…, folds=KFold/TimeSeriesSplit)Bring your own splitter — essential for temporal data.lgb.cv(…, callbacks=[lgb.early_stopping(50)], return_cvbooster=True)Early-stop across folds; retrieve fitted CVBooster.
def obj(y_true, y_pred): return grad, hessFirst and second derivatives w.r.t. the raw score.lgb.train({'objective': obj}, …)/LGBMRegressor(objective=obj)Works in both APIs; predictions come back as raw scores.def feval(preds, eval_data): return 'name', val, is_higher_betterNative custom metric; pass viafeval=in train/cv.eval_metric=lambda y, ŷ: ('name', val, True)sklearn-API custom metric — note the different signature.
monotone_constraints=[1,-1,0]Force prediction ↑ / ↓ / free per feature.monotone_constraints_method='advanced'basicover-constrains;advanced/intermediatelose less accuracy.monotone_penalty0.0Discourage (rather than forbid) early monotone splits.interaction_constraints=[[0,1],[2,3]]Features may only co-occur within their listed group per branch.forcedsplits_filename='splits.json'Force specific top-of-tree splits from a JSON spec.
linear_tree=TrueFit a linear model per leaf instead of a constant — good for trends/extrapolation.linear_lambda0.0Ridge regularization on the per-leaf linear fits.linear_tree + 'regression_l1'unsupportedNot supported with the L1 objective; memory use also rises significantly.linear_tree + monotone_constraintspartialConstraints apply to split choice only, not the leaf linear fits.
device_type='cpu' / 'gpu' / 'cuda'OpenCLgpuvs nativecudabuild; needs a GPU-enabled install.num_threads=NSet to physical core count; hyperthreading often hurts.force_col_wise / force_row_wiseautoPin the histogram build strategy to skip the auto-test overhead.use_quantized_grad=Truev4.0+Low-bit gradient quantization — faster, minor accuracy cost.histogram_pool_size-1Cap histogram cache memory (MB).max_bin=63 + save_binaryOfficial speed recipe: fewer bins + cached binary data.
from lightgbm import DaskLGBMClassifierAlsoDaskLGBMRegressor,DaskLGBMRanker— maintainer-supported.DaskLGBMRegressor(client=client).fit(dX, dy)Dask DataFrame/Array in; one LightGBM worker per Dask worker.client.persist(dX)Materialize once before hyper-parameter sweeps.tree_learner='data' / 'feature' / 'voting'Partition strategy: data-parallel is the usual default choice.joblib.dump(dask_model, …)Dask estimators pickle directly (client isn't saved).
bst.feature_importance(importance_type='gain')★'split'counts uses;'gain'sums loss reduction — prefer gain.lgb.plot_importance(bst, importance_type='gain')★Bar chart (matplotlib).lgb.plot_metric(history)Train/valid curves fromrecord_evaluation.lgb.plot_tree(bst, tree_index=0) · lgb.create_tree_digraph(bst)Visualize a single tree (matplotlib / graphviz).lgb.plot_split_value_histogram(bst, feature='f1')Where the model splits a feature — great sanity check.bst.trees_to_dataframe()Whole ensemble as a tidy DataFrame for custom analysis.
bst.save_model('m.txt', num_iteration=bst.best_iteration)★Save only up to the best round.lgb.Booster(model_file='m.txt')★Reload for prediction.bst.model_to_string() · bst.dump_model()Serialize to string / JSON dict (inspection, custom runtimes).joblib.dump(model, 'm.pkl')★Pickle the sklearn estimator (keeps params + wrapper state).bst.refit(X_new, y_new)Keep tree structure, refresh leaf values on new data — cheap domain adaptation.lgb.train(…, init_model='m.txt')Continue boosting with new trees (vs refit's value update).
seed=42Master seed (aliasrandom_state) — derives all sub-seeds.deterministic=TrueStable results across runs (same data/params); pair withforce_col_wiseorforce_row_wise.verbosity=-1Silence info/warnings;0=warn,1=info,2=debug.lgb.register_logger(custom_logger)Route LightGBM output through your logging setup.num_threads changes resultsnoteDifferent thread counts / versions / compilers may vary results even when seeded.
for accuracy: max_bin↑ · learning_rate↓ + rounds↑ · num_leaves↑Plus more training data; pair leaves↑ with regularization.for speed: bagging + feature_fraction · max_bin↓ · save_binaryAlsomax_depth, fewer rounds, GOSS, quantized grads.vs overfit: min_data_in_leaf↑ · num_leaves↓ · lambda_l1/l2 · bagging★The canonical order of attack for leaf-wise trees.num_leaves ≈ 2^(max_depth) × 0.6, then tune downPractical starting heuristic — always strictly < 2^max_depth.optuna.integration.LightGBMTunerCV(params, dtrain)Stepwise tuner purpose-built for LightGBM (3rd-party, widely used).
num_leaves = 2**max_depthoverfitsFull-depth leaf count defeats leaf-wise growth — keep it well below.pd.get_dummies(df)avoidOne-hot slows training and weakens splits — usecategorical_feature.bagging_fraction without bagging_freqsilent no-opRow sampling stays off untilbagging_freq > 0.feature_pre_filter=TruedefaultReusing a Dataset while tuningmin_data_in_leaf? Set itFalseor features get pre-dropped.params vs keyword argsprecedenceInlgb.train, values in theparamsdict override function arguments.changing max_bin after Dataset builtignoredBinning params are frozen at Dataset construction — rebuild to change.is_unbalance for probability usecalibrateRe-weighting skews predicted probabilities — recalibrate or threshold-tune.