Source code for ax.benchmark.benchmark_suite

#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
# pyre-strict

from itertools import product
from typing import List

from ax.benchmark.benchmark_problem import (
    BenchmarkProblem,
    branin_max,
    hartmann6_constrained,
)
from ax.benchmark.benchmark_runner import (
    BenchmarkResult,
    BenchmarkSetup,
    BOBenchmarkRunner,
)
from ax.modelbridge.generation_strategy import GenerationStep, GenerationStrategy
from ax.modelbridge.registry import Models
from ax.plot.base import AxPlotConfig
from ax.plot.render import plot_config_to_html
from ax.plot.trace import (
    optimization_times,
    optimization_trace_all_methods,
    optimization_trace_single_method,
)
from ax.utils.report.render import h2_html, h3_html, p_html, render_report_elements


BOStrategies: List[GenerationStrategy] = [
    GenerationStrategy(
        name="Sobol", steps=[GenerationStep(model=Models.SOBOL, num_arms=50)]
    ),
    # Generation strategy to use Sobol for first 5 arms and GP+EI for next 45:
    GenerationStrategy(
        name="Sobol+GPEI",
        steps=[
            GenerationStep(model=Models.SOBOL, num_arms=5, min_arms_observed=5),
            GenerationStep(model=Models.GPEI, num_arms=-1),
        ],
    ),
]

BOProblems: List[BenchmarkProblem] = [hartmann6_constrained, branin_max]


[docs]class BOBenchmarkingSuite: """Suite that runs all standard Bayesian optimization benchmarks.""" def __init__(self) -> None: self._runner: BOBenchmarkRunner = BOBenchmarkRunner()
[docs] def run( self, num_runs: int, total_iterations: int, bo_strategies: List[GenerationStrategy], bo_problems: List[BenchmarkProblem], batch_size: int = 1, raise_all_errors: bool = False, ) -> BOBenchmarkRunner: """Run all standard BayesOpt benchmarks. Args: num_runs: How many time to run each test. total_iterations: How many iterations to run each optimization for. bo_strategies: GenerationStrategies representing each method to benchmark. bo_problems: Problems to benchmark the methods on. batch_size: Number of arms to be generated and evaluated in optimization at once. raise_all_errors: Debugging setting; set to true if all encountered errors should be raised right away (and interrupt the benchm arking) rather than logged and recorded. """ setups = ( BenchmarkSetup(problem, total_iterations, batch_size) for problem in bo_problems ) for setup, gs in product(setups, bo_strategies): self._runner.run_benchmark_test( setup=setup, generation_strategy=gs, num_runs=num_runs, raise_all_errors=raise_all_errors, ) return self._runner
[docs] def add_run(self, setup: BenchmarkSetup, strategy_name: str) -> None: """Add a run (BenchmarkSetup) to the benchmark results. Args: setup: Run to add strategy_name: Name of strategy used for this run """ # Get run_idx run_idx = 0 while (setup.name, strategy_name, run_idx) in self._runner._runs: run_idx += 1 run_key = (setup.name, strategy_name, run_idx) self._runner._runs[run_key] = setup self._runner._generator_changes[run_key] = []
@classmethod def _make_plots( cls, benchmark_result: BenchmarkResult, problem_name: str, include_individual: bool, ) -> List[AxPlotConfig]: plots: List[AxPlotConfig] = [] # Plot objective at true best plots.append( optimization_trace_all_methods( y_dict=benchmark_result.objective_at_true_best, optimum=benchmark_result.optimum, title=f"{problem_name}: cumulative best objective", ylabel="Objective at best-feasible point observed so far", ) ) if include_individual: # Plot individual plots of a single method on a single problem. for m, y in benchmark_result.objective_at_true_best.items(): plots.append( optimization_trace_single_method( y=y, optimum=benchmark_result.optimum, generator_changes=benchmark_result.generator_changes[m], title=f"{problem_name}, {m}: cumulative best objective", ylabel="Objective at best-feasible point observed so far", ) ) # Plot time plots.append( optimization_times( fit_times=benchmark_result.fit_times, gen_times=benchmark_result.gen_times, title=f"{problem_name}: optimization times", ) ) return plots
[docs] def generate_report(self, include_individual: bool = False) -> str: benchmark_result_dict = self._runner.aggregate_results() html_elements = [h2_html("Bayesian Optimization benchmarking suite report")] for p, benchmark_result in benchmark_result_dict.items(): html_elements.append(h3_html(f"{p}:")) plots = self._make_plots( benchmark_result, problem_name=p, include_individual=include_individual ) html_elements.extend(plot_config_to_html(plt) for plt in plots) if len(self._runner._error_messages) > 0: html_elements.append(h3_html("Errors encountered")) html_elements.extend(p_html(err) for err in self._runner._error_messages) else: html_elements.append(h3_html("No errors encountered")) return render_report_elements("bo_benchmark_suite_test", html_elements)