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

@ -299,7 +299,7 @@ def white_noise(n=500):
def random_walk(n=500, type='gaussian'):
"""
Simple random walk
:param n: number of samples
:param type: 'gaussian' or 'uniform'
:return:

View File

@ -43,10 +43,12 @@ class EnsembleFTS(fts.FTS):
self.alpha = kwargs.get("alpha", 0.05)
"""The quantiles """
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')
"""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):
"""
@ -80,9 +82,9 @@ class EnsembleFTS(fts.FTS):
data = self.indexer.get_data(data)
sample = data[-model.order:]
forecast = model.forecast(sample)
forecast = model.predict(sample)
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:
forecast = np.nan
if isinstance(forecast, list):
@ -99,6 +101,11 @@ class EnsembleFTS(fts.FTS):
elif self.point_method == 'quantile':
alpha = kwargs.get("alpha",0.05)
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

View File

@ -38,6 +38,11 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
self.batch_size = kwargs.get('batch_size', 10)
"""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.uod_clip = False
#self.max_lag = self.window_length + self.max_lag
@ -49,16 +54,9 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
if model.is_high_order:
model = self.fts_method(partitioner=partitioner, order=self.order, **self.fts_params)
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.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):
l = len(data)
@ -79,7 +77,7 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
sample = data[k - self.max_lag: k]
tmp = self.get_models_forecasts(sample)
point = self._point_smoothing(tmp)
point = self.get_point(tmp)
ret.append(point)
return ret