def test_get_contour_info_nonfinite_removed(value: float) -> None: study = prepare_study_with_trials(value_for_first_trial=value) info = _get_contour_info(study, params=["param_b", "param_d"]) assert info == _ContourInfo( sorted_params=["param_b", "param_d"], sub_plot_infos=[[ _SubContourInfo( xaxis=_AxisInfo( name="param_b", range=(-0.05, 1.05), is_log=False, is_cat=False, indices=[-0.05, 0.0, 1.0, 1.05], values=[0.0, 1.0], ), yaxis=_AxisInfo( name="param_d", range=(1.9, 4.1), is_log=False, is_cat=False, indices=[1.9, 2.0, 4.0, 4.1], values=[4.0, 2.0], ), z_values={ (1, 2): 2.0, (2, 1): 1.0 }, ) ]], reverse_scale=True, target_name="Objective Value", )
def test_get_contour_info_2_params() -> None: params = ["param_a", "param_b"] study = prepare_study_with_trials() info = _get_contour_info(study, params=params) assert info == _ContourInfo( sorted_params=params, sub_plot_infos=[[ _SubContourInfo( xaxis=_AxisInfo( name="param_a", range=(0.925, 2.575), is_log=False, is_cat=False, indices=[0.925, 1.0, 2.5, 2.575], values=[1.0, None, 2.5], ), yaxis=_AxisInfo( name="param_b", range=(-0.1, 2.1), is_log=False, is_cat=False, indices=[-0.1, 0.0, 1.0, 2.0, 2.1], values=[2.0, 0.0, 1.0], ), z_values={ (1, 3): 0.0, (2, 2): 1.0 }, ) ]], reverse_scale=True, target_name="Objective Value", )
def test_get_contour_info_mixture_category_types() -> None: study = _create_study_mixture_category_types() info = _get_contour_info(study) assert info == _ContourInfo( sorted_params=["param_a", "param_b"], sub_plot_infos=[[ _SubContourInfo( xaxis=_AxisInfo( name="param_a", range=(-0.05, 1.05), is_log=False, is_cat=True, indices=["100", "None"], values=["None", "100"], ), yaxis=_AxisInfo( name="param_b", range=(100.95, 102.05), is_log=False, is_cat=False, indices=[100.95, 101, 102, 102.05], values=[101.0, 102.0], ), z_values={ (0, 2): 0.5, (1, 1): 0.0 }, ) ]], reverse_scale=True, target_name="Objective Value", )
def test_get_contour_info_empty(specific_create_study: Callable[[], Study], params: Optional[List[str]]) -> None: study = specific_create_study() info = _get_contour_info(study, params=params) assert len(info.sorted_params) == 0 assert len(info.sub_plot_infos) == 0
def test_get_contour_info_more_than_2_params( params: Optional[List[str]]) -> None: study = prepare_study_with_trials() n_params = len(params) if params is not None else 4 info = _get_contour_info(study, params=params) assert len(info.sorted_params) == n_params assert np.shape(np.asarray(info.sub_plot_infos)) == (n_params, n_params, 3)
def test_get_contour_info_log_scale_and_str_category_more_than_2_params( ) -> None: # If the search space has three parameters, plot_contour generates nine plots. study = _create_study_with_log_scale_and_str_category_3d() info = _get_contour_info(study) params = ["param_a", "param_b", "param_c"] assert info.sorted_params == params assert np.shape(np.asarray(info.sub_plot_infos)) == (3, 3, 3) ranges = { "param_a": (math.pow(10, -6.05), math.pow(10, -4.95)), "param_b": (-0.05, 1.05), "param_c": (-0.05, 1.05), } is_log = {"param_a": True, "param_b": False, "param_c": False} is_cat = {"param_a": False, "param_b": True, "param_c": True} indices: Dict[str, List[Union[str, float]]] = { "param_a": [math.pow(10, -6.05), 1e-6, 1e-5, math.pow(10, -4.95)], "param_b": ["100", "101"], "param_c": ["one", "two"], } values = { "param_a": [1e-6, 1e-5], "param_b": ["101", "100"], "param_c": ["one", "two"] } def _check_axis(axis: _AxisInfo, name: str) -> None: assert axis.name == name assert axis.range == ranges[name] assert axis.is_log == is_log[name] assert axis.is_cat == is_cat[name] assert axis.indices == indices[name] assert axis.values == values[name] for yi in range(3): for xi in range(3): xaxis = info.sub_plot_infos[yi][xi].xaxis yaxis = info.sub_plot_infos[yi][xi].yaxis x_param = params[xi] y_param = params[yi] _check_axis(xaxis, x_param) _check_axis(yaxis, y_param) z_values = info.sub_plot_infos[yi][xi].z_values if xi == yi: assert z_values == {} else: for i, v in enumerate([0.0, 1.0]): x_value = xaxis.values[i] y_value = yaxis.values[i] assert x_value is not None assert y_value is not None xi = xaxis.indices.index(x_value) yi = yaxis.indices.index(y_value) assert z_values[(xi, yi)] == v
def test_get_contour_info_customized_target(params: List[str]) -> None: study = prepare_study_with_trials() info = _get_contour_info(study, params=params, target=lambda t: t.params["param_d"]) n_params = len(params) assert len(info.sorted_params) == n_params plot_shape = (1, 1, 3) if n_params == 2 else (n_params, n_params, 3) assert np.shape(np.asarray(info.sub_plot_infos)) == plot_shape
def test_generate_contour_plot_for_few_observations(params: List[str]) -> None: study = create_study(direction="minimize") study.add_trial( create_trial( values=[0.0], params={ "param_a": 1.0, "param_b": 2.0 }, distributions={ "param_a": FloatDistribution(0.0, 3.0), "param_b": FloatDistribution(0.0, 3.0), }, )) study.add_trial( create_trial( values=[2.0], params={"param_b": 0.0}, distributions={"param_b": FloatDistribution(0.0, 3.0)}, )) info = _get_contour_info(study, params=params) assert info == _ContourInfo( sorted_params=sorted(params), sub_plot_infos=[[ _SubContourInfo( xaxis=_AxisInfo( name=sorted(params)[0], range=(1.0, 1.0), is_log=False, is_cat=False, indices=[1.0], values=[1.0, None], ), yaxis=_AxisInfo( name=sorted(params)[1], range=(-0.1, 2.1), is_log=False, is_cat=False, indices=[-0.1, 0.0, 2.0, 2.1], values=[2.0, 0.0], ), z_values={}, ) ]], reverse_scale=True, target_name="Objective Value", )
def test_get_contour_info_log_scale_and_str_category_2_params() -> None: # If the search space has two parameters, plot_contour generates a single plot. study = _create_study_with_log_scale_and_str_category_2d() info = _get_contour_info(study) assert info == _ContourInfo( sorted_params=["param_a", "param_b"], sub_plot_infos=[[ _SubContourInfo( xaxis=_AxisInfo( name="param_a", range=(math.pow(10, -6.05), math.pow(10, -4.95)), is_log=True, is_cat=False, indices=[ math.pow(10, -6.05), 1e-6, 1e-5, math.pow(10, -4.95) ], values=[1e-6, 1e-5], ), yaxis=_AxisInfo( name="param_b", range=(-0.05, 1.05), is_log=False, is_cat=True, indices=["100", "101"], values=["101", "100"], ), z_values={ (1, 1): 0.0, (2, 0): 1.0 }, ) ]], reverse_scale=True, target_name="Objective Value", )
def plot_contour( study: Study, params: Optional[List[str]] = None, *, target: Optional[Callable[[FrozenTrial], float]] = None, target_name: str = "Objective Value", ) -> "Axes": """Plot the parameter relationship as contour plot in a study with Matplotlib. Note that, if a parameter contains missing values, a trial with missing values is not plotted. .. seealso:: Please refer to :func:`optuna.visualization.plot_contour` for an example. Warnings: Output figures of this Matplotlib-based :func:`~optuna.visualization.matplotlib.plot_contour` function would be different from those of the Plotly-based :func:`~optuna.visualization.plot_contour`. Example: The following code snippet shows how to plot the parameter relationship as contour plot. .. plot:: import optuna def objective(trial): x = trial.suggest_float("x", -100, 100) y = trial.suggest_categorical("y", [-1, 0, 1]) return x ** 2 + y sampler = optuna.samplers.TPESampler(seed=10) study = optuna.create_study(sampler=sampler) study.optimize(objective, n_trials=30) optuna.visualization.matplotlib.plot_contour(study, params=["x", "y"]) Args: study: A :class:`~optuna.study.Study` object whose trials are plotted for their target values. params: Parameter list to visualize. The default is all parameters. target: A function to specify the value to display. If it is :obj:`None` and ``study`` is being used for single-objective optimization, the objective values are plotted. .. note:: Specify this argument if ``study`` is being used for multi-objective optimization. target_name: Target's name to display on the color bar. Returns: A :class:`matplotlib.axes.Axes` object. """ _imports.check() _logger.warning( "Output figures of this Matplotlib-based `plot_contour` function would be different from " "those of the Plotly-based `plot_contour`.") info = _get_contour_info(study, params, target, target_name) return _get_contour_plot(info)
def test_get_contour_info_too_short_params(params: List[str]) -> None: study = prepare_study_with_trials() info = _get_contour_info(study, params=params) assert len(info.sorted_params) == len(params) assert len(info.sub_plot_infos) == len(params)
def test_get_contour_info_non_exist_param_error() -> None: study = prepare_study_with_trials() with pytest.raises(ValueError): _get_contour_info(study, ["optuna"])
def test_target_is_none_and_study_is_multi_obj() -> None: study = create_study(directions=["minimize", "minimize"]) with pytest.raises(ValueError): _get_contour_info(study)