Source code for sconce.monitors.ringbuffer_monitor

from sconce.monitors.base import Monitor
from torch import Tensor

import math
import numpy as np
from numpy_ringbuffer import RingBuffer


[docs]class RingbufferMonitor(Monitor): def __init__(self, capacity=100, key='training_loss', name='ringbuffer_monitor'): super().__init__(name=name) self.capacity = capacity self.key = key self.value_buffer = None self.step_buffer = RingBuffer(capacity=capacity, dtype='float32') self.previous_session_steps = 0 self.last_step = 0
[docs] def start_session(self, num_steps, **kwargs): self.previous_session_steps += self.last_step
[docs] def write(self, data, step, **kwargs): if self.key in data.keys(): value = data[self.key] if isinstance(value, Tensor): dtype = value.data.cpu().numpy().dtype value = self._to_scalar(value) else: dtype = np.array(value).dtype if self.value_buffer is None: self.value_buffer = RingBuffer(capacity=self.capacity, dtype=dtype) self.value_buffer.append(value) self.step_buffer.append(step + self.previous_session_steps) self.last_step = math.ceil(step)
[docs] def mean(self, *args, **kwargs): return np.array(self.value_buffer).mean(*args, **kwargs)
[docs] def std(self, *args, **kwargs): return np.array(self.value_buffer).std(*args, **kwargs)
@property def movement_index(self): steps = self.step_buffer if len(steps) < self.capacity: # not enough information gathered yet to say... return None else: step_difference = (steps[-1] - steps[0]) midpoint = np.argmax(steps >= steps[0] + (step_difference // 2)) values = np.array(self.value_buffer) first = values[:midpoint] last = values[midpoint:] d = (np.abs(first.mean() - last.mean()) / (2 * np.sqrt(first.std() * last.std()))) return d