def _get_optimization_history_plot(study: Study) -> "go.Figure":

    layout = go.Layout(
        title="Optimization History Plot",
        xaxis={"title": "#Trials"},
        yaxis={"title": "Objective Value"},
    )

    trials = [t for t in study.trials if t.state == TrialState.COMPLETE]

    if len(trials) == 0:
        logger.warning("Study instance does not contain trials.")
        return go.Figure(data=[], layout=layout)

    best_values = [float("inf")] if study.direction == StudyDirection.MINIMIZE else [-float("inf")]
    comp = min if study.direction == StudyDirection.MINIMIZE else max
    for trial in trials:
        trial_value = trial.value
        assert trial_value is not None  # For mypy
        best_values.append(comp(best_values[-1], trial_value))
    best_values.pop(0)
    traces = [
        go.Scatter(
            x=[t.number for t in trials],
            y=[t.value for t in trials],
            mode="markers",
            name="Objective Value",
        ),
        go.Scatter(x=[t.number for t in trials], y=best_values, name="Best Value"),
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure
def _get_intermediate_plot(study):
    # type: (Study) -> go.Figure

    layout = go.Layout(title='Intermediate Values Plot',
                       xaxis={'title': 'Step'},
                       yaxis={'title': 'Intermediate Value'},
                       showlegend=False)

    target_state = [TrialState.PRUNED, TrialState.COMPLETE, TrialState.RUNNING]
    trials = [trial for trial in study.trials if trial.state in target_state]

    if len(trials) == 0:
        logger.warning('Study instance does not contain trials.')
        return go.Figure(data=[], layout=layout)

    traces = []
    for trial in trials:
        if trial.intermediate_values:
            trace = go.Scatter(x=tuple(trial.intermediate_values.keys()),
                               y=tuple(trial.intermediate_values.values()),
                               mode='lines+markers',
                               marker={'maxdisplayed': 10},
                               name='Trial{}'.format(trial.number))
            traces.append(trace)

    if not traces:
        logger.warning(
            'You need to set up the pruning feature to utilize `plot_intermediate_values()`'
        )
        return go.Figure(data=[], layout=layout)

    figure = go.Figure(data=traces, layout=layout)

    return figure
Exemple #3
0
def _get_slice_plot(study: Study,
                    params: Optional[List[str]] = None) -> "go.Figure":

    layout = go.Layout(title="Slice Plot", )

    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]

    if len(trials) == 0:
        logger.warning("Your study does not have any completed trials.")
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is None:
        sorted_params = sorted(list(all_params))
    else:
        for input_p_name in params:
            if input_p_name not in all_params:
                raise ValueError(
                    "Parameter {} does not exist in your study.".format(
                        input_p_name))
        sorted_params = sorted(list(set(params)))

    n_params = len(sorted_params)

    if n_params == 1:
        figure = go.Figure(
            data=[_generate_slice_subplot(study, trials, sorted_params[0])],
            layout=layout)
        figure.update_xaxes(title_text=sorted_params[0])
        figure.update_yaxes(title_text="Objective Value")
        if _is_log_scale(trials, sorted_params[0]):
            figure.update_xaxes(type="log")
    else:
        figure = make_subplots(rows=1,
                               cols=len(sorted_params),
                               shared_yaxes=True)
        figure.update_layout(layout)
        showscale = True  # showscale option only needs to be specified once.
        for i, param in enumerate(sorted_params):
            trace = _generate_slice_subplot(study, trials, param)
            trace.update(marker={"showscale":
                                 showscale})  # showscale's default is True.
            if showscale:
                showscale = False
            figure.add_trace(trace, row=1, col=i + 1)
            figure.update_xaxes(title_text=param, row=1, col=i + 1)
            if i == 0:
                figure.update_yaxes(title_text="Objective Value", row=1, col=1)
            if _is_log_scale(trials, param):
                figure.update_xaxes(type="log", row=1, col=i + 1)
        if n_params > 3:
            # Ensure that each subplot has a minimum width without relying on autusizing.
            figure.update_layout(width=300 * n_params)

    return figure
