feat(monitor): impl. a MetricsMonitor
@@ -31,6 +31,7 @@ class BaseMonitor(ABC):
def __init__(self, check_every=None):
self.check_every = check_every or 100
self.fig = ...
+ self.using_non_gui_backend = (matplotlib.get_backend() == 'agg')
@abstractmethod
def check(self, nets, conditions, history):
@@ -116,7 +117,6 @@ class MonitorSpherical(BaseMonitor):
if not self.contour_plot_available:
warnings.warn("Warning: contourf plot only available for matplotlib version >= v3.3.0 "
"switching to matshow instead")
- self.using_non_gui_backend = (matplotlib.get_backend() == 'agg')
self.fig = None
self.axs = [] # subplots
self.ax_metrics = None
@@ -516,7 +516,6 @@ class Monitor1D(BaseMonitor):
"""Initializer method
"""
super(Monitor1D, self).__init__(check_every=check_every)
- self.using_non_gui_backend = (matplotlib.get_backend() == 'agg')
self.fig = plt.figure(figsize=(30, 8))
self.ax1 = self.fig.add_subplot(131)
self.ax2 = self.fig.add_subplot(132)
@@ -621,7 +620,6 @@ class Monitor2D(BaseMonitor):
if solution_style not in ['heatmap', 'curves']:
raise ValueError(f"Unsupported 'solution_style' = {solution_style}")
self.solution_style = solution_style
- self.using_non_gui_backend = (matplotlib.get_backend() == 'agg')
self.fig = None
self.axs = [] # subplots
# self.caxs = [] # colorbars
@@ -729,3 +727,45 @@ class Monitor2D(BaseMonitor):
self.fig.canvas.draw()
if not self.using_non_gui_backend:
plt.pause(0.05)
+
+
+class MetricsMonitor(BaseMonitor):
+ r"""A monitor for visualizing the loss and other metrics.
+ This monitor does not visualize the solution.
+
+ :param check_every:
+ The frequency of checking the neural network represented by the number of epochs between two checks.
+ Defaults to 100.
+ :type check_every: int, optional
+ """
+ def __init__(self, check_every=100):
+ super().__init__(check_every=check_every)
+ self.fig = plt.figure(figsize=(12, 6), dpi=125)
+ self.ax1, self.ax2 = self.fig.subplots(1, 2)
+
+ def check(self, nets, conditions, history):
+ self.ax1.clear()
+ self.ax1.plot(history['train_loss'], label='training loss')
+ self.ax1.plot(history['valid_loss'], label='validation loss')
+ self.ax1.set_title('loss during training')
+ self.ax1.set_ylabel('loss')
+ self.ax1.set_xlabel('epochs')
+ self.ax1.set_yscale('log')
+ self.ax1.legend()
+
+ self.ax2.clear()
+ for metric_name, metric_values in history.items():
+ if metric_name == 'train_loss' or metric_name == 'valid_loss':
+ continue
+ self.ax2.plot(metric_values, label=metric_name)
+ self.ax2.set_title('metrics during training')
+ self.ax2.set_ylabel('metrics')
+ self.ax2.set_xlabel('epochs')
+ self.ax2.set_yscale('log')
+ # if there're not custom metrics, then there won't be any labels in this axis
+ if len(history) > 2:
+ self.ax2.legend()
+
+ self.fig.canvas.draw()
+ if not self.using_non_gui_backend:
+ plt.pause(0.05)
\ No newline at end of file
