Improvements on EnsembleFTS and IncrementalEnsembleFTS

This commit is contained in:
Petrônio Cândido 2019-02-27 10:32:58 -03:00
parent 934c744139
commit f7c1b4443e
3 changed files with 20 additions and 15 deletions

View File

@ -43,10 +43,12 @@ class EnsembleFTS(fts.FTS):
self.alpha = kwargs.get("alpha", 0.05) self.alpha = kwargs.get("alpha", 0.05)
"""The quantiles """ """The quantiles """
self.point_method = kwargs.get('point_method', 'mean') self.point_method = kwargs.get('point_method', 'mean')
"""The method used to mix the several model's forecasts into a unique point forecast. Options: mean, median, quantile""" """The method used to mix the several model's forecasts into a unique point forecast. Options: mean, median, quantile, exponential"""
self.interval_method = kwargs.get('interval_method', 'quantile') self.interval_method = kwargs.get('interval_method', 'quantile')
"""The method used to mix the several model's forecasts into a interval forecast. Options: quantile, extremum, normal""" """The method used to mix the several model's forecasts into a interval forecast. Options: quantile, extremum, normal"""
self.order = 1 #self.order = 1
self.exp_factor = kwargs.get('exp_factor', 0.5)
"""Multiplicative factor on exponential averaging of the models"""
def append_model(self, model): def append_model(self, model):
""" """
@ -80,9 +82,9 @@ class EnsembleFTS(fts.FTS):
data = self.indexer.get_data(data) data = self.indexer.get_data(data)
sample = data[-model.order:] sample = data[-model.order:]
forecast = model.forecast(sample) forecast = model.predict(sample)
if isinstance(forecast, (list,np.ndarray)) and len(forecast) > 0: if isinstance(forecast, (list,np.ndarray)) and len(forecast) > 0:
forecast = int(forecast[-1]) forecast = forecast[-1]
elif isinstance(forecast, (list,np.ndarray)) and len(forecast) == 0: elif isinstance(forecast, (list,np.ndarray)) and len(forecast) == 0:
forecast = np.nan forecast = np.nan
if isinstance(forecast, list): if isinstance(forecast, list):
@ -99,6 +101,11 @@ class EnsembleFTS(fts.FTS):
elif self.point_method == 'quantile': elif self.point_method == 'quantile':
alpha = kwargs.get("alpha",0.05) alpha = kwargs.get("alpha",0.05)
ret = np.percentile(forecasts, alpha*100) ret = np.percentile(forecasts, alpha*100)
elif self.point_method == 'exponential':
l = len(self.models)
if l == 1:
return forecasts
ret = np.nansum([np.exp(-(self.exp_factor * (l - k))) * forecasts[k] for k in range(l)])
return ret return ret

View File

@ -38,6 +38,11 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
self.batch_size = kwargs.get('batch_size', 10) self.batch_size = kwargs.get('batch_size', 10)
"""The batch interval between each retraining""" """The batch interval between each retraining"""
self.num_models = kwargs.get('num_models', 5)
"""The number of models to hold in the ensemble"""
self.point_method = kwargs.get('point_method', 'exponential')
self.is_high_order = True self.is_high_order = True
self.uod_clip = False self.uod_clip = False
#self.max_lag = self.window_length + self.max_lag #self.max_lag = self.window_length + self.max_lag
@ -49,16 +54,9 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
if model.is_high_order: if model.is_high_order:
model = self.fts_method(partitioner=partitioner, order=self.order, **self.fts_params) model = self.fts_method(partitioner=partitioner, order=self.order, **self.fts_params)
model.fit(data, **kwargs) model.fit(data, **kwargs)
if len(self.models) > 0: self.append_model(model)
if len(self.models) > self.num_models:
self.models.pop(0) self.models.pop(0)
self.models.append(model)
def _point_smoothing(self, forecasts):
l = len(self.models)
ret = np.nansum([np.exp(-(l-k)) * forecasts[k] for k in range(l)])
return ret
def forecast(self, data, **kwargs): def forecast(self, data, **kwargs):
l = len(data) l = len(data)
@ -79,7 +77,7 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
sample = data[k - self.max_lag: k] sample = data[k - self.max_lag: k]
tmp = self.get_models_forecasts(sample) tmp = self.get_models_forecasts(sample)
point = self._point_smoothing(tmp) point = self.get_point(tmp)
ret.append(point) ret.append(point)
return ret return ret