def _get_intermediate_plot(study):
    # type: (Study) -> go.Figure

    layout = go.Layout(
        title="Intermediate Values Plot",
        xaxis={"title": "Step"},
        yaxis={"title": "Intermediate Value"},
        showlegend=False,
    )

    target_state = [TrialState.PRUNED, TrialState.COMPLETE, TrialState.RUNNING]
    trials = [trial for trial in study.trials if trial.state in target_state]

    if len(trials) == 0:
        logger.warning("Study instance does not contain trials.")
        return go.Figure(data=[], layout=layout)

    traces = []
    for trial in trials:
        if trial.intermediate_values:
            sorted_intermediate_values = sorted(
                trial.intermediate_values.items())
            trace = go.Scatter(
                x=tuple((x for x, _ in sorted_intermediate_values)),
                y=tuple((y for _, y in sorted_intermediate_values)),
                mode="lines+markers",
                marker={"maxdisplayed": 10},
                name="Trial{}".format(trial.number),
            )
            traces.append(trace)

    if not traces:
        logger.warning(
            "You need to set up the pruning feature to utilize `plot_intermediate_values()`"
        )
        return go.Figure(data=[], layout=layout)

    figure = go.Figure(data=traces, layout=layout)

    return figure
def _get_optimization_history_plot(study):
    # type: (Study) -> Figure

    layout = go.Layout(
        title='Optimization History Plot',
        xaxis={'title': '#Trials'},
        yaxis={'title': 'Objective Value'},
    )

    trials = [t for t in study.trials if t.state == TrialState.COMPLETE]

    if len(trials) == 0:
        logger.warning('Study instance does not contain trials.')
        return go.Figure(data=[], layout=layout)

    best_values = [
        float('inf')
    ] if study.direction == StudyDirection.MINIMIZE else [-float('inf')]
    comp = min if study.direction == StudyDirection.MINIMIZE else max
    for trial in trials:
        trial_value = trial.value
        assert trial_value is not None  # For mypy
        best_values.append(comp(best_values[-1], trial_value))
    best_values.pop(0)
    traces = [
        go.Scatter(x=[t.number for t in trials],
                   y=[t.value for t in trials],
                   mode='markers',
                   name='Objective Value'),
        go.Scatter(x=[t.number for t in trials],
                   y=best_values,
                   name='Best Value')
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure
def _get_parallel_coordinate_plot(study: Study,
                                  params: Optional[List[str]] = None
                                  ) -> "go.Figure":

    layout = go.Layout(title="Parallel Coordinate Plot", )

    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]

    if len(trials) == 0:
        logger.warning("Your study does not have any completed trials.")
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is not None:
        for input_p_name in params:
            if input_p_name not in all_params:
                ValueError("Parameter {} does not exist in your study.".format(
                    input_p_name))
        all_params = set(params)
    sorted_params = sorted(list(all_params))

    dims = [{
        "label":
        "Objective Value",
        "values":
        tuple([t.value for t in trials]),
        "range":
        (min([t.value for t in trials]), max([t.value for t in trials])),
    }]  # type: List[Dict[str, Any]]
    for p_name in sorted_params:
        values = []
        for t in trials:
            if p_name in t.params:
                values.append(t.params[p_name])
        is_categorical = False
        try:
            tuple(map(float, values))
        except (TypeError, ValueError):
            vocab = defaultdict(
                lambda: len(vocab))  # type: DefaultDict[str, int]
            values = [vocab[v] for v in values]
            is_categorical = True
        dim = {
            "label":
            p_name if len(p_name) < 20 else "{}...".format(p_name[:17]),
            "values": tuple(values),
            "range": (min(values), max(values)),
        }
        if is_categorical:
            dim["tickvals"] = list(range(len(vocab)))
            dim["ticktext"] = list(sorted(vocab.items(), key=lambda x: x[1]))
        dims.append(dim)

    traces = [
        go.Parcoords(
            dimensions=dims,
            labelangle=30,
            labelside="bottom",
            line={
                "color": dims[0]["values"],
                "colorscale": "blues",
                "colorbar": {
                    "title": "Objective Value"
                },
                "showscale": True,
                "reversescale": study.direction == StudyDirection.MINIMIZE,
            },
        )
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure
Exemple #7
0
def _get_contour_plot(study, params=None):
    # type: (Study, Optional[List[str]]) -> Figure

    layout = go.Layout(
        title='Contour Plot',
    )

    trials = [trial for trial in study.trials if trial.state == TrialState.COMPLETE]

    if len(trials) == 0:
        logger.warning('Your study does not have any completed trials.')
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is None:
        sorted_params = sorted(list(all_params))
    elif len(params) <= 1:
        logger.warning('The length of params must be greater than 1.')
        return go.Figure(data=[], layout=layout)
    else:
        for input_p_name in params:
            if input_p_name not in all_params:
                raise ValueError('Parameter {} does not exist in your study.'.format(input_p_name))
        sorted_params = sorted(list(set(params)))

    param_values_range = {}
    for p_name in sorted_params:
        values = [t.params[p_name] for t in trials if p_name in t.params]
        param_values_range[p_name] = (min(values), max(values))

    if len(sorted_params) == 2:
        x_param = sorted_params[0]
        y_param = sorted_params[1]
        sub_plots = _generate_contour_subplot(
            trials, x_param, y_param, study.direction)
        figure = go.Figure(data=sub_plots)
        figure.update_xaxes(title_text=x_param, range=param_values_range[x_param])
        figure.update_yaxes(title_text=y_param, range=param_values_range[y_param])
        if _is_log_scale(trials, x_param):
            log_range = [math.log10(p) for p in param_values_range[x_param]]
            figure.update_xaxes(range=log_range, type='log')
        if _is_log_scale(trials, y_param):
            log_range = [math.log10(p) for p in param_values_range[y_param]]
            figure.update_yaxes(range=log_range, type='log')
    else:
        figure = make_subplots(rows=len(sorted_params),
                               cols=len(sorted_params), shared_xaxes=True, shared_yaxes=True)
        showscale = True   # showscale option only needs to be specified once
        for x_i, x_param in enumerate(sorted_params):
            for y_i, y_param in enumerate(sorted_params):
                if x_param == y_param:
                    figure.add_trace(go.Scatter(), row=y_i + 1, col=x_i + 1)
                else:
                    sub_plots = _generate_contour_subplot(
                        trials, x_param, y_param, study.direction)
                    contour = sub_plots[0]
                    scatter = sub_plots[1]
                    contour.update(showscale=showscale)  # showscale's default is True
                    if showscale:
                        showscale = False
                    figure.add_trace(contour, row=y_i + 1, col=x_i + 1)
                    figure.add_trace(scatter, row=y_i + 1, col=x_i + 1)
                figure.update_xaxes(range=param_values_range[x_param],
                                    row=y_i + 1, col=x_i + 1)
                figure.update_yaxes(range=param_values_range[y_param],
                                    row=y_i + 1, col=x_i + 1)
                if _is_log_scale(trials, x_param):
                    log_range = [math.log10(p) for p in param_values_range[x_param]]
                    figure.update_xaxes(range=log_range, type='log', row=y_i + 1, col=x_i + 1)
                if _is_log_scale(trials, y_param):
                    log_range = [math.log10(p) for p in param_values_range[y_param]]
                    figure.update_yaxes(range=log_range, type='log', row=y_i + 1, col=x_i + 1)
                if x_i == 0:
                    figure.update_yaxes(title_text=y_param, row=y_i + 1, col=x_i + 1)
                if y_i == len(sorted_params) - 1:
                    figure.update_xaxes(title_text=x_param, row=y_i + 1, col=x_i + 1)

    return figure
def _get_parallel_coordinate_plot(study, params=None):
    # type: (Study, Optional[List[str]]) -> go.Figure

    layout = go.Layout(title='Parallel Coordinate Plot', )

    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]

    if len(trials) == 0:
        logger.warning('Your study does not have any completed trials.')
        return go.Figure(data=[], layout=layout)

    all_params = {p_name for t in trials for p_name in t.params.keys()}
    if params is not None:
        for input_p_name in params:
            if input_p_name not in all_params:
                ValueError('Parameter {} does not exist in your study.'.format(
                    input_p_name))
        all_params = set(params)
    sorted_params = sorted(list(all_params))

    dims = [{
        'label':
        'Objective Value',
        'values':
        tuple([t.value for t in trials]),
        'range':
        (min([t.value for t in trials]), max([t.value for t in trials]))
    }]  # type: List[Dict[str, Any]]
    for p_name in sorted_params:
        values = []
        for t in trials:
            if p_name in t.params:
                values.append(t.params[p_name])
        is_categorical = False
        try:
            tuple(map(float, values))
        except (TypeError, ValueError):
            vocab = defaultdict(
                lambda: len(vocab))  # type: DefaultDict[str, int]
            values = [vocab[v] for v in values]
            is_categorical = True
        dim = {
            'label': p_name,
            'values': tuple(values),
            'range': (min(values), max(values))
        }
        if is_categorical:
            dim['tickvals'] = list(range(len(vocab)))
            dim['ticktext'] = list(sorted(vocab.items(), key=lambda x: x[1]))
        dims.append(dim)

    traces = [
        go.Parcoords(dimensions=dims,
                     line={
                         'color':
                         dims[0]['values'],
                         'colorscale':
                         'blues',
                         'colorbar': {
                             'title': 'Objective Value'
                         },
                         'showscale':
                         True,
                         'reversescale':
                         study.direction == StudyDirection.MINIMIZE,
                     })
    ]

    figure = go.Figure(data=traces, layout=layout)

    return figure
