Module easyagents.callbacks.plot
View Source
from typing import Optional, List, Tuple, Union, Dict import easyagents.core as core import easyagents.backends.core import base64 import matplotlib.pyplot as plt import numpy as np import imageio import math import gym import os.path # avoid "double rendering" of the final jupyter output on_play_end_clear_jupyter_display: bool = True on_train_end_clear_jupyter_display: bool = True # check if we are running in Jupyter, if so interactive plotting must be handled differently # (in order to get plot updates during training) _is_jupyter_active = False try: # noinspection PyUnresolvedReferences from IPython import get_ipython # noinspection PyUnresolvedReferences from IPython.display import display, clear_output # noinspection PyUnresolvedReferences from IPython.display import HTML shell = get_ipython().__class__.__name__ if shell == 'ZMQInteractiveShell': _is_jupyter_active = True else: # noinspection PyPackageRequirements import google.colab _is_jupyter_active = True except ImportError: pass class _PreProcess(core._PreProcessCallback): """Initializes the matplotlib agent_context.pyplot.figure""" def _setup(self, agent_context: core.AgentContext): # create figure / remove all existing axes from previous calls to train/play pyc = agent_context.pyplot pyc.is_jupyter_active = _is_jupyter_active if pyc.figure is None: pyc.figure = plt.figure("_EasyAgents", figsize=pyc.figsize) for ax in pyc.figure.axes: pyc.figure.delaxes(ax) def on_play_begin(self, agent_context: core.AgentContext): # play_begin is also called at the start of a policy evaluation if agent_context.is_play: self._setup(agent_context=agent_context) def on_train_begin(self, agent_context: core.AgentContext): self._setup(agent_context=agent_context) class _PostProcess(core._PostProcessCallback): """Redraws the plots int the matplotlib agent_context.figure. In jupyter the plots are only refreshed once per second. """ def __init__(self): self._call_jupyter_display: bool self._reset() def _clear_jupyter_plots(self, agent_context: core.AgentContext, wait=True): """Clears the content in the current jupyter output cell. NoOp if not in jupyter or no plot output. Args: wait: Wait to clear the output until new output is available to replace it. """ # don't clear the jupyter output if no plot is present, may clear the log output otherwise if agent_context.pyplot.is_jupyter_active and self._plot_exists(agent_context): clear_output(wait=wait) def _display_plots(self, agent_context: core.AgentContext): """Fixes the layout of multiple subplots and refreshs the display.""" pyc = agent_context.pyplot if self._plot_exists(agent_context): count = len(pyc.figure.axes) rows = math.ceil(count / pyc.max_columns) columns = math.ceil(count / rows) for i in range(count): pyc.figure.axes[i].change_geometry(rows, columns, i + 1) pyc.figure.tight_layout() if pyc.is_jupyter_active: self._clear_jupyter_plots(agent_context) if self._call_jupyter_display: # noinspection PyTypeChecker display(pyc.figure) self._call_jupyter_display = True else: plt.pause(0.01) def _plot_exists(self, agent_context: core.AgentContext): """Yields true if at least 1 jupyter plot exists.""" pyc = agent_context.pyplot count = len(pyc.figure.axes) result = count > 0 return result def _reset(self): self._call_jupyter_display = False def on_play_begin(self, agent_context: core.AgentContext): if agent_context.is_play: self._reset() def on_train_begin(self, agent_context: core.AgentContext): self._reset() def on_play_episode_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE): self._display_plots(agent_context) def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): if agent_context._is_plot_ready(core.PlotType.PLAY_STEP): self._display_plots(agent_context) def on_play_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.TRAIN_EVAL): self._display_plots(agent_context) if agent_context.is_play: self._display_plots(agent_context) if on_play_end_clear_jupyter_display: self._clear_jupyter_plots(agent_context, wait=False) def on_train_end(self, agent_context: core.AgentContext): self._display_plots(agent_context) if on_train_end_clear_jupyter_display: self._clear_jupyter_plots(agent_context, wait=False) def on_train_iteration_begin(self, agent_context: core.AgentContext): # display initial evaluation before training starts. if agent_context.train.iterations_done_in_training == 0 and \ agent_context._is_plot_ready(core.PlotType.TRAIN_EVAL): self._display_plots(agent_context) def on_train_iteration_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.TRAIN_ITERATION): self._display_plots(agent_context) # noinspection DuplicatedCode class _PlotCallback(core.AgentCallback): """Base class of plyplot callbacks generating a plot after a trained iteration or an episode played. Attributes: axes: the subplot to plot onto """ def __init__(self, plot_type: core.PlotType): """Base class of plyplot callbacks generating a plot after a trained iteration or an episode played. Args: plot_type: point in time when the plot is updated """ self.axes = None self.axes_color: str = 'grey' self._plot_type: core.PlotType = plot_type def _create_subplot(self, agent_context: core.AgentContext): if self.axes is None: pyc = agent_context.pyplot pyc._created_subplots = pyc._created_subplots | self._plot_type count = len(pyc.figure.axes) + 1 rows = math.ceil(count / pyc.max_columns) columns = math.ceil(count / rows) self.axes = pyc.figure.add_subplot(rows, columns, count) self.plot_axes(xlim=(0, 1), ylabel='', xlabel='') def _is_nan(self, values: Optional[List[float]]): """yields true if all values are equal to nan. yields false if values is None or empty.""" result = False if values and all(isinstance(v, float) for v in values): result = all(math.isnan(v) for v in values) return result def _refresh_subplot(self, agent_context: core.AgentContext, plot_type: core.PlotType): """Sets this axes active and calls plot if this plot callback is registered on at least 1 plot out of plot_type.""" assert self.axes is not None plot_type = plot_type & self._plot_type if agent_context._is_plot_ready(plot_type): pyc = agent_context.pyplot if not pyc.is_jupyter_active: plt.figure(pyc.figure.number) if plt.gcf() is pyc.figure: plt.sca(self.axes) self.plot(agent_context, plot_type) def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla() def on_play_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.PLAY_EPISODE | core.PlotType.PLAY_STEP)) != core.PlotType.NONE: self._create_subplot(agent_context) def on_play_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_EVAL) def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE) def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP) def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context) def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION) def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): """Plots a graph on the self.axes object. Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call. """ pass def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale) def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color) def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color) def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01) # noinspection DuplicatedCode class Actions(_PlotCallback): def __init__(self, num_steps_between_plot=100): """Plots a histogram of the actions taken during play or during the last evaluation period. Args: num_steps_between_plot: num of steps to play before plot is updated. """ super().__init__(plot_type=core.PlotType.PLAY_STEP | core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL) assert num_steps_between_plot > 0 self._actions: List[float] = [] self._num_steps_between_plot = num_steps_between_plot def _reset(self): self._actions: List[float] = [] def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset() def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset() def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): try: pc = agent_context.play is_plot = True xlabel = 'actions' if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: xlabel = 'actions taken during last evaluation period' if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: is_plot = (pc.steps_done_in_episode % self._num_steps_between_plot == 0) if is_plot: self.clear_plot(agent_context) self.plot_axes(xlabel=xlabel, ylabel='count') self.axes.hist(pc.actions.values()) except: self.plot_text(f'Failed to create the actions histogram.\n') class Clear(core.AgentCallback): """Configures the clearing of plots in the jupyter output cell after calls to train or play.""" def __init__(self, on_play: bool = True, on_train: bool = True): """Define the cell clearing behaviour after agent.train and agent.play. Args: on_play: if set the output cell is cleared after agent.play if a plot exists on_train: if set the output cell is cleared after agent.train if a plot exists """ self._on_play: bool = on_play self._on_train: bool = on_train on_play_end_clear_jupyter_display = self._on_play on_train_end_clear_jupyter_display = self._on_train def on_play_begin(self, agent_context: core.AgentContext): global on_play_end_clear_jupyter_display on_play_end_clear_jupyter_display = self._on_play def on_train_begin(self, agent_context: core.AgentContext): global on_train_end_clear_jupyter_display on_train_end_clear_jupyter_display = self._on_train class Loss(_PlotCallback): def __init__(self, yscale: str = 'symlog', ylim: Optional[Tuple[float, float]] = None): """Plots the loss resulting from each iterations policy training. Hints: o for actro-critic agents the loss from training the actor- and critic-networks are plotted along with the total loss. Args: yscale: scale of the y-axes ('linear', 'symlog',...) ylim: (min,max) for the y-axes """ super().__init__(plot_type=core.PlotType.TRAIN_ITERATION) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): ac = agent_context tc = ac.train xvalues = list(tc.loss.keys()) self.clear_plot(agent_context) lossvalues = list(tc.loss.values()) if self._is_nan(lossvalues): self.plot_text('no loss data available') else: self.plot_axes(xlim=(0, tc.episodes_done_in_training), xlabel='episodes trained', ylim=self.ylim, ylabel='loss', yscale=self.yscale) if isinstance(tc, core.PpoTrainContext): acc: core.PpoTrainContext = tc self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.actor_loss.values()), color='g', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.critic_loss.values()), color='b') self.axes.legend(('total', 'actor', 'critic')) else: self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo') class Rewards(_PlotCallback): def __init__(self, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Plots the sum of rewards observed during policy evaluation. Args: yscale: scale of the y-axes ('linear', 'symlog',...) ylim: (min,max) for the y-axes """ super().__init__(core.PlotType.TRAIN_ITERATION | core.PlotType.TRAIN_EVAL | core.PlotType.PLAY_EPISODE) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'sum of rewards' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_rewards.keys()) yvalues = list(tc.eval_rewards.values()) ylabel = 'Ø sum of rewards' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.sum_of_rewards.keys()) yvalues = list(pc.sum_of_rewards.values()) if xvalues: self.plot_subplot(agent_context, color='green', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel) class State(_PlotCallback): """Renders the gym state as a plot to the pyplot figure using gym.render('rgb_array'). During training only the last state of the last game evaluation is plotted. During play all states are plotted. """ def __init__(self, mode='rgb_array'): """ Args: mode: the render mode passed to gym.render(), yielding an rgb_array """ super().__init__(plot_type=core.PlotType.PLAY_STEP | core.PlotType.TRAIN_EVAL) self._render_mode = mode def _plot_rgb_array(self, agent_context: core.AgentContext, rgb_array: np.ndarray): """Renders rgb_array to the current subplot.""" assert rgb_array is not None ax = self.axes xlabel = '' if agent_context.is_eval: xlabel = "'done state' of last evaluation episode" ax.imshow(rgb_array) ax.set_xlabel(xlabel) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color) # noinspection PyArgumentList,DuplicatedCode def _render_to_rgb_array(self, gym_env: gym.Env, mode: str) -> np.ndarray: """ calls gym_env.render(mode) and validates the return value to be a numpy rgb array throws an exception if not an rgb array Returns: numpy rgb array """ result = gym_env.render(mode=mode) assert result is not None, f'gym_env.render(mode={mode}) yielded None' assert isinstance(result, np.ndarray), f'gym_env.render(mode={mode}) did not yield a numpy.ndarray.' assert result.min() >= 0, f'gym_env.render(mode={mode}) contains negative values => not an rgb array' assert result.max() <= 255, f'gym_env.render(mode={mode}) contains values > 255 => not an rgb array' assert len(result.shape) == 3, f'gym_env.render(mode={mode}) shape is not of the form (x,y,n)' assert result.shape[2] == 3 or result.shape[2] == 4, \ f'gym_env.render(mode={mode}) shape is not of the form (x,y,3|4)' return result def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): self.clear_plot(agent_context) try: rgb_array: np.ndarray = self._render_to_rgb_array(agent_context.play.gym_env, self._render_mode) self._plot_rgb_array(agent_context, rgb_array) except: self.plot_text(f'gym.Env.render(mode="{self._render_mode}") failed:\n') class Steps(_PlotCallback): def __init__(self, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Plots the step counts observed during policy evaluation. Args: yscale: scale of the y-axes ('linear','log') ylim: (min,max) for the y-axes """ super().__init__(core.PlotType.TRAIN_ITERATION | core.PlotType.TRAIN_EVAL | core.PlotType.PLAY_EPISODE) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'steps' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_steps.keys()) yvalues = list(tc.eval_steps.values()) ylabel = 'Ø steps' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.actions.keys()) yvalues = [len(pc.actions[episode]) for episode in pc.actions.keys()] self.plot_subplot(agent_context, color='blue', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel) class StepRewards(_PlotCallback): def __init__(self, num_steps_between_plot=100): """Plots the sum of rewards up to the current step during play or at the end of an evaluation period. Args: num_steps_between_plot: num of steps to play before plot is updated. """ super().__init__(core.PlotType.PLAY_STEP | core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL) assert num_steps_between_plot > 0 self._xy_values: Dict[int, Tuple[List[int], List[float]]] = dict() self._xmax: int = 0 self._num_steps_between_plot = num_steps_between_plot def _replot(self, agent_context: core.AgentContext): if self._xmax >= 1: self.clear_plot(agent_context) xlabel = 'steps played' if agent_context.is_eval: xlabel = 'steps taken during last evaluation period' self.plot_axes(xlim=(1, self._xmax), ylabel='sum of rewards', xlabel=xlabel) xy_values = list(self._xy_values.values()) xlast, _ = xy_values[-1] for xvalues, yvalues in xy_values: pause = (xvalues == xlast) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=None, marker='', pause=pause) def _reset(self): self._xy_values = dict() self._xmax = 0 def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset() def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset() def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): pc = agent_context.play if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: episode = pc.episodes_done + 1 if episode not in self._xy_values: self._xy_values[episode] = ([], []) xvalues, yvalues = self._xy_values[episode] xvalues.append(pc.steps_done_in_episode) yvalues.append(pc.sum_of_rewards[episode]) if pc.steps_done_in_episode > self._xmax: self._xmax = pc.steps_done_in_episode if (episode == 1 and pc.steps_done == 1) or (pc.steps_done % self._num_steps_between_plot) == 0: self._replot(agent_context) if plot_type & core.PlotType.PLAY_EPISODE != core.PlotType.NONE: self._replot(agent_context) if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: self._xmax = max([len(step_rewards) for step_rewards in pc.rewards.values()]) for episode in pc.rewards.keys(): step_rewards = pc.rewards[episode] xvalues = list(range(1, len(step_rewards) + 1)) yvalues = [] for reward in step_rewards: old_sum = yvalues[-1] if len(yvalues) > 0 else 0 yvalues.append(old_sum + reward) self._xy_values[episode] = (xvalues, yvalues) self._replot(agent_context) class ToMovie(core._PostProcessCallback): """Plots the pyplot figure to an mp4 file Attributes: fps: frame per seconds filepath: the filepath of the mp4 file. """ def __init__(self, fps: Optional[int] = None, filepath: str = None): """Writes the ploted graphs and images to the mp4 / gif file given by filepath. if filepath ends in '.gif' an animated gif is created. Args: fps: frames per second filepath: the filepath of the mp4 or gif file file. If None the file is written to a temp file. """ super().__init__() self.fps = fps self._is_filepath_set = filepath is not None self.filepath = filepath if not self._is_filepath_set: self.filepath = easyagents.backends.core._get_temp_path() if (not self._is_animated_gif()) and (not self.filepath.lower().endswith('.mp4')): self.filepath = self.filepath + '.mp4' self._video = imageio.get_writer(self.filepath, fps=fps) if fps else imageio.get_writer(self.filepath) def _close(self, agent_context: core.AgentContext): """closes the mp4 file and displays it in jupyter cell (if in a jupyter notebook)""" self._video.close() self._video = None if agent_context.pyplot.is_jupyter_active: with open(self.filepath, 'rb') as f: video = f.read() b64 = base64.b64encode(video) if not self._is_filepath_set: os.remove(self.filepath) width = 640 height = 480 if self._is_animated_gif(): result = ''' <img src="data:image/gif;base64,{2}" alt="easyagents.plot" width={0}/> '''.format(width, height, b64.decode()) else: result = ''' <video width="{0}" height="{1}" controls> <source src="data:video/mp4;base64,{2}" type="video/mp4"> Your browser does not support the video tag. </video>'''.format(width, height, b64.decode()) result = HTML(result) # noinspection PyTypeChecker clear_output(wait=True) # noinspection PyTypeChecker display(result) def _get_rgb_array(self, agent_context: core.AgentContext) -> np.ndarray: """Yields an rgb array representing the current content of the subplots.""" pyc = agent_context.pyplot pyc.figure.canvas.draw() result = np.frombuffer(pyc.figure.canvas.tostring_rgb(), dtype='uint8') result = result.reshape(pyc.figure.canvas.get_width_height()[::-1] + (3,)) return result def _is_animated_gif(self): return self.filepath.lower().endswith('.gif') def _write_figure_to_video(self, agent_context: core.AgentContext): """Appends the current pyplot figure to the video. if an exception occures no frame is added. """ try: rgb_array = self._get_rgb_array(agent_context) self._video.append_data(rgb_array) except: pass def on_play_episode_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL): self._write_figure_to_video(agent_context) def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): if agent_context._is_plot_ready(core.PlotType.PLAY_STEP): self._write_figure_to_video(agent_context) def on_train_iteration_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.TRAIN_ITERATION): self._write_figure_to_video(agent_context) def on_play_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE): self._close(agent_context) def on_train_end(self, agent_context: core.AgentContext): self._close(agent_context)
Variables
on_play_end_clear_jupyter_display
on_train_end_clear_jupyter_display
shell
Classes
Actions
class Actions( num_steps_between_plot=100 )
Base class of plyplot callbacks generating a plot after a trained iteration or an episode played.
Attributes: axes: the subplot to plot onto
View Source
class Actions(_PlotCallback): def __init__(self, num_steps_between_plot=100): """Plots a histogram of the actions taken during play or during the last evaluation period. Args: num_steps_between_plot: num of steps to play before plot is updated. """ super().__init__(plot_type=core.PlotType.PLAY_STEP | core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL) assert num_steps_between_plot > 0 self._actions: List[float] = [] self._num_steps_between_plot = num_steps_between_plot def _reset(self): self._actions: List[float] = [] def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset() def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset() def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): try: pc = agent_context.play is_plot = True xlabel = 'actions' if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: xlabel = 'actions taken during last evaluation period' if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: is_plot = (pc.steps_done_in_episode % self._num_steps_between_plot == 0) if is_plot: self.clear_plot(agent_context) self.plot_axes(xlabel=xlabel, ylabel='count') self.axes.hist(pc.actions.values()) except: self.plot_text(f'Failed to create the actions histogram.\n')
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset()
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset()
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): try: pc = agent_context.play is_plot = True xlabel = 'actions' if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: xlabel = 'actions taken during last evaluation period' if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: is_plot = (pc.steps_done_in_episode % self._num_steps_between_plot == 0) if is_plot: self.clear_plot(agent_context) self.plot_axes(xlabel=xlabel, ylabel='count') self.axes.hist(pc.actions.values()) except: self.plot_text(f'Failed to create the actions histogram.\n')
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
Clear
class Clear( on_play: bool = True, on_train: bool = True )
Configures the clearing of plots in the jupyter output cell after calls to train or play.
View Source
class Clear(core.AgentCallback): """Configures the clearing of plots in the jupyter output cell after calls to train or play.""" def __init__(self, on_play: bool = True, on_train: bool = True): """Define the cell clearing behaviour after agent.train and agent.play. Args: on_play: if set the output cell is cleared after agent.play if a plot exists on_train: if set the output cell is cleared after agent.train if a plot exists """ self._on_play: bool = on_play self._on_train: bool = on_train on_play_end_clear_jupyter_display = self._on_play on_train_end_clear_jupyter_display = self._on_train def on_play_begin(self, agent_context: core.AgentContext): global on_play_end_clear_jupyter_display on_play_end_clear_jupyter_display = self._on_play def on_train_begin(self, agent_context: core.AgentContext): global on_train_end_clear_jupyter_display on_train_end_clear_jupyter_display = self._on_train
Ancestors (in MRO)
- easyagents.core.AgentCallback
- abc.ABC
Methods
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): global on_play_end_clear_jupyter_display on_play_end_clear_jupyter_display = self._on_play
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: AgentContext): """Called once before exiting an agent.play() call (during play or eval, but not during train)"""
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: AgentContext): """Called once after an episode is done or stopped (during play or eval, but not during train)."""
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """Called once after a step is completed in the current episode (during play or eval, but not during train)."""
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): global on_train_end_clear_jupyter_display on_train_end_clear_jupyter_display = self._on_train
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: AgentContext): """Called once after the current iteration is completed"""
Loss
class Loss( yscale: str = 'symlog', ylim: Union[Tuple[float, float], NoneType] = None )
Base class of plyplot callbacks generating a plot after a trained iteration or an episode played.
Attributes: axes: the subplot to plot onto
View Source
class Loss(_PlotCallback): def __init__(self, yscale: str = 'symlog', ylim: Optional[Tuple[float, float]] = None): """Plots the loss resulting from each iterations policy training. Hints: o for actro-critic agents the loss from training the actor- and critic-networks are plotted along with the total loss. Args: yscale: scale of the y-axes ('linear', 'symlog',...) ylim: (min,max) for the y-axes """ super().__init__(plot_type=core.PlotType.TRAIN_ITERATION) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): ac = agent_context tc = ac.train xvalues = list(tc.loss.keys()) self.clear_plot(agent_context) lossvalues = list(tc.loss.values()) if self._is_nan(lossvalues): self.plot_text('no loss data available') else: self.plot_axes(xlim=(0, tc.episodes_done_in_training), xlabel='episodes trained', ylim=self.ylim, ylabel='loss', yscale=self.yscale) if isinstance(tc, core.PpoTrainContext): acc: core.PpoTrainContext = tc self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.actor_loss.values()), color='g', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.critic_loss.values()), color='b') self.axes.legend(('total', 'actor', 'critic')) else: self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo')
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.PLAY_EPISODE | core.PlotType.PLAY_STEP)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_EVAL)
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): ac = agent_context tc = ac.train xvalues = list(tc.loss.keys()) self.clear_plot(agent_context) lossvalues = list(tc.loss.values()) if self._is_nan(lossvalues): self.plot_text('no loss data available') else: self.plot_axes(xlim=(0, tc.episodes_done_in_training), xlabel='episodes trained', ylim=self.ylim, ylabel='loss', yscale=self.yscale) if isinstance(tc, core.PpoTrainContext): acc: core.PpoTrainContext = tc self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.actor_loss.values()), color='g', pause=False) self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=list(acc.critic_loss.values()), color='b') self.axes.legend(('total', 'actor', 'critic')) else: self.plot_values(agent_context=ac, xvalues=xvalues, yvalues=lossvalues, color='indigo')
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
Rewards
class Rewards( yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Base class of plyplot callbacks generating a plot after a trained iteration or an episode played.
Attributes: axes: the subplot to plot onto
View Source
class Rewards(_PlotCallback): def __init__(self, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Plots the sum of rewards observed during policy evaluation. Args: yscale: scale of the y-axes ('linear', 'symlog',...) ylim: (min,max) for the y-axes """ super().__init__(core.PlotType.TRAIN_ITERATION | core.PlotType.TRAIN_EVAL | core.PlotType.PLAY_EPISODE) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'sum of rewards' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_rewards.keys()) yvalues = list(tc.eval_rewards.values()) ylabel = 'Ø sum of rewards' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.sum_of_rewards.keys()) yvalues = list(pc.sum_of_rewards.values()) if xvalues: self.plot_subplot(agent_context, color='green', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel)
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.PLAY_EPISODE | core.PlotType.PLAY_STEP)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_EVAL)
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'sum of rewards' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_rewards.keys()) yvalues = list(tc.eval_rewards.values()) ylabel = 'Ø sum of rewards' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.sum_of_rewards.keys()) yvalues = list(pc.sum_of_rewards.values()) if xvalues: self.plot_subplot(agent_context, color='green', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel)
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
State
class State( mode='rgb_array' )
Renders the gym state as a plot to the pyplot figure using gym.render('rgb_array').
During training only the last state of the last game evaluation is plotted. During play all states are plotted.
View Source
class State(_PlotCallback): """Renders the gym state as a plot to the pyplot figure using gym.render('rgb_array'). During training only the last state of the last game evaluation is plotted. During play all states are plotted. """ def __init__(self, mode='rgb_array'): """ Args: mode: the render mode passed to gym.render(), yielding an rgb_array """ super().__init__(plot_type=core.PlotType.PLAY_STEP | core.PlotType.TRAIN_EVAL) self._render_mode = mode def _plot_rgb_array(self, agent_context: core.AgentContext, rgb_array: np.ndarray): """Renders rgb_array to the current subplot.""" assert rgb_array is not None ax = self.axes xlabel = '' if agent_context.is_eval: xlabel = "'done state' of last evaluation episode" ax.imshow(rgb_array) ax.set_xlabel(xlabel) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color) # noinspection PyArgumentList,DuplicatedCode def _render_to_rgb_array(self, gym_env: gym.Env, mode: str) -> np.ndarray: """ calls gym_env.render(mode) and validates the return value to be a numpy rgb array throws an exception if not an rgb array Returns: numpy rgb array """ result = gym_env.render(mode=mode) assert result is not None, f'gym_env.render(mode={mode}) yielded None' assert isinstance(result, np.ndarray), f'gym_env.render(mode={mode}) did not yield a numpy.ndarray.' assert result.min() >= 0, f'gym_env.render(mode={mode}) contains negative values => not an rgb array' assert result.max() <= 255, f'gym_env.render(mode={mode}) contains values > 255 => not an rgb array' assert len(result.shape) == 3, f'gym_env.render(mode={mode}) shape is not of the form (x,y,n)' assert result.shape[2] == 3 or result.shape[2] == 4, \ f'gym_env.render(mode={mode}) shape is not of the form (x,y,3|4)' return result def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): self.clear_plot(agent_context) try: rgb_array: np.ndarray = self._render_to_rgb_array(agent_context.play.gym_env, self._render_mode) self._plot_rgb_array(agent_context, rgb_array) except: self.plot_text(f'gym.Env.render(mode="{self._render_mode}") failed:\n')
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.PLAY_EPISODE | core.PlotType.PLAY_STEP)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_EVAL)
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): self.clear_plot(agent_context) try: rgb_array: np.ndarray = self._render_to_rgb_array(agent_context.play.gym_env, self._render_mode) self._plot_rgb_array(agent_context, rgb_array) except: self.plot_text(f'gym.Env.render(mode="{self._render_mode}") failed:\n')
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
StepRewards
class StepRewards( num_steps_between_plot=100 )
Base class of plyplot callbacks generating a plot after a trained iteration or an episode played.
Attributes: axes: the subplot to plot onto
View Source
class StepRewards(_PlotCallback): def __init__(self, num_steps_between_plot=100): """Plots the sum of rewards up to the current step during play or at the end of an evaluation period. Args: num_steps_between_plot: num of steps to play before plot is updated. """ super().__init__(core.PlotType.PLAY_STEP | core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL) assert num_steps_between_plot > 0 self._xy_values: Dict[int, Tuple[List[int], List[float]]] = dict() self._xmax: int = 0 self._num_steps_between_plot = num_steps_between_plot def _replot(self, agent_context: core.AgentContext): if self._xmax >= 1: self.clear_plot(agent_context) xlabel = 'steps played' if agent_context.is_eval: xlabel = 'steps taken during last evaluation period' self.plot_axes(xlim=(1, self._xmax), ylabel='sum of rewards', xlabel=xlabel) xy_values = list(self._xy_values.values()) xlast, _ = xy_values[-1] for xvalues, yvalues in xy_values: pause = (xvalues == xlast) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=None, marker='', pause=pause) def _reset(self): self._xy_values = dict() self._xmax = 0 def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset() def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset() def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): pc = agent_context.play if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: episode = pc.episodes_done + 1 if episode not in self._xy_values: self._xy_values[episode] = ([], []) xvalues, yvalues = self._xy_values[episode] xvalues.append(pc.steps_done_in_episode) yvalues.append(pc.sum_of_rewards[episode]) if pc.steps_done_in_episode > self._xmax: self._xmax = pc.steps_done_in_episode if (episode == 1 and pc.steps_done == 1) or (pc.steps_done % self._num_steps_between_plot) == 0: self._replot(agent_context) if plot_type & core.PlotType.PLAY_EPISODE != core.PlotType.NONE: self._replot(agent_context) if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: self._xmax = max([len(step_rewards) for step_rewards in pc.rewards.values()]) for episode in pc.rewards.keys(): step_rewards = pc.rewards[episode] xvalues = list(range(1, len(step_rewards) + 1)) yvalues = [] for reward in step_rewards: old_sum = yvalues[-1] if len(yvalues) > 0 else 0 yvalues.append(old_sum + reward) self._xy_values[episode] = (xvalues, yvalues) self._replot(agent_context)
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): super().on_play_begin(agent_context) self._reset()
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): super().on_play_end(agent_context) self._reset()
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): pc = agent_context.play if plot_type & core.PlotType.PLAY_STEP != core.PlotType.NONE: episode = pc.episodes_done + 1 if episode not in self._xy_values: self._xy_values[episode] = ([], []) xvalues, yvalues = self._xy_values[episode] xvalues.append(pc.steps_done_in_episode) yvalues.append(pc.sum_of_rewards[episode]) if pc.steps_done_in_episode > self._xmax: self._xmax = pc.steps_done_in_episode if (episode == 1 and pc.steps_done == 1) or (pc.steps_done % self._num_steps_between_plot) == 0: self._replot(agent_context) if plot_type & core.PlotType.PLAY_EPISODE != core.PlotType.NONE: self._replot(agent_context) if plot_type & core.PlotType.TRAIN_EVAL != core.PlotType.NONE: self._xmax = max([len(step_rewards) for step_rewards in pc.rewards.values()]) for episode in pc.rewards.keys(): step_rewards = pc.rewards[episode] xvalues = list(range(1, len(step_rewards) + 1)) yvalues = [] for reward in step_rewards: old_sum = yvalues[-1] if len(yvalues) > 0 else 0 yvalues.append(old_sum + reward) self._xy_values[episode] = (xvalues, yvalues) self._replot(agent_context)
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
Steps
class Steps( yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Base class of plyplot callbacks generating a plot after a trained iteration or an episode played.
Attributes: axes: the subplot to plot onto
View Source
class Steps(_PlotCallback): def __init__(self, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Plots the step counts observed during policy evaluation. Args: yscale: scale of the y-axes ('linear','log') ylim: (min,max) for the y-axes """ super().__init__(core.PlotType.TRAIN_ITERATION | core.PlotType.TRAIN_EVAL | core.PlotType.PLAY_EPISODE) self.ylim = ylim self.yscale = yscale def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'steps' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_steps.keys()) yvalues = list(tc.eval_steps.values()) ylabel = 'Ø steps' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.actions.keys()) yvalues = [len(pc.actions[episode]) for episode in pc.actions.keys()] self.plot_subplot(agent_context, color='blue', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel)
Ancestors (in MRO)
- easyagents.callbacks.plot._PlotCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
clear_plot
def clear_plot( self, agent_context: easyagents.core.AgentContext )
Clears the axes for this plot. Should be called by self.plot before replotting an axes.
View Source
def clear_plot(self, agent_context: core.AgentContext): """Clears the axes for this plot. Should be called by self.plot before replotting an axes.""" assert self.axes is not None pyc = agent_context.pyplot if pyc.is_jupyter_active: self.axes.cla() else: plt.cla()
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.PLAY_EPISODE | core.PlotType.PLAY_STEP)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_EVAL)
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.PLAY_EPISODE)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): self._refresh_subplot(agent_context, core.PlotType.PLAY_STEP)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: core.AgentContext): if (self._plot_type & (core.PlotType.TRAIN_EVAL | core.PlotType.TRAIN_ITERATION)) != core.PlotType.NONE: self._create_subplot(agent_context)
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: AgentContext): """Called once before exiting an agent.train() call"""
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): self._refresh_subplot(agent_context, core.PlotType.TRAIN_ITERATION)
plot
def plot( self, agent_context: easyagents.core.AgentContext, plot_type: easyagents.core.PlotType )
Plots a graph on the self.axes object.
Args: agent_context: the context containing the data to plot plot_type: the PlotType requesting this plot call.
View Source
def plot(self, agent_context: core.AgentContext, plot_type: core.PlotType): xvalues = yvalues = [] ylabel = 'steps' if agent_context.is_train or agent_context.is_eval: tc = agent_context.train xvalues = list(tc.eval_steps.keys()) yvalues = list(tc.eval_steps.values()) ylabel = 'Ø steps' if agent_context.is_play: pc = agent_context.play xvalues = list(pc.actions.keys()) yvalues = [len(pc.actions[episode]) for episode in pc.actions.keys()] self.plot_subplot(agent_context, color='blue', ylim=self.ylim, yscale=self.yscale, xvalues=xvalues, yvalues=yvalues, ylabel=ylabel)
plot_axes
def plot_axes( self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None )
Draws the x- and y-axes.
Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...)
View Source
def plot_axes(self, xlabel: str, ylabel: str, xlim: Tuple[float, float] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None): """Draws the x- and y-axes. Attributes: xlim: None or (min,max) for the x-axes xlabel: label of the x-axes ylim: None or (min,max) for the y-axes (or None) ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log', ...) """ assert xlim is None or xlim[0] <= xlim[1] assert ylim is None or ylim[0] <= ylim[1] assert xlabel is not None assert ylabel is not None # setup subplot (axes, labels, colors) axes_color = self.axes_color self.axes.set_xlabel(xlabel) self.axes.set_ylabel(ylabel) self.axes.spines['top'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['bottom'].set_color(axes_color) self.axes.spines['left'].set_color(axes_color) self.axes.grid(color=axes_color, linestyle='-', linewidth=0.25, alpha=0.5) if xlim is not None: self.axes.set_xlim(xlim) if ylim is not None: self.axes.set_ylim(ylim) self.axes.set_yscale(yscale)
plot_subplot
def plot_subplot( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Union[Tuple[float, float], NoneType] = None, yscale: str = 'linear', ylim: Union[Tuple[float, float], NoneType] = None, color: str = 'blue' )
Draws the graph given by xvalues, yvalues (including x- & y-axes) .
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color)
View Source
def plot_subplot(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], ylabel: str, xlabel: str = None, xlim: Optional[Tuple[float, float]] = None, yscale: str = 'linear', ylim: Optional[Tuple[float, float]] = None, color: str = 'blue'): """Draws the graph given by xvalues, yvalues (including x- & y-axes) . Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) ylim: (min,max) for the x-axes xlabel: label of the x-axes ylabel: label of the y-axes yscale: scale of the y-axes ('linear', 'log',...) ylim: (min,max) for the y-axes (or None) color: the graphs color (must be the name of a matplotlib color) """ if not xlim: xmin = 0 xmax = 1 if agent_context.is_play: xmin = 1 xmax = agent_context.play.episodes_done if agent_context.is_train or agent_context.is_eval: xmin = 0 xmax = agent_context.train.episodes_done_in_training xlim = (xmin, xmax) if xlabel is None: xlabel = 'episodes' if agent_context.is_play: xlabel = 'episodes played' if agent_context.is_eval or agent_context.is_train: xlabel = 'episodes trained' self.clear_plot(agent_context) self.plot_axes(xlim=xlim, xlabel=xlabel, ylabel=ylabel, yscale=yscale, ylim=ylim) self.plot_values(agent_context=agent_context, xvalues=xvalues, yvalues=yvalues, color=color)
plot_text
def plot_text( self, text: str )
View Source
def plot_text(self, text: str): if text: ax = self.axes ax.text(0.5, 0.5, text, horizontalalignment='center', verticalalignment='center', color='blue', wrap=True) ax.set_xlabel('') ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) axes_color = self.axes_color for spin in ax.spines: ax.spines[spin].set_visible(True) ax.spines[spin].set_color(axes_color)
plot_values
def plot_values( self, agent_context: easyagents.core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Union[str, NoneType] = 'blue', marker: str = None, pause: bool = True )
Draws the graph given by xvalues, yvalues.
Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot.
View Source
def plot_values(self, agent_context: core.AgentContext, xvalues: List[int], yvalues: List[Union[float, Tuple[float, float, float]]], color: Optional[str] = 'blue', marker: str = None, pause: bool = True): """Draws the graph given by xvalues, yvalues. Attributes: agent_context: context containing the figure to plot to xvalues: the graphs x-values (must have same length as y-values) yvalues: the graphs y-values or (min,y,max)-tuples (must have same length as x-values) color: the graphs color (must be the name of a matplotlib color) or None marker: if None a marker is used if the graph has just a few points. pause: pause to redraw the plot. """ assert xvalues is not None assert yvalues is not None assert len(xvalues) == len(yvalues), "xvalues do not match yvalues" pyc: core.PyPlotContext = agent_context.pyplot # extract min / max and y values if yvalues is of the form [(min,y,max),...) yminvalues = None ymaxvalues = None if len(yvalues) > 0 and isinstance(yvalues[0], tuple): ymaxvalues = [t[2] for t in yvalues] yminvalues = [t[0] for t in yvalues] yvalues = [t[1] for t in yvalues] # plot values marker = marker if marker is None and len(xvalues) < 10: marker = 'o' fill_alpha = 0.1 if pyc.is_jupyter_active: if yminvalues is not None: self.axes.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) self.axes.plot(xvalues, yvalues, color=color, marker=marker) else: if yminvalues is not None: plt.fill_between(xvalues, yminvalues, ymaxvalues, color=color, alpha=fill_alpha) plt.plot(xvalues, yvalues, color=color, marker=marker) if pause: plt.pause(0.01)
ToMovie
class ToMovie( fps: Union[int, NoneType] = None, filepath: str = None )
Plots the pyplot figure to an mp4 file
Attributes: fps: frame per seconds filepath: the filepath of the mp4 file.
View Source
class ToMovie(core._PostProcessCallback): """Plots the pyplot figure to an mp4 file Attributes: fps: frame per seconds filepath: the filepath of the mp4 file. """ def __init__(self, fps: Optional[int] = None, filepath: str = None): """Writes the ploted graphs and images to the mp4 / gif file given by filepath. if filepath ends in '.gif' an animated gif is created. Args: fps: frames per second filepath: the filepath of the mp4 or gif file file. If None the file is written to a temp file. """ super().__init__() self.fps = fps self._is_filepath_set = filepath is not None self.filepath = filepath if not self._is_filepath_set: self.filepath = easyagents.backends.core._get_temp_path() if (not self._is_animated_gif()) and (not self.filepath.lower().endswith('.mp4')): self.filepath = self.filepath + '.mp4' self._video = imageio.get_writer(self.filepath, fps=fps) if fps else imageio.get_writer(self.filepath) def _close(self, agent_context: core.AgentContext): """closes the mp4 file and displays it in jupyter cell (if in a jupyter notebook)""" self._video.close() self._video = None if agent_context.pyplot.is_jupyter_active: with open(self.filepath, 'rb') as f: video = f.read() b64 = base64.b64encode(video) if not self._is_filepath_set: os.remove(self.filepath) width = 640 height = 480 if self._is_animated_gif(): result = ''' <img src="data:image/gif;base64,{2}" alt="easyagents.plot" width={0}/> '''.format(width, height, b64.decode()) else: result = ''' <video width="{0}" height="{1}" controls> <source src="data:video/mp4;base64,{2}" type="video/mp4"> Your browser does not support the video tag. </video>'''.format(width, height, b64.decode()) result = HTML(result) # noinspection PyTypeChecker clear_output(wait=True) # noinspection PyTypeChecker display(result) def _get_rgb_array(self, agent_context: core.AgentContext) -> np.ndarray: """Yields an rgb array representing the current content of the subplots.""" pyc = agent_context.pyplot pyc.figure.canvas.draw() result = np.frombuffer(pyc.figure.canvas.tostring_rgb(), dtype='uint8') result = result.reshape(pyc.figure.canvas.get_width_height()[::-1] + (3,)) return result def _is_animated_gif(self): return self.filepath.lower().endswith('.gif') def _write_figure_to_video(self, agent_context: core.AgentContext): """Appends the current pyplot figure to the video. if an exception occures no frame is added. """ try: rgb_array = self._get_rgb_array(agent_context) self._video.append_data(rgb_array) except: pass def on_play_episode_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL): self._write_figure_to_video(agent_context) def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): if agent_context._is_plot_ready(core.PlotType.PLAY_STEP): self._write_figure_to_video(agent_context) def on_train_iteration_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.TRAIN_ITERATION): self._write_figure_to_video(agent_context) def on_play_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE): self._close(agent_context) def on_train_end(self, agent_context: core.AgentContext): self._close(agent_context)
Ancestors (in MRO)
- easyagents.core._PostProcessCallback
- easyagents.core.AgentCallback
- abc.ABC
Methods
on_api_log
def on_api_log( self, agent_context: easyagents.core.AgentContext, api_target: str, log_msg: str )
Logs a call to the api of the agents implementation library / framework.
View Source
def on_api_log(self, agent_context: AgentContext, api_target: str, log_msg: str): """Logs a call to the api of the agents implementation library / framework.""" pass
on_gym_init_begin
def on_gym_init_begin( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment begins the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_begin(self, agent_context: AgentContext): """called when the monitored environment begins the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """
on_gym_init_end
def on_gym_init_end( self, agent_context: easyagents.core.AgentContext )
called when the monitored environment completed the instantiation of a new gym environment.
Args: agent_context: api_context passed to calling agent
View Source
def on_gym_init_end(self, agent_context: AgentContext): """called when the monitored environment completed the instantiation of a new gym environment. Args: agent_context: api_context passed to calling agent """ pass
on_gym_reset_begin
def on_gym_reset_begin( self, agent_context: easyagents.core.AgentContext, **kwargs )
Before a call to gym.reset
Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment
View Source
def on_gym_reset_begin(self, agent_context: AgentContext, **kwargs): """Before a call to gym.reset Args: agent_context: api_context passed to calling agent kwargs: the args to be passed to the underlying environment """
on_gym_reset_end
def on_gym_reset_end( self, agent_context: easyagents.core.AgentContext, reset_result: Tuple, **kwargs )
After a call to gym.reset was completed
Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset
View Source
def on_gym_reset_end(self, agent_context: AgentContext, reset_result: Tuple, **kwargs): """After a call to gym.reset was completed Args: agent_context: api_context passed to calling agent reset_result: object returned by gym.reset kwargs: args passed to gym.reset """ pass
on_gym_step_begin
def on_gym_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Before a call to gym.step
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment
View Source
def on_gym_step_begin(self, agent_context: AgentContext, action): """Before a call to gym.step Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment """ pass
on_gym_step_end
def on_gym_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
After a call to gym.step was completed
Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step
View Source
def on_gym_step_end(self, agent_context: AgentContext, action, step_result: Tuple): """After a call to gym.step was completed Args: agent_context: api_context passed to calling agent action: the action to be passed to the underlying environment step_result: (observation,reward,done,info) tuple returned by gym.step """ pass
on_log
def on_log( self, agent_context: easyagents.core.AgentContext, log_msg: str )
Logs a general message
View Source
def on_log(self, agent_context: AgentContext, log_msg: str): """Logs a general message""" pass
on_play_begin
def on_play_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.play() call (during play or eval, but not during train).
View Source
def on_play_begin(self, agent_context: AgentContext): """Called once at the entry of an agent.play() call (during play or eval, but not during train). """
on_play_end
def on_play_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.play() call (during play or eval, but not during train)
View Source
def on_play_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE): self._close(agent_context)
on_play_episode_begin
def on_play_episode_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of new episode to be played (during play or eval, but not during train).
View Source
def on_play_episode_begin(self, agent_context: AgentContext): """Called once at the start of new episode to be played (during play or eval, but not during train). """
on_play_episode_end
def on_play_episode_end( self, agent_context: easyagents.core.AgentContext )
Called once after an episode is done or stopped (during play or eval, but not during train).
View Source
def on_play_episode_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.PLAY_EPISODE | core.PlotType.TRAIN_EVAL): self._write_figure_to_video(agent_context)
on_play_step_begin
def on_play_step_begin( self, agent_context: easyagents.core.AgentContext, action )
Called once before a new step is taken in the current episode (during play or eval, but not during train).
Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call
View Source
def on_play_step_begin(self, agent_context: AgentContext, action): """Called once before a new step is taken in the current episode (during play or eval, but not during train). Args: agent_context: the context describing the agents current configuration action: the action to be passed to the upcoming gym_env.step call """
on_play_step_end
def on_play_step_end( self, agent_context: easyagents.core.AgentContext, action, step_result: Tuple )
Called once after a step is completed in the current episode (during play or eval, but not during train).
View Source
def on_play_step_end(self, agent_context: core.AgentContext, action, step_result: Tuple): if agent_context._is_plot_ready(core.PlotType.PLAY_STEP): self._write_figure_to_video(agent_context)
on_train_begin
def on_train_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the entry of an agent.train() call.
View Source
def on_train_begin(self, agent_context: AgentContext): """Called once at the entry of an agent.train() call. """
on_train_end
def on_train_end( self, agent_context: easyagents.core.AgentContext )
Called once before exiting an agent.train() call
View Source
def on_train_end(self, agent_context: core.AgentContext): self._close(agent_context)
on_train_iteration_begin
def on_train_iteration_begin( self, agent_context: easyagents.core.AgentContext )
Called once at the start of a new iteration.
View Source
def on_train_iteration_begin(self, agent_context: AgentContext): """Called once at the start of a new iteration. """
on_train_iteration_end
def on_train_iteration_end( self, agent_context: easyagents.core.AgentContext )
Called once after the current iteration is completed
View Source
def on_train_iteration_end(self, agent_context: core.AgentContext): if agent_context._is_plot_ready(core.PlotType.TRAIN_ITERATION): self._write_figure_to_video(agent_context)