Source code for pypesto.visualize.optimization_stats

from numbers import Real
from typing import Dict, Iterable, List, Optional, Sequence, Tuple, Union

import matplotlib.axes
import matplotlib.pyplot as plt
import numpy as np

from pypesto.util import delete_nan_inf

from ..result import Result
from .clust_color import assign_colors, assign_colors_for_list
from .misc import process_result_list, process_start_indices


[docs]def optimization_run_properties_one_plot( results: Result, properties_to_plot: Optional[List[str]] = None, size: Tuple[float, float] = (18.5, 10.5), start_indices: Optional[Union[int, Iterable[int]]] = None, colors: Optional[Union[List[float], List[List[float]]]] = None, legends: Optional[Union[str, List[str]]] = None, plot_type: str = 'line', ) -> matplotlib.axes.Axes: """ Plot stats for allproperties specified in properties_to_plot on one plot. Parameters ---------- results: Optimization result obtained by 'optimize.py' or list of those properties_to_plot: Optimization run properties that should be plotted size: Figure size (width, height) in inches. Is only applied when no ax object is specified start_indices: List of integers specifying the multistarts to be plotted or int specifying up to which start index should be plotted colors: List of RGBA colors (one color per property in properties_to_plot), or single RGBA color. If not set and one result, clustering is done and colors are assigned automatically legends: Labels, one label per optimization property plot_type: Specifies plot type. Possible values: 'line' and 'hist' Returns ------- ax: The plot axes. Examples -------- optimization_properties_per_multistart( result1, properties_to_plot=['time'], colors=[.5, .9, .9, .3]) optimization_properties_per_multistart( result1, properties_to_plot=['time', 'n_grad'], colors=[[.5, .9, .9, .3], [.2, .1, .9, .5]]) """ if properties_to_plot is None: properties_to_plot = [ 'time', 'n_fval', 'n_grad', 'n_hess', 'n_res', 'n_sres', ] if colors is None: colors = assign_colors_for_list(len(properties_to_plot)) elif len(colors) == 4 and isinstance(colors[0], Real): colors = [colors] if len(colors) != len(properties_to_plot): raise ValueError( 'Number of RGBA colors should be the same as number ' 'of optimization properties to plot' ) if legends is None: legends = properties_to_plot elif not isinstance(legends, list): legends = [legends] if len(legends) != len(properties_to_plot): raise ValueError( 'Number of legends should be the same as number of ' 'optimization properties to plot' ) ax = plt.subplots()[1] fig = plt.gcf() fig.set_size_inches(*size) for idx, prop_name in enumerate(properties_to_plot): optimization_run_property_per_multistart( results, prop_name, ax, size, start_indices, colors[idx], legends[idx], plot_type, ) ax.set_ylabel("property value") ax.set_title("Optimization properties per optimization run") return ax
[docs]def optimization_run_properties_per_multistart( results: Union[Result, Sequence[Result]], properties_to_plot: Optional[List[str]] = None, size: Tuple[float, float] = (18.5, 10.5), start_indices: Optional[Union[int, Iterable[int]]] = None, colors: Optional[Union[List[float], List[List[float]]]] = None, legends: Optional[Union[str, List[str]]] = None, plot_type: str = 'line', ) -> Dict[str, plt.Subplot]: """ One plot per optimization property in properties_to_plot. Parameters ---------- results: Optimization result obtained by 'optimize.py' or list of those properties_to_plot: Optimization run properties that should be plotted size: Figure size (width, height) in inches. Is only applied when no ax object is specified start_indices: List of integers specifying the multistarts to be plotted or int specifying up to which start index should be plotted colors: List of RGBA colors (one color per result in results), or single RGBA color. If not set and one result, clustering is done and colors are assigned automatically legends: Labels for line plots, one label per result object plot_type: Specifies plot type. Possible values: 'line' and 'hist' Returns ------- ax: The plot axes. Examples -------- optimization_properties_per_multistart( result1, properties_to_plot=['time'], colors=[.5, .9, .9, .3]) optimization_properties_per_multistart( [result1, result2], properties_to_plot=['time'], colors=[[.5, .9, .9, .3], [.2, .1, .9, .5]]) optimization_properties_per_multistart( result1, properties_to_plot=['time', 'n_grad'], colors=[.5, .9, .9, .3]) optimization_properties_per_multistart( [result1, result2], properties_to_plot=['time', 'n_fval'], colors=[[.5, .9, .9, .3], [.2, .1, .9, .5]]) """ if properties_to_plot is None: properties_to_plot = [ 'time', 'n_fval', 'n_grad', 'n_hess', 'n_res', 'n_sres', ] num_subplot = len(properties_to_plot) # compute, how many rows and columns we need for the subplots num_row = int(np.round(np.sqrt(num_subplot))) num_col = int(np.ceil(num_subplot / num_row)) fig, axes = plt.subplots(num_row, num_col, squeeze=False) fig.set_size_inches(*size) for ax in axes.flat[num_subplot:]: ax.remove() axes = dict(zip(range(num_subplot), axes.flat)) for idx, prop_name in enumerate(properties_to_plot): ax = axes[idx] optimization_run_property_per_multistart( results, prop_name, ax, size, start_indices, colors, legends, plot_type, ) return axes
[docs]def optimization_run_property_per_multistart( results: Union[Result, Sequence[Result]], opt_run_property: str, axes: Optional[matplotlib.axes.Axes] = None, size: Tuple[float, float] = (18.5, 10.5), start_indices: Optional[Union[int, Iterable[int]]] = None, colors: Optional[Union[List[float], List[List[float]]]] = None, legends: Optional[Union[str, List[str]]] = None, plot_type: str = 'line', ) -> matplotlib.axes.Axes: """ Plot stats for an optimization run property specified by opt_run_property. It is possible to plot a histogram or a line plot. In a line plot, on the x axis are the numbers of the multistarts, where the multistarts are ordered with respect to a function value. On the y axis of the line plot the value of the corresponding parameter for each multistart is displayed. Parameters ---------- opt_run_property: optimization run property to plot. One of the 'time', 'n_fval', 'n_grad', 'n_hess', 'n_res', 'n_sres' results: Optimization result obtained by 'optimize.py' or list of those axes: Axes object to use size: Figure size (width, height) in inches. Is only applied when no ax object is specified start_indices: List of integers specifying the multistarts to be plotted or int specifying up to which start index should be plotted colors: List of RGBA colors (one color per result in results), or single RGBA color. If not set and one result, clustering is done and colors are assigned automatically legends: Labels for line plots, one label per result object plot_type: Specifies plot type. Possible values: 'line', 'hist', 'both' Returns ------- axes: The plot axes. """ supported_properties = { 'time': 'Wall-clock time (seconds)', 'n_fval': 'Number of function evaluations', 'n_grad': 'Number of gradient evaluations', 'n_hess': 'Number of Hessian evaluations', 'n_res': 'Number of residuals evaluations', 'n_sres': 'Number of residual sensitivity evaluations', } if opt_run_property not in supported_properties: raise ValueError( "Wrong value of opt_run_property. Only the following " "values are allowed: 'time', 'n_fval', 'n_grad', " "'n_hess', 'n_res', 'n_sres'" ) # parse input (results, colors, legends) = process_result_list(results, colors, legends) # axes if axes is None: ncols = 2 if plot_type == 'both' else 1 fig, axes = plt.subplots(1, ncols) fig.set_size_inches(*size) fig.suptitle( f'{supported_properties[opt_run_property]} per optimizer run' ) else: axes.set_title( f'{supported_properties[opt_run_property]} per optimizer run' ) # loop over results for j, result in enumerate(results): if plot_type == 'both': axes[0] = stats_lowlevel( result, opt_run_property, supported_properties[opt_run_property], axes[0], start_indices, colors[j], legends[j], ) axes[1] = stats_lowlevel( result, opt_run_property, supported_properties[opt_run_property], axes[1], start_indices, colors[j], legends[j], plot_type='hist', ) else: axes = stats_lowlevel( result, opt_run_property, supported_properties[opt_run_property], axes, start_indices, colors[j], legends[j], plot_type, ) if sum((legend is not None for legend in legends)) > 0: if plot_type == 'both': for ax in axes: ax.legend() else: axes.legend() return axes
def stats_lowlevel( result: Result, property_name: str, axis_label: str, ax: matplotlib.axes.Axes, start_indices: Optional[Union[int, Iterable[int]]] = None, color: Union[str, List[float], List[List[float]]] = 'C0', legend: Optional[str] = None, plot_type: str = 'line', ): """ Plot values of the optimization run property across different multistarts. Parameters ---------- result: Optimization result obtained by 'optimize.py' property_name: name of the optimization result property which value should be plotted axis_label: Label for the y axis of the line plot or x axis of the histogram ax: Axes object to use start_indices: List of integers specifying the multistarts to be plotted or int specifying up to which start index should be plotted color: List of RGBA colors (length equal to the number of multistarts), or single color, defined by a string or RGBA list If not set, then for the line plot clustering is done and colors are assigned automatically legend: Label describing the result plot_type: Specifies plot type. Possible values: 'line' and 'hist' Returns ------- ax: The plot axes. """ fvals = result.optimize_result.fval values = [res[property_name] for res in result.optimize_result.list] values, fvals = delete_nan_inf(fvals, values) if start_indices is not None: start_indices = process_start_indices(result, start_indices) values = values[start_indices] fvals = fvals[start_indices] n_starts = len(values) # assign colors colors = assign_colors(vals=fvals, colors=color, balance_alpha=False) # sort TODO: issue # 378 sorted_indices = sorted(range(n_starts), key=lambda j: fvals[j]) values = values[sorted_indices] if plot_type == 'line': # plot line ax.plot(range(n_starts), values, color=[0.7, 0.7, 0.7, 0.6]) # plot points for i, v in enumerate(values): if i == 0: tmp_legend = legend else: tmp_legend = None ax.scatter(i, v, color=colors[i], marker='o', label=tmp_legend) ax.set_xlabel('Ordered optimizer run') ax.set_ylabel(axis_label) else: ax.hist(values, color=color, bins='auto', label=legend) ax.set_xlabel(axis_label) ax.set_ylabel('Number of multistarts') return ax