From ac23ad1dcf93425e527ecd4ae60370a276410f04 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Sat, 28 Feb 2026 22:55:15 +0530 Subject: [PATCH 1/2] add missing torch entries in README and documentation --- README.md | 4 +- docs/source/examples/integrations.rst | 25 ++++ examples/integrations/README.md | 103 +++++++++++++++- .../integrations/torch_experiment_example.py | 111 ++++++++++++++++++ 4 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 examples/integrations/torch_experiment_example.py diff --git a/README.md b/README.md index 0562174b..9e24588a 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,8 @@ pip install hyperactive[all_extras] # Everything including Optuna GFO algorithms, Optuna samplers, and sklearn search methods through one unified API. - Stable & Tested
- 5+ years of development, comprehensive test coverage, and active maintenance since 2019. + Problems & Experiments
+ Toy optimization problems as well as AI/ML benchmarking experiments for evaluation and testing. diff --git a/docs/source/examples/integrations.rst b/docs/source/examples/integrations.rst index 2fff131c..ea991cd2 100644 --- a/docs/source/examples/integrations.rst +++ b/docs/source/examples/integrations.rst @@ -33,6 +33,31 @@ For time series forecasting and classification with sktime: pip install hyperactive[sktime-integration] +PyTorch Lightning Integration +----------------------------- + +For deep learning hyperparameter optimization with PyTorch Lightning: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Use Case + - Example + * - PyTorch Lightning Experiment + - `torch_experiment_example.py `_ + +.. note:: + + PyTorch Lightning integration requires additional dependencies: + + .. code-block:: bash + + pip install hyperactive[all_extras] + + or install ``torch`` and ``lightning`` separately. + + Installing Extras ----------------- diff --git a/examples/integrations/README.md b/examples/integrations/README.md index d049161b..c9c172e3 100644 --- a/examples/integrations/README.md +++ b/examples/integrations/README.md @@ -1,7 +1,7 @@ # Integrations with AI framework toolboxes This directory contains examples for estimator level integration with -common AI toolbox libraries such as `scikit-learn` or `sktime`. +common AI toolbox libraries such as `scikit-learn`, `sktime`, or `torch`. ## Quick Start @@ -12,9 +12,10 @@ You can also run any example directly: python sklearn_classif_example.py python sktime_forecasting_example.py python sktime_tsc_example.py +python torch_experiment_example.py ``` -Requires `scikit-learn` resp `sktime` installed. +Requires `scikit-learn` resp `sktime` resp `torch` and `lightning` installed. ## Available Integrations @@ -23,6 +24,7 @@ Requires `scikit-learn` resp `sktime` installed. | `sklearn` classifier or regressor tuner | [OptCV](sklearn_classif_example.py) | | `sktime` forecasting tuner | [ForecastingOptCV](sktime_forecasting_example.py) | | `sktime` time series classifier tuner | [TSCOptCV](sktime_tsc_example.py) | +| `torch` experiment tuner | [TorchExperiment](torch_experiment_example.py) | ## Integration with sklearn @@ -143,3 +145,100 @@ y_pred = tuned_naive.predict(X_test) best_params = tuned_naive.best_params_ best_classifier = tuned_naive.best_estimator_ ``` + +## Integration with torch + +Any available tuning engine from hyperactive can be used, for example: + +* hill climbing - ``from hyperactive.opt import HillClimbing`` +* bayesian optimization - ``from hyperactive.opt.gfo import BayesianOptimizer`` +* optuna parzen-tree search - ``from hyperactive.opt.optuna import TPEOptimizer`` + +For illustration, we use hill climbing, this can be replaced by any other optimizer. + +```python +# 1. defining the experiment: +import numpy as np +import lightning as L +import torch +from torch import nn +from torch.utils.data import DataLoader + +from hyperactive.experiment.integrations import TorchExperiment +from hyperactive.opt.gfo import HillClimbing + +class SimpleLightningModule(L.LightningModule): + def __init__(self, input_dim=10, hidden_dim=16, lr=1e-3): + super().__init__() + self.save_hyperparameters() + self.model = nn.Sequential( + nn.Linear(input_dim, hidden_dim), nn.ReLU(), + nn.Linear(hidden_dim, 2), + ) + self.lr = lr + + def forward(self, x): + return self.model(x) + + def training_step(self, batch, batch_idx): + x, y = batch + loss = nn.functional.cross_entropy(self(x), y) + self.log("train_loss", loss) + return loss + + def validation_step(self, batch, batch_idx): + x, y = batch + val_loss = nn.functional.cross_entropy(self(x), y) + self.log("val_loss", val_loss, on_epoch=True) + return val_loss + + def configure_optimizers(self): + return torch.optim.Adam(self.parameters(), lr=self.lr) + +class RandomDataModule(L.LightningDataModule): + def __init__(self, batch_size=32): + super().__init__() + self.batch_size = batch_size + + def setup(self, stage=None): + dataset = torch.utils.data.TensorDataset( + torch.randn(200, 10), torch.randint(0, 2, (200,)), + ) + self.train, self.val = torch.utils.data.random_split( + dataset, [160, 40] + ) + + def train_dataloader(self): + return DataLoader(self.train, batch_size=self.batch_size) + + def val_dataloader(self): + return DataLoader(self.val, batch_size=self.batch_size) + +# 2. creating the experiment: +datamodule = RandomDataModule(batch_size=16) +datamodule.setup() + +experiment = TorchExperiment( + datamodule=datamodule, + lightning_module=SimpleLightningModule, + trainer_kwargs={"max_epochs": 3}, + objective_metric="val_loss", +) + +# 3. defining search space and running optimization: +search_space = { + "hidden_dim": [16, 32, 64, 128], + "lr": np.logspace(-4, -1, 10).tolist(), +} + +optimizer = HillClimbing( + search_space=search_space, + n_iter=5, + experiment=experiment, +) +best_params = optimizer.solve() + +# 4. obtaining best parameters +print(f"Best params: {best_params}") +``` + diff --git a/examples/integrations/torch_experiment_example.py b/examples/integrations/torch_experiment_example.py new file mode 100644 index 00000000..6df4ced5 --- /dev/null +++ b/examples/integrations/torch_experiment_example.py @@ -0,0 +1,111 @@ +"""Example: Hyperparameter tuning with TorchExperiment and PyTorch Lightning. + +This example demonstrates how to use the TorchExperiment class to +optimize hyperparameters of a PyTorch Lightning model using Hyperactive. +""" + +import lightning as L +import numpy as np +import torch +from torch import nn +from torch.utils.data import DataLoader + +from hyperactive.experiment.integrations import TorchExperiment +from hyperactive.opt.gfo import HillClimbing + + +# 1. Define a Lightning Module +class SimpleLightningModule(L.LightningModule): + """Simple classification model for demonstration.""" + + def __init__(self, input_dim=10, hidden_dim=16, lr=1e-3): + super().__init__() + self.save_hyperparameters() + self.model = nn.Sequential( + nn.Linear(input_dim, hidden_dim), + nn.ReLU(), + nn.Linear(hidden_dim, 2), + ) + self.lr = lr + + def forward(self, x): + """Forward pass.""" + return self.model(x) + + def training_step(self, batch, batch_idx): + """Training step.""" + x, y = batch + y_hat = self(x) + loss = nn.functional.cross_entropy(y_hat, y) + self.log("train_loss", loss) + return loss + + def validation_step(self, batch, batch_idx): + """Validate a single batch.""" + x, y = batch + y_hat = self(x) + val_loss = nn.functional.cross_entropy(y_hat, y) + self.log("val_loss", val_loss, on_epoch=True) + return val_loss + + def configure_optimizers(self): + """Configure optimizers.""" + return torch.optim.Adam(self.parameters(), lr=self.lr) + + +# 2. Define a DataModule +class RandomDataModule(L.LightningDataModule): + """Random data module for demonstration.""" + + def __init__(self, batch_size=32): + super().__init__() + self.batch_size = batch_size + + def setup(self, stage=None): + """Set up train and validation datasets.""" + dataset = torch.utils.data.TensorDataset( + torch.randn(200, 10), + torch.randint(0, 2, (200,)), + ) + self.train, self.val = torch.utils.data.random_split(dataset, [160, 40]) + + def train_dataloader(self): + """Return training dataloader.""" + return DataLoader(self.train, batch_size=self.batch_size) + + def val_dataloader(self): + """Return validation dataloader.""" + return DataLoader(self.val, batch_size=self.batch_size) + + +# 3. Create the TorchExperiment +datamodule = RandomDataModule(batch_size=16) +datamodule.setup() + +experiment = TorchExperiment( + datamodule=datamodule, + lightning_module=SimpleLightningModule, + trainer_kwargs={ + "max_epochs": 3, + "enable_progress_bar": False, + "enable_model_summary": False, + "logger": False, + }, + objective_metric="val_loss", +) + +# 4. Define search space and optimizer +search_space = { + "hidden_dim": [16, 32, 64, 128], + "lr": np.logspace(-4, -1, 10).tolist(), +} + +optimizer = HillClimbing( + search_space=search_space, + n_iter=5, + experiment=experiment, +) + +# 5. Run optimization +best_params = optimizer.solve() +print(f"Best params: {best_params}") From bb93f4bb8e8413c5e3cdfd567a2ca8444d352f80 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Sun, 1 Mar 2026 11:42:15 +0530 Subject: [PATCH 2/2] revert README changes, keep example and docs only --- README.md | 4 +- examples/integrations/README.md | 103 +------------------------------- 2 files changed, 4 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 9e24588a..0562174b 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,8 @@ pip install hyperactive[all_extras] # Everything including Optuna GFO algorithms, Optuna samplers, and sklearn search methods through one unified API. - Problems & Experiments
- Toy optimization problems as well as AI/ML benchmarking experiments for evaluation and testing. + Stable & Tested
+ 5+ years of development, comprehensive test coverage, and active maintenance since 2019. diff --git a/examples/integrations/README.md b/examples/integrations/README.md index c9c172e3..d049161b 100644 --- a/examples/integrations/README.md +++ b/examples/integrations/README.md @@ -1,7 +1,7 @@ # Integrations with AI framework toolboxes This directory contains examples for estimator level integration with -common AI toolbox libraries such as `scikit-learn`, `sktime`, or `torch`. +common AI toolbox libraries such as `scikit-learn` or `sktime`. ## Quick Start @@ -12,10 +12,9 @@ You can also run any example directly: python sklearn_classif_example.py python sktime_forecasting_example.py python sktime_tsc_example.py -python torch_experiment_example.py ``` -Requires `scikit-learn` resp `sktime` resp `torch` and `lightning` installed. +Requires `scikit-learn` resp `sktime` installed. ## Available Integrations @@ -24,7 +23,6 @@ Requires `scikit-learn` resp `sktime` resp `torch` and `lightning` installed. | `sklearn` classifier or regressor tuner | [OptCV](sklearn_classif_example.py) | | `sktime` forecasting tuner | [ForecastingOptCV](sktime_forecasting_example.py) | | `sktime` time series classifier tuner | [TSCOptCV](sktime_tsc_example.py) | -| `torch` experiment tuner | [TorchExperiment](torch_experiment_example.py) | ## Integration with sklearn @@ -145,100 +143,3 @@ y_pred = tuned_naive.predict(X_test) best_params = tuned_naive.best_params_ best_classifier = tuned_naive.best_estimator_ ``` - -## Integration with torch - -Any available tuning engine from hyperactive can be used, for example: - -* hill climbing - ``from hyperactive.opt import HillClimbing`` -* bayesian optimization - ``from hyperactive.opt.gfo import BayesianOptimizer`` -* optuna parzen-tree search - ``from hyperactive.opt.optuna import TPEOptimizer`` - -For illustration, we use hill climbing, this can be replaced by any other optimizer. - -```python -# 1. defining the experiment: -import numpy as np -import lightning as L -import torch -from torch import nn -from torch.utils.data import DataLoader - -from hyperactive.experiment.integrations import TorchExperiment -from hyperactive.opt.gfo import HillClimbing - -class SimpleLightningModule(L.LightningModule): - def __init__(self, input_dim=10, hidden_dim=16, lr=1e-3): - super().__init__() - self.save_hyperparameters() - self.model = nn.Sequential( - nn.Linear(input_dim, hidden_dim), nn.ReLU(), - nn.Linear(hidden_dim, 2), - ) - self.lr = lr - - def forward(self, x): - return self.model(x) - - def training_step(self, batch, batch_idx): - x, y = batch - loss = nn.functional.cross_entropy(self(x), y) - self.log("train_loss", loss) - return loss - - def validation_step(self, batch, batch_idx): - x, y = batch - val_loss = nn.functional.cross_entropy(self(x), y) - self.log("val_loss", val_loss, on_epoch=True) - return val_loss - - def configure_optimizers(self): - return torch.optim.Adam(self.parameters(), lr=self.lr) - -class RandomDataModule(L.LightningDataModule): - def __init__(self, batch_size=32): - super().__init__() - self.batch_size = batch_size - - def setup(self, stage=None): - dataset = torch.utils.data.TensorDataset( - torch.randn(200, 10), torch.randint(0, 2, (200,)), - ) - self.train, self.val = torch.utils.data.random_split( - dataset, [160, 40] - ) - - def train_dataloader(self): - return DataLoader(self.train, batch_size=self.batch_size) - - def val_dataloader(self): - return DataLoader(self.val, batch_size=self.batch_size) - -# 2. creating the experiment: -datamodule = RandomDataModule(batch_size=16) -datamodule.setup() - -experiment = TorchExperiment( - datamodule=datamodule, - lightning_module=SimpleLightningModule, - trainer_kwargs={"max_epochs": 3}, - objective_metric="val_loss", -) - -# 3. defining search space and running optimization: -search_space = { - "hidden_dim": [16, 32, 64, 128], - "lr": np.logspace(-4, -1, 10).tolist(), -} - -optimizer = HillClimbing( - search_space=search_space, - n_iter=5, - experiment=experiment, -) -best_params = optimizer.solve() - -# 4. obtaining best parameters -print(f"Best params: {best_params}") -``` -