Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[BUG] Problem with HyperBand setup given a total budget #1179

Open
becktepe opened this issue Dec 6, 2024 · 2 comments · May be fixed by #1186
Open

[BUG] Problem with HyperBand setup given a total budget #1179

becktepe opened this issue Dec 6, 2024 · 2 comments · May be fixed by #1186
Assignees
Labels
Milestone

Comments

@becktepe
Copy link

becktepe commented Dec 6, 2024

Description

I wanted to use HyperBand and define a total budget as shown in the documentation. However, the actual budget that is used by SMAC does not match the requested budget.

The bug is caused by this line:

total_budget = np.sum([np.sum(v) for v in _budgets_in_stage.values()])

When computing the total budget of a HyperBand bracket we need to multiply the number of configs per budget by the respective budget:

  total_budget = 0
  for stage in _n_configs_in_stage.keys():
      for b, c in zip(_budgets_in_stage[stage], _n_configs_in_stage[stage]):
          total_budget += b * c

After fixing this, the actual budget is 9_999.99.

Steps/Code to Reproduce

This is basically the example mentioned above:

from __future__ import annotations

import numpy as np
from ConfigSpace import Configuration, ConfigurationSpace, Float
from matplotlib import pyplot as plt

from smac import MultiFidelityFacade, RunHistory, Scenario
from smac.intensifier.hyperband_utils import get_n_trials_for_hyperband_multifidelity

__copyright__ = "Copyright 2021, AutoML.org Freiburg-Hannover"
__license__ = "3-clause BSD"


class QuadraticFunction:
    max_budget = 500

    @property
    def configspace(self) -> ConfigurationSpace:
        cs = ConfigurationSpace(seed=0)
        x = Float("x", (-5, 5), default=-5)
        cs.add([x])

        return cs

    def train(self, config: Configuration, seed: int = 0, budget: float | None = None) -> float:
        """Returns the y value of a quadratic function with a minimum we know to be at x=0."""
        x = config["x"]

        if budget is None:
            multiplier = 1
        else:
            multiplier = 1 + budget / self.max_budget

        return x**2 * multiplier


if __name__ == "__main__":
    model = QuadraticFunction()

    total_budget = 10000
    min_budget = 10  # minimum budget per trial
    max_budget = 500  # maximum budget per trial
    eta = 3  # standard HB parameter influencing the number of stages

    # Let's calculate how many trials we need to exhaust the total optimization budget (in terms of
    # fidelity units)
    n_trials = get_n_trials_for_hyperband_multifidelity(
        total_budget=total_budget,  # this is the total optimization budget we specify in terms of fidelity units
        min_budget=min_budget,  # This influences the Hyperband rounds, minimum budget per trial
        max_budget=max_budget,  # This influences the Hyperband rounds, maximum budget per trial
        eta=eta,  # This influences the Hyperband rounds
        print_summary=True,
    )

    # Scenario object specifying the optimization "environment"
    scenario = Scenario(
        model.configspace, deterministic=True, n_trials=n_trials, min_budget=min_budget, max_budget=max_budget
    )

    # Now we use SMAC to find the best hyperparameters
    smac = MultiFidelityFacade(
        scenario,
        model.train,  # We pass the target function here
        overwrite=True,  # Overrides any previous results that are found that are inconsistent with the meta-data
        intensifier=MultiFidelityFacade.get_intensifier(scenario=scenario, eta=eta),
    )

    incumbent = smac.optimize()

    total_budget_used = sum([trial.budget for trial in smac.runhistory])

    print(f"Total budget defined: {total_budget}")
    print(f"Total budget used: {total_budget_used}")

Expected Results

After calling get_n_trials_for_hyperband_multifidelity with a total budget of 10_000 I would expect the actual used budget to be less than or equal to 10_000.

Actual Results

The actual used budget is 25_611.11.

Versions

2.2.0

@becktepe becktepe changed the title [BUG] [BUG] Problem with HyperBand setup given a total budget Dec 6, 2024
@benjamc benjamc added the bug label Dec 19, 2024
@benjamc
Copy link
Collaborator

benjamc commented Dec 19, 2024

Hi @becktepe
just to confirm, the fix is this?

total_budget = 0
for stage in _n_configs_in_stage.keys():
    for b, c in zip(_budgets_in_stage[stage], _n_configs_in_stage[stage]):
        total_budget += b * c

@benjamc benjamc added this to the v2.3 milestone Dec 19, 2024
@becktepe
Copy link
Author

becktepe commented Jan 8, 2025

Hi, yes, that's the fix :)

@daphne12345 daphne12345 linked a pull request Jan 13, 2025 that will close this issue
@benjamc benjamc linked a pull request Jan 13, 2025 that will close this issue
@benjamc benjamc moved this to In Progress in SMAC board Jan 13, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
Status: In Progress
Development

Successfully merging a pull request may close this issue.

3 participants