import numpy as np class RunningStat: # tracks realtime mean and standard deviation without storing any data def __init__(self, priors=None, max_trackable=-1): self.max_trackable = max_trackable if priors is not None: # initialize from history self.M = priors[0] self.S = priors[1] self.n = priors[2] self.M_last = self.M self.S_last = self.S else: self.reset() def reset(self): self.M = 0. self.S = 0. self.M_last = 0. self.S_last = 0. self.n = 0 def push_data(self, new_data): # short term memory hack if self.max_trackable < 0 or self.n < self.max_trackable: self.n += 1 if self.n == 0: self.M_last = new_data self.M = self.M_last self.S_last = 0. else: self.M = self.M_last + (new_data - self.M_last) / self.n self.S = self.S_last + (new_data - self.M_last) * (new_data - self.M) self.M_last = self.M self.S_last = self.S def mean(self): return self.M def variance(self): if self.n >= 2: return self.S / (self.n - 1.) else: return 0 def std(self): return np.sqrt(self.variance()) def params_to_save(self): return [self.M, self.S, self.n] class RunningStatFilter: def __init__(self, raw_priors=None, filtered_priors=None, max_trackable=-1): self.raw_stat = RunningStat(raw_priors, -1) self.filtered_stat = RunningStat(filtered_priors, max_trackable) def reset(self): self.raw_stat.reset() self.filtered_stat.reset() def push_and_update(self, new_data): _std_last = self.raw_stat.std() self.raw_stat.push_data(new_data) _delta_std = self.raw_stat.std() - _std_last if _delta_std <= 0: self.filtered_stat.push_data(new_data) else: pass # self.filtered_stat.push_data(self.filtered_stat.mean()) # class SequentialBayesian():