From dbe2be24cc33f281c271aa36be3ebcbb0c0d8a56 Mon Sep 17 00:00:00 2001 From: kajal-jotwani Date: Fri, 20 Feb 2026 22:13:24 +0530 Subject: [PATCH 1/4] Add LightGBM Experiment integration --- .../experiment/integrations/__init__.py | 2 + .../integrations/lightgbm_experiment.py | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/hyperactive/experiment/integrations/lightgbm_experiment.py diff --git a/src/hyperactive/experiment/integrations/__init__.py b/src/hyperactive/experiment/integrations/__init__.py index c302e25a..351d97f5 100644 --- a/src/hyperactive/experiment/integrations/__init__.py +++ b/src/hyperactive/experiment/integrations/__init__.py @@ -2,6 +2,7 @@ # copyright: hyperactive developers, MIT License (see LICENSE file) from hyperactive.experiment.integrations.sklearn_cv import SklearnCvExperiment +from hyperactive.experiment.integrations.lightgbm_experiment import LightGBMExperiment from hyperactive.experiment.integrations.skpro_probareg import ( SkproProbaRegExperiment, ) @@ -21,4 +22,5 @@ "SktimeClassificationExperiment", "SktimeForecastingExperiment", "TorchExperiment", + "LightGBMExperiment", ] diff --git a/src/hyperactive/experiment/integrations/lightgbm_experiment.py b/src/hyperactive/experiment/integrations/lightgbm_experiment.py new file mode 100644 index 00000000..bfc551a9 --- /dev/null +++ b/src/hyperactive/experiment/integrations/lightgbm_experiment.py @@ -0,0 +1,64 @@ +"""Experiment adapter for LightGBM cross-validation experiments.""" + +# copyright: hyperactive developers, MIT License (see LICENSE file) + +from hyperactive.experiment.integrations.sklearn_cv import SklearnCvExperiment + + +class LightGBMExperiment(SklearnCvExperiment): + """Experiment adapter for LightGBM cross-validation experiments. + + Thin wrapper around SklearnCvExperiment for LightGBM estimators. + + LightGBM estimators follow the sklearn API, so this class does not + add new functionality beyond SklearnCvExperiment. It exists for + discoverability and explicit LightGBM support. + """ + + _tags = { + "python_dependencies": "lightgbm", + } + + @classmethod + def get_test_params(cls, parameter_set="default"): + """Return testing parameter settings for the estimator.""" + from skbase.utils.dependencies import _check_soft_dependencies + + if not _check_soft_dependencies("lightgbm", severity="none"): + return [] + + from sklearn.datasets import load_iris, load_diabetes + from lightgbm import LGBMClassifier, LGBMRegressor + + # Classification test case + X, y = load_iris(return_X_y=True) + params0 = { + "estimator": LGBMClassifier(n_estimators=10), + "X": X, + "y": y, + "cv": 2, + } + + # Regression test case + X, y = load_diabetes(return_X_y=True) + params1 = { + "estimator": LGBMRegressor(n_estimators=10), + "X": X, + "y": y, + "cv": 2, + } + + return [params0, params1] + + @classmethod + def _get_score_params(cls): + """Return parameter settings for score/evaluate tests.""" + from skbase.utils.dependencies import _check_soft_dependencies + + if not _check_soft_dependencies("lightgbm", severity="none"): + return [] + + val0 = {"n_estimators": 5, "max_depth": 2} + val1 = {"n_estimators": 5, "max_depth": 2} + + return [val0, val1] \ No newline at end of file From 8789a25469464e3203c901c07c9ef1b448955c19 Mon Sep 17 00:00:00 2001 From: kajal-jotwani Date: Fri, 6 Mar 2026 10:40:58 +0530 Subject: [PATCH 2/4] pre-commit fixes --- src/hyperactive/experiment/integrations/__init__.py | 2 +- .../experiment/integrations/lightgbm_experiment.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hyperactive/experiment/integrations/__init__.py b/src/hyperactive/experiment/integrations/__init__.py index 351d97f5..f4dba126 100644 --- a/src/hyperactive/experiment/integrations/__init__.py +++ b/src/hyperactive/experiment/integrations/__init__.py @@ -1,8 +1,8 @@ """Integrations with packages for tuning.""" # copyright: hyperactive developers, MIT License (see LICENSE file) -from hyperactive.experiment.integrations.sklearn_cv import SklearnCvExperiment from hyperactive.experiment.integrations.lightgbm_experiment import LightGBMExperiment +from hyperactive.experiment.integrations.sklearn_cv import SklearnCvExperiment from hyperactive.experiment.integrations.skpro_probareg import ( SkproProbaRegExperiment, ) diff --git a/src/hyperactive/experiment/integrations/lightgbm_experiment.py b/src/hyperactive/experiment/integrations/lightgbm_experiment.py index bfc551a9..2b5fcc0a 100644 --- a/src/hyperactive/experiment/integrations/lightgbm_experiment.py +++ b/src/hyperactive/experiment/integrations/lightgbm_experiment.py @@ -27,8 +27,8 @@ def get_test_params(cls, parameter_set="default"): if not _check_soft_dependencies("lightgbm", severity="none"): return [] - from sklearn.datasets import load_iris, load_diabetes from lightgbm import LGBMClassifier, LGBMRegressor + from sklearn.datasets import load_diabetes, load_iris # Classification test case X, y = load_iris(return_X_y=True) @@ -61,4 +61,4 @@ def _get_score_params(cls): val0 = {"n_estimators": 5, "max_depth": 2} val1 = {"n_estimators": 5, "max_depth": 2} - return [val0, val1] \ No newline at end of file + return [val0, val1] From 16e7b4f04da53219c8df46f56afd153947e5ec57 Mon Sep 17 00:00:00 2001 From: kajal-jotwani Date: Thu, 12 Mar 2026 13:23:55 +0530 Subject: [PATCH 3/4] add docs and tests --- .../_snippets/user_guide/integrations.py | 35 +++++++++++++ .../experiments_integrations.rst | 13 ++++- docs/source/user_guide/integrations.rst | 43 +++++++++++++++- src/hyperactive/base/tests/test_lightgbm.py | 49 +++++++++++++++++++ 4 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 src/hyperactive/base/tests/test_lightgbm.py diff --git a/docs/source/_snippets/user_guide/integrations.py b/docs/source/_snippets/user_guide/integrations.py index 5b9a0507..2eec0499 100644 --- a/docs/source/_snippets/user_guide/integrations.py +++ b/docs/source/_snippets/user_guide/integrations.py @@ -226,6 +226,41 @@ def configure_optimizers(self): best_params = optimizer.solve() # [end:pytorch_lightning] +# [start:lightgbm_experiment] +from lightgbm import LGBMClassifier +from sklearn.datasets import load_iris + +from hyperactive.experiment.integrations import LightGBMExperiment +from hyperactive.opt.gfo import BayesianOptimizer + +# Load data +X, y = load_iris(return_X_y=True) + +# Create the experiment +experiment = LightGBMExperiment( + estimator=LGBMClassifier(), + X=X, + y=y, + cv=3, +) + +# Define search space +search_space = { + "n_estimators": [50, 100, 200], + "max_depth": [3, 5, 7, -1], + "learning_rate": [0.01, 0.05, 0.1, 0.2], +} + +# Optimize +optimizer = BayesianOptimizer( + search_space=search_space, + n_iter=10, + experiment=experiment, +) +best_params = optimizer.solve() +print(f"Best parameters: {best_params}") +# [end:lightgbm_experiment] + # --- Runnable test code below --- if __name__ == "__main__": diff --git a/docs/source/api_reference/experiments_integrations.rst b/docs/source/api_reference/experiments_integrations.rst index 913e249a..4cca69ce 100644 --- a/docs/source/api_reference/experiments_integrations.rst +++ b/docs/source/api_reference/experiments_integrations.rst @@ -7,7 +7,7 @@ The :mod:`hyperactive.experiment.integrations` module contains experiment classe for integration with machine learning frameworks. These experiments provide seamless hyperparameter optimization for scikit-learn, -sktime, skpro, and PyTorch Lightning models. +sktime, skpro, PyTorch Lightning, and LightGBM models. Scikit-Learn ------------ @@ -55,3 +55,14 @@ Experiments for PyTorch Lightning models. :template: class.rst TorchExperiment + +LightGBM +-------- + +Cross-validation experiments for LightGBM estimators. + +.. autosummary:: + :toctree: auto_generated/ + :template: class.rst + + LightGBMExperiment diff --git a/docs/source/user_guide/integrations.rst b/docs/source/user_guide/integrations.rst index cf0bc2f9..07768d88 100644 --- a/docs/source/user_guide/integrations.rst +++ b/docs/source/user_guide/integrations.rst @@ -7,7 +7,7 @@ Framework Integrations Hyperactive integrates with popular ML frameworks, providing drop-in replacements for tools like ``GridSearchCV``. Each ML framework has its own conventions for training and evaluation. The integration classes handle cross-validation setup, scoring metrics, and parameter translation, so -you can use any optimizer with scikit-learn, sktime, skpro, or PyTorch models. +you can use any optimizer with scikit-learn, sktime, skpro, PyTorch, or LightGBM models. ---- @@ -53,6 +53,15 @@ Supported Frameworks Deep learning models + .. grid-item-card:: LightGBM + :class-card: sd-border-info + :link: #lightgbm-integration + :link-type: url + + **LightGBMExperiment** + + Gradient boosting models + ---- Quick Reference @@ -86,6 +95,10 @@ Quick Reference - ``TorchExperiment`` - Deep learning models - ``[all_extras]`` + * - LightGBM + - ``LightGBMExperiment`` + - Classification, regression + - ``[lightgbm]`` ---- @@ -237,6 +250,34 @@ For deep learning hyperparameter optimization with PyTorch Lightning: ---- +LightGBM Integration +-------------------- + +For gradient boosting hyperparameter optimization with LightGBM: + +.. note:: + + Requires ``pip install lightgbm`` + +.. grid:: 1 + :gutter: 0 + + .. grid-item:: + :class: sd-bg-light sd-pt-3 sd-pb-1 sd-ps-3 sd-pe-3 sd-rounded-3 + + **Key Features** + + - Optimize LightGBM classifiers and regressors + - LightGBM follows the sklearn API, so cross-validation works out of the box + - Supports all LightGBM hyperparameters (``n_estimators``, ``max_depth``, ``learning_rate``, etc.) + +.. literalinclude:: ../_snippets/user_guide/integrations.py + :language: python + :start-after: # [start:lightgbm_experiment] + :end-before: # [end:lightgbm_experiment] + +---- + Tips ---- diff --git a/src/hyperactive/base/tests/test_lightgbm.py b/src/hyperactive/base/tests/test_lightgbm.py new file mode 100644 index 00000000..9a981744 --- /dev/null +++ b/src/hyperactive/base/tests/test_lightgbm.py @@ -0,0 +1,49 @@ +"""Integration test for end-to-end usage of optimizer with LightGBM experiment.""" +# copyright: hyperactive developers, MIT License (see LICENSE file) + + + +def test_endtoend_lightgbm(): + """Test end-to-end usage of HillClimbing optimizer with LightGBM experiment.""" + from skbase.utils.dependencies import _check_soft_dependencies + + if not _check_soft_dependencies("lightgbm", severity="none"): + return None + + # define the experiment + from lightgbm import LGBMClassifier + from sklearn.datasets import load_iris + + from hyperactive.experiment.integrations import LightGBMExperiment + + X, y = load_iris(return_X_y=True) + + lgbm_exp = LightGBMExperiment( + estimator=LGBMClassifier(n_estimators=10, verbosity=-1), + X=X, + y=y, + cv=2, + ) + + # set up the HillClimbing optimizer + import numpy as np + + from hyperactive.opt import HillClimbing + + hillclimbing_config = { + "search_space": { + "n_estimators": np.array([5, 10, 20]), + "max_depth": np.array([2, 3, 5]), + }, + "n_iter": 10, + } + hill_climbing = HillClimbing(**hillclimbing_config, experiment=lgbm_exp) + + # run the HillClimbing optimizer + hill_climbing.solve() + + best_params = hill_climbing.best_params_ + assert best_params is not None, "Best parameters should not be None" + assert isinstance(best_params, dict), "Best parameters should be a dictionary" + assert "n_estimators" in best_params, "Best parameters should contain 'n_estimators'" + assert "max_depth" in best_params, "Best parameters should contain 'max_depth'" \ No newline at end of file From 85906db4acca76f6fe067b97d21eed54af58ce38 Mon Sep 17 00:00:00 2001 From: kajal-jotwani Date: Thu, 12 Mar 2026 18:09:14 +0530 Subject: [PATCH 4/4] fix lint --- src/hyperactive/base/tests/test_lightgbm.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hyperactive/base/tests/test_lightgbm.py b/src/hyperactive/base/tests/test_lightgbm.py index 9a981744..078a2b65 100644 --- a/src/hyperactive/base/tests/test_lightgbm.py +++ b/src/hyperactive/base/tests/test_lightgbm.py @@ -2,7 +2,6 @@ # copyright: hyperactive developers, MIT License (see LICENSE file) - def test_endtoend_lightgbm(): """Test end-to-end usage of HillClimbing optimizer with LightGBM experiment.""" from skbase.utils.dependencies import _check_soft_dependencies @@ -45,5 +44,7 @@ def test_endtoend_lightgbm(): best_params = hill_climbing.best_params_ assert best_params is not None, "Best parameters should not be None" assert isinstance(best_params, dict), "Best parameters should be a dictionary" - assert "n_estimators" in best_params, "Best parameters should contain 'n_estimators'" - assert "max_depth" in best_params, "Best parameters should contain 'max_depth'" \ No newline at end of file + assert ( + "n_estimators" in best_params + ), "Best parameters should contain 'n_estimators'" + assert "max_depth" in best_params, "Best parameters should contain 'max_depth'"