Exemple #9
0
def plot_param_importances(study: Study,
                           evaluator: BaseImportanceEvaluator = None,
                           params: Optional[List[str]] = None) -> "go.Figure":
    """Plot hyperparameter importances.

    Example:

        The following code snippet shows how to plot hyperparameter importances.

        .. testcode::

            import optuna

            def objective(trial):
                x = trial.suggest_int("x", 0, 2)
                y = trial.suggest_float("y", -1.0, 1.0)
                z = trial.suggest_float("z", 0.0, 1.5)
                return x ** 2 + y ** 3 - z ** 4

            study = optuna.create_study(sampler=optuna.samplers.RandomSampler())
            study.optimize(objective, n_trials=100)

            optuna.visualization.plot_param_importances(study)

        .. raw:: html

            <iframe src="../_static/plot_param_importances.html"
             width="100%" height="500px" frameborder="0">
            </iframe>

    .. seealso::

        This function visualizes the results of :func:`optuna.importance.get_param_importances`.

    Args:
        study:
            An optimized study.
        evaluator:
            An importance evaluator object that specifies which algorithm to base the importance
            assessment on.
            Defaults to
            :class:`~optuna.importance._mean_decrease_impurity.MeanDecreaseImpurityImportanceEvaluator`.
        params:
            A list of names of parameters to assess.
            If :obj:`None`, all parameters that are present in all of the completed trials are
            assessed.

    Returns:
        A :class:`plotly.graph_objs.Figure` object.
    """

    _imports.check()

    layout = go.Layout(
        title="Hyperparameter Importances",
        xaxis={"title": "Feature"},
        yaxis={"title": "Importance"},
        showlegend=False,
    )

    # Importances cannot be evaluated without completed trials.
    # Return an empty figure for consistency with other visualization functions.
    trials = [
        trial for trial in study.trials if trial.state == TrialState.COMPLETE
    ]
    if len(trials) == 0:
        logger.warning("Study instance does not contain completed trials.")
        return go.Figure(data=[], layout=layout)

    importances = optuna.importance.get_param_importances(study,
                                                          evaluator=evaluator,
                                                          params=params)

    fig = go.Figure(data=[
        go.Bar(x=list(importances.keys()), y=list(importances.values()))
    ],
                    layout=layout)

    return fig