Exemple #1
0
def trace_gauge(self, fig, gridspec):
    """Trace gauge, showing the trace of the Hessian versus iteration.

    Args:
        self (cockpit.plotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Trace"

    # Check if the required data is available, else skip this instrument
    requires = ["trace"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        warnings.warn(
            "Couldn't get the required data for the " + title + " instrument",
            stacklevel=1,
        )
        return

    # Compute
    self.tracking_data["trace_all"] = self.tracking_data.trace.map(
        lambda x: sum(x) if type(x) == list else x)

    plot_args = {
        "x": "iteration",
        "y": "trace_all",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #2
0
def max_ev_gauge(self, fig, gridspec):
    """Showing the largest eigenvalue of the Hessian versus iteration.

    Args:
        self (cockpit.plotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec): GridSpec where the instrument should be
            placed.
    """
    # Plot Trace vs iteration
    title = "Max Eigenvalue"

    # Check if the required data is available, else skip this instrument
    requires = ["max_ev"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        warnings.warn(
            "Couldn't get the required data for the " + title + " instrument",
            stacklevel=1,
        )
        return

    plot_args = {
        "x": "iteration",
        "y": "max_ev",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "log",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    # part that should be plotted
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #3
0
def grad_norm_gauge(self, fig, gridspec):
    """Showing the gradient norm versus iteration.

    If the training gets stuck, due to a small
    :class:`~cockpit.quantities.UpdateSize` it can be the result of both a badly
    chosen learning rate, or from a flat plateau in the loss landscape.
    This instrument shows the gradient norm at each iteration, overlayed with an
    exponentially weighted average, and can thus distinguish these two cases.

    **Preview**

    .. image:: ../../_static/instrument_previews/GradientNorm.png
        :alt: Preview GradientNorm Gauge

    **Requires**

    The gradient norm instrument requires data from the
    :class:`~cockpit.quantities.GradNorm` quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Gradient Norm"

    # Check if the required data is available, else skip this instrument
    requires = ["GradNorm"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return

    # Compute
    self.tracking_data["GradNorm_all"] = self.tracking_data.GradNorm.map(
        lambda x: _root_sum_of_squares(x) if type(x) == list else x)

    plot_args = {
        "x": "iteration",
        "y": "GradNorm_all",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #4
0
def distance_gauge(self, fig, gridspec):
    """Showing the parameter L2-distance to the initialization versus iteration.

    Args:
        self (cockpit.plotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Distance"

    # Check if the required data is available, else skip this instrument
    requires = ["d2init", "update_size"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        warnings.warn(
            "Couldn't get the required data for the " + title + " instrument",
            stacklevel=1,
        )
        return

    # Compute
    self.tracking_data["d2init_all"] = self.tracking_data.d2init.map(
        lambda x: _root_sum_of_squares(x) if type(x) == list else x
    )
    self.tracking_data["update_size_all"] = self.tracking_data.update_size.map(
        lambda x: _root_sum_of_squares(x) if type(x) == list else x
    )

    plot_args = {
        "x": "iteration",
        "y": "d2init_all",
        "data": self.tracking_data,
        "y_scale": "linear",
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)

    ax2 = ax.twinx()
    plot_args = {
        "x": "iteration",
        "y": "update_size_all",
        "data": self.tracking_data,
        "y_scale": "linear",
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "cmap": self.cmap.reversed(),
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2.reversed(),
        "xlim": "tight",
        "ylim": None,
        "marker": ",",
    }
    create_basic_plot(**plot_args, ax=ax2)
def early_stopping_gauge(self, fig, gridspec):
    """Early Stopping gauge, showing the LHS of the stopping criterion versus iteration.

    Early stopping the training has been widely used to prevent poor generalization
    due to over-fitting. `Mahsereci et al. (2017) <https://arxiv.org/abs/1703.09580>`_
    proposed an evidence-based stopping criterion based on mini-batch statistics.
    This instruments visualizes this criterion versus iteration, overlayed
    with an exponentially weighted average. If the stopping criterion becomes
    positive, this suggests stopping the training according to

    - `Mahsereci, M., Balles, L., Lassner, C., & Hennig, P.,
      Early stopping without a validation set (2017).
      <https://arxiv.org/abs/1703.09580>`_

    **Preview**

    .. image:: ../../_static/instrument_previews/EarlyStopping.png
        :alt: Preview EarlyStopping Gauge

    **Requires**

    This instrument requires data from the :class:`~cockpit.quantities.EarlyStopping`
    quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Early stopping"

    # Check if the required data is available, else skip this instrument
    requires = ["EarlyStopping"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return

    plot_args = {
        "x": "iteration",
        "y": "EarlyStopping",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #6
0
def distance_gauge(self, fig, gridspec):
    """Distance gauge showing two different quantities related to distance.

    This instruments shows two quantities at once. Firstly, the :math:`L_2`-distance
    of the current parameters to their initialization. This describes the total distance
    that the optimization trajectory "has traveled so far" and can be seen via the
    blue-to-green dots (and the left y-axis).

    Secondly, the update sizes of individual steps are shown via the yellow-to-blue
    dots (and the right y-axis). It measure the distance that a single parameter
    update covers.

    Both quantities are overlayed with an exponentially weighted average.

    .. image:: ../../_static/instrument_previews/Distances.png
        :alt: Preview Distances Gauge

    **Requires**

    The distance instrument requires data from both, the
    :class:`~cockpit.quantities.UpdateSize` and the
    :class:`~cockpit.quantities.Distance` quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Distance"

    # Check if the required data is available, else skip this instrument
    requires = ["Distance", "UpdateSize"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return

    # Compute
    self.tracking_data["Distance_all"] = self.tracking_data.Distance.map(
        lambda x: _root_sum_of_squares(x) if type(x) == list else x)
    self.tracking_data["UpdateSize_all"] = self.tracking_data.UpdateSize.map(
        lambda x: _root_sum_of_squares(x) if type(x) == list else x)

    plot_args = {
        "x": "iteration",
        "y": "Distance_all",
        "data": self.tracking_data,
        "y_scale": "linear",
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)

    ax2 = ax.twinx()
    plot_args = {
        "x": "iteration",
        "y": "UpdateSize_all",
        "data": self.tracking_data,
        "y_scale": "linear",
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "cmap": self.cmap.reversed(),
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2.reversed(),
        "xlim": "tight",
        "ylim": None,
        "marker": ",",
    }
    create_basic_plot(**plot_args, ax=ax2)
Exemple #7
0
def performance_gauge(self, fig, gridspec):
    """Plotting train/valid accuracy vs. epoch and mini-batch loss vs. iteration.

    Args:
        self (cockpit.plotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Performance Plot"

    # Check if the required data is available, else skip this instrument
    requires = [
        "iteration", "train_accuracy", "valid_accuracy", "mini_batch_loss"
    ]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        warnings.warn(
            "Couldn't get the required data for the " + title + " instrument",
            stacklevel=1,
        )
        return

    # Mini-batch train loss
    plot_args = {
        "x": "iteration",
        "y": "mini_batch_loss",
        "data": self.tracking_data,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments2,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)

    clean_accuracies = self.tracking_data[[
        "iteration", "train_accuracy", "valid_accuracy"
    ]].dropna()

    # Train Accuracy
    plot_args = {
        "x": "iteration",
        "y": "train_accuracy",
        "data": clean_accuracies,
    }
    ax2 = ax.twinx()
    sns.lineplot(
        **plot_args,
        ax=ax2,
        label=plot_args["y"].title().replace("_", " "),
        linewidth=2,
        color=self.primary_color,
    )

    # Train Accuracy
    plot_args = {
        "x": "iteration",
        "y": "valid_accuracy",
        "data": clean_accuracies,
    }
    sns.lineplot(
        **plot_args,
        ax=ax2,
        label=plot_args["y"].title().replace("_", " "),
        linewidth=2,
        color=self.secondary_color,
    )

    # Customization
    ax2.set_ylim([0, 1])
    ax2.set_ylabel("Accuracy")
    _add_last_value_to_legend(ax2, percentage=True)
Exemple #8
0
def cabs_gauge(self, fig, gridspec):
    """CABS gauge, showing the CABS rule versus iteration.

    The batch size trades-off more accurate gradient approximations with longer
    computation. The `CABS criterion <https://arxiv.org/abs/1612.05086>`_ describes
    the optimal batch size under certain assumptions.

    The instruments shows the suggested batch size (and an exponential weighted
    average) over the course of training, according to

    - `Balles, L., Romero, J., & Hennig, P.,
      Coupling adaptive batch sizes with learning rates (2017).
      <https://arxiv.org/abs/1612.05086>`_

    **Preview**

    .. image:: ../../_static/instrument_previews/CABS.png
        :alt: Preview CABS Gauge

    **Requires**

    This instrument requires data from the :class:`~cockpit.quantities.CABS`
    quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "CABS"

    # Check if the required data is available, else skip this instrument
    requires = ["CABS"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title + " instrument",
                stacklevel=1,
            )
        return

    plot_args = {
        "x": "iteration",
        "y": "CABS",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #9
0
def max_ev_gauge(self, fig, gridspec):
    """Showing the largest eigenvalue of the Hessian versus iteration.

    The largest eigenvalue of the Hessian indicates the loss surface's sharpest
    valley. Together with the :func:`~cockpit.instruments.trace_gauge()`, which
    provides a notion of "average curvature", it can help understand the "average
    condition number" of the loss landscape at the current point. The instrument
    shows the largest eigenvalue of the Hessian versus iteration, overlayed with
    an exponentially weighted average.

    **Preview**

    .. image:: ../../_static/instrument_previews/HessMaxEV.png
        :alt: Preview HessMaxEV Gauge

    **Requires**

    The trace instrument requires data from the :class:`~cockpit.quantities.HessMaxEv`
    quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed.
    """
    # Plot Trace vs iteration
    title = "Max Eigenvalue"

    # Check if the required data is available, else skip this instrument
    requires = ["HessMaxEV"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return

    plot_args = {
        "x": "iteration",
        "y": "HessMaxEV",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "log",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    # part that should be plotted
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)

    ax.yaxis.set_minor_formatter(ticker.FormatStrFormatter("%.2g"))
Exemple #10
0
def tic_gauge(self, fig, gridspec):
    """TIC gauge, showing the TIC versus iteration.

    The TIC (either approximated via traces or using a diagonal approximation)
    describes the relation between the curvature and the gradient noise. `Recent
    work <https://arxiv.org/abs/1906.07774>`_ suggested that *at a local minimum*,
    this quantitiy can estimate the generalization gap. This instrument shows the
    TIC versus iteration, overlayed with an exponentially weighted average.

    **Preview**

    .. image:: ../../_static/instrument_previews/TIC.png
        :alt: Preview TIC Gauge

    **Requires**

    The trace instrument requires data from the :class:`~cockpit.quantities.TICDiag`
    or :class:`~cockpit.quantities.TICTrace` quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "TIC"

    if check_data(self.tracking_data, ["TICDiag"]):
        plot_args = {
            "x": "iteration",
            "y": "TICDiag",
            "data": self.tracking_data,
            "x_scale": "symlog" if self.show_log_iter else "linear",
            "y_scale": "linear",
            "cmap": self.cmap,
            "EMA": "y",
            "EMA_alpha": self.EMA_alpha,
            "EMA_cmap": self.cmap2,
            "title": title,
            "xlim": "tight",
            "ylim": None,
            "fontweight": "bold",
            "facecolor": self.bg_color_instruments,
        }
        ax = fig.add_subplot(gridspec)
        create_basic_plot(**plot_args, ax=ax)

    if check_data(self.tracking_data, ["TICTrace"]):
        if "ax" in locals():
            ax2 = ax.twinx()
        else:
            ax2 = fig.add_subplot(gridspec)
        plot_args = {
            "x": "iteration",
            "y": "TICTrace",
            "data": self.tracking_data,
            "x_scale": "symlog" if self.show_log_iter else "linear",
            "y_scale": "linear",
            "cmap": self.cmap_backup,
            "EMA": "y",
            "EMA_alpha": self.EMA_alpha,
            "EMA_cmap": self.cmap2_backup,
            "title": title,
            "xlim": "tight",
            "ylim": None,
            "fontweight": "bold",
            "facecolor": self.bg_color_instruments,
        }
        create_basic_plot(**plot_args, ax=ax2)
Exemple #11
0
def trace_gauge(self, fig, gridspec):
    """Trace gauge, showing the trace of the Hessian versus iteration.

    The trace of the hessian is the sum of its eigenvalues and thus can indicate
    the overall or average curvature of the loss landscape at the current point.
    Increasing values for the trace indicate a steeper curvature, for example, a
    narrower valley. This instrument shows the trace versus iteration, overlayed
    with an exponentially weighted average.

    **Preview**

    .. image:: ../../_static/instrument_previews/HessTrace.png
        :alt: Preview HessTrace Gauge

    **Requires**

    The trace instrument requires data from the :class:`~cockpit.quantities.HessTrace`
    quantity class.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Trace"

    # Check if the required data is available, else skip this instrument
    requires = ["HessTrace"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the required data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return

    # Compute
    self.tracking_data["HessTrace_all"] = self.tracking_data.HessTrace.map(
        lambda x: sum(x) if type(x) == list else x)

    plot_args = {
        "x": "iteration",
        "y": "HessTrace_all",
        "data": self.tracking_data,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)
Exemple #12
0
def performance_gauge(self, fig, gridspec):
    """Plotting train/valid accuracy vs. epoch and mini-batch loss vs. iteration.

    This instruments visualizes the currently most popular diagnostic metrics. It
    shows the mini-batch loss in each iteration (overlayed with an exponentially
    weighted average) as well as accuracies for both the training as well as the
    validation set. The current accuracy numbers are also shown in the legend.

    **Preview**

    .. image:: ../../_static/instrument_previews/Performance.png
        :alt: Preview Performance Gauge

    **Requires**

    This instrument visualizes quantities passed via the
    :func:`cockpit.Cockpit.log()` method.

    Args:
        self (CockpitPlotter): The cockpit plotter requesting this instrument.
        fig (matplotlib.figure.Figure): Figure of the Cockpit.
        gridspec (matplotlib.gridspec.GridSpec): GridSpec where the instrument should be
            placed
    """
    # Plot Trace vs iteration
    title = "Performance Plot"

    # Check if the required data is available, else skip this instrument
    requires = ["iteration", "Loss"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the loss data for the " + title + " instrument",
                stacklevel=1,
            )
        return

    # Mini-batch train loss
    plot_args = {
        "x": "iteration",
        "y": "Loss",
        "data": self.tracking_data,
        "EMA": "y",
        "EMA_alpha": self.EMA_alpha,
        "EMA_cmap": self.cmap2,
        "x_scale": "symlog" if self.show_log_iter else "linear",
        "y_scale": "linear",
        "cmap": self.cmap,
        "title": title,
        "xlim": "tight",
        "ylim": None,
        "fontweight": "bold",
        "facecolor": self.bg_color_instruments2,
    }
    ax = fig.add_subplot(gridspec)
    create_basic_plot(**plot_args, ax=ax)

    requires = ["iteration", "train_accuracy", "valid_accuracy"]
    plot_possible = check_data(self.tracking_data, requires)
    if not plot_possible:
        if self.debug:
            warnings.warn(
                "Couldn't get the accuracy data for the " + title +
                " instrument",
                stacklevel=1,
            )
        return
    else:
        clean_accuracies = self.tracking_data[[
            "iteration", "train_accuracy", "valid_accuracy"
        ]].dropna()

        # Train Accuracy
        plot_args = {
            "x": "iteration",
            "y": "train_accuracy",
            "data": clean_accuracies,
        }
        ax2 = ax.twinx()
        sns.lineplot(
            **plot_args,
            ax=ax2,
            label=plot_args["y"].title().replace("_", " "),
            linewidth=2,
            color=self.primary_color,
        )

        # Train Accuracy
        plot_args = {
            "x": "iteration",
            "y": "valid_accuracy",
            "data": clean_accuracies,
        }
        sns.lineplot(
            **plot_args,
            ax=ax2,
            label=plot_args["y"].title().replace("_", " "),
            linewidth=2,
            color=self.secondary_color,
        )

        # Customization
        ax2.set_ylim([0, 1])
        ax2.set_ylabel("Accuracy")
        _add_last_value_to_legend(ax2, percentage=True)