Added the data.artificial.SignalEmulator

This commit is contained in:
Petrônio Cândido 2019-02-20 16:02:07 -03:00
parent fc1f295150
commit 9125582c9c
6 changed files with 228 additions and 30 deletions

View File

@ -24,6 +24,8 @@ class FTS(object):
"""A string with the model name""" """A string with the model name"""
self.detail = kwargs.get('name',"") self.detail = kwargs.get('name',"")
"""A string with the model detailed information""" """A string with the model detailed information"""
self.is_wrapper = False
"""Indicates that this model is a wrapper for other(s) method(s)"""
self.is_high_order = False self.is_high_order = False
"""A boolean value indicating if the model support orders greater than 1, default: False""" """A boolean value indicating if the model support orders greater than 1, default: False"""
self.min_order = 1 self.min_order = 1
@ -313,11 +315,12 @@ class FTS(object):
if 'partitioner' in kwargs: if 'partitioner' in kwargs:
self.partitioner = kwargs.pop('partitioner') self.partitioner = kwargs.pop('partitioner')
if (self.sets is None or len(self.sets) == 0) and not self.benchmark_only and not self.is_multivariate: if not self.is_wrapper:
if self.partitioner is not None: if (self.sets is None or len(self.sets) == 0) and not self.benchmark_only and not self.is_multivariate:
self.sets = self.partitioner.sets if self.partitioner is not None:
else: self.sets = self.partitioner.sets
raise Exception("Fuzzy sets were not provided for the model. Use 'sets' parameter or 'partitioner'. ") else:
raise Exception("Fuzzy sets were not provided for the model. Use 'sets' parameter or 'partitioner'. ")
if 'order' in kwargs: if 'order' in kwargs:
self.order = kwargs.pop('order') self.order = kwargs.pop('order')

View File

@ -34,6 +34,83 @@ def generate_gaussian_linear(mu_ini, sigma_ini, mu_inc, sigma_inc, it=100, num=1
return ret return ret
def generate_linear_periodic_gaussian(period, mu_min, sigma_min, mu_max, sigma_max, it=100, num=10, vmin=None, vmax=None):
"""
:param period:
:param mu_min:
:param sigma_min:
:param mu_max:
:param sigma_max:
:param it:
:param num:
:param vmin:
:param vmax:
:return:
"""
if period > num:
raise("The 'period' parameter must be lesser than 'it' parameter")
mu_inc = (mu_max - mu_min)/period
sigma_inc = (sigma_max - sigma_min) / period
mu = mu_min
sigma = sigma_min
ret = []
signal = True
for k in np.arange(0, it):
tmp = np.random.normal(mu, sigma, num)
if vmin is not None:
tmp = np.maximum(np.full(num, vmin), tmp)
if vmax is not None:
tmp = np.minimum(np.full(num, vmax), tmp)
ret.extend(tmp)
if k % period == 0:
signal = not signal
mu += (mu_inc if signal else -mu_inc)
sigma += (sigma_inc if signal else -sigma_inc)
return ret
def generate_senoidal_periodic_gaussian(period, mu_min, sigma_min, mu_max, sigma_max, it=100, num=10, vmin=None, vmax=None):
"""
:param period:
:param mu_min:
:param sigma_min:
:param mu_max:
:param sigma_max:
:param it:
:param num:
:param vmin:
:param vmax:
:return:
"""
mu_range = mu_max - mu_min
sigma_range = sigma_max - sigma_min
mu = mu_min
sigma = sigma_min
ret = []
for k in np.arange(0, it):
tmp = np.random.normal(mu, sigma, num)
if vmin is not None:
tmp = np.maximum(np.full(num, vmin), tmp)
if vmax is not None:
tmp = np.minimum(np.full(num, vmax), tmp)
ret.extend(tmp)
mu += mu_range * np.sin (period * k)
sigma += mu_range * np.sin (period * k)
return ret
def generate_uniform_linear(min_ini, max_ini, min_inc, max_inc, it=100, num=10, vmin=None, vmax=None): def generate_uniform_linear(min_ini, max_ini, min_inc, max_inc, it=100, num=10, vmin=None, vmax=None):
""" """
Generate data sampled from Uniform distribution, with constant or linear changing bounds Generate data sampled from Uniform distribution, with constant or linear changing bounds
@ -78,3 +155,125 @@ def random_walk(n=500, type='gaussian'):
return ret return ret
def _append(additive, start, before, new):
if not additive:
before.extend(new)
return before
else:
for k in range(start):
new.insert(0,0)
tmp = np.array(before) + np.array(new)
return tmp
class SignalEmulator(object):
def __init__(self, **kwargs):
super(SignalEmulator, self).__init__()
self.components = []
def stationary_gaussian(self, mu, sigma, **kwargs):
"""
Creates a continuous Gaussian signal with mean mu and variance sigma.
:param mu: mean
:param sigma: variance
:keyword cummulative: If False it cancels the previous signal and start this one, if True
this signal is added to the previous one
:keyword start: lag index to start this signal, the default value is 0
:keyword it: Number of iterations, the default value is 1
:keyword length: Number of samples generated on each iteration, the default value is 100
:keyword vmin: Lower bound value of generated data, the default value is None
:keyword vmax: Upper bound value of generated data, the default value is None
:return: A list of it*num float values
"""
parameters = {'mu': mu, 'sigma': sigma}
self.components.append({'dist': 'gaussian', 'type': 'constant',
'parameters': parameters, 'args': kwargs})
def incremental_gaussian(self, mu, sigma, **kwargs):
"""
Creates an additive gaussian interference on a previous signal
:param mu:
:param sigma:
:keyword cummulative: If False it cancels the previous signal and start this one, if True
this signal is added to the previous one
:keyword start: lag index to start this signal, the default value is 0
:keyword it: Number of iterations, the default value is 1
:keyword length: Number of samples generated on each iteration, the default value is 100
:keyword vmin: Lower bound value of generated data, the default value is None
:keyword vmax: Upper bound value of generated data, the default value is None
:return: A list of it*num float values
"""
parameters = {'mu': mu, 'sigma': sigma}
self.components.append({'dist': 'gaussian', 'type': 'incremental',
'parameters': parameters, 'args': kwargs})
def periodic_gaussian(self, type, period, mu_min, sigma_min, mu_max, sigma_max, **kwargs):
"""
Creates an additive periodic gaussian interference on a previous signal
:param mu:
:param sigma:
:keyword additive: If False it cancels the previous signal and start this one, if True
this signal is added to the previous one
:keyword start: lag index to start this signal, the default value is 0
:keyword it: Number of iterations, the default value is 1
:keyword length: Number of samples generated on each iteration, the default value is 100
:keyword vmin: Lower bound value of generated data, the default value is None
:keyword vmax: Upper bound value of generated data, the default value is None
:return: A list of it*num float values
"""
parameters = {'type':type, 'period':period,
'mu_min': mu_min, 'sigma_min': sigma_min, 'mu_max': mu_max, 'sigma_max': sigma_max}
self.components.append({'dist': 'gaussian', 'type': 'periodic',
'parameters': parameters, 'args': kwargs})
def blip(self, intensity, **kwargs):
"""
:param intensity:
:param kwargs:
:return:
"""
self.components.append({'dist': 'blip', 'type': 'blip', 'parameters': [intensity, kwargs]})
def run(self):
signal = []
last_it = 10
last_num = 10
for ct, component in enumerate(self.components):
parameters = component['parameters']
kwargs = component['args']
additive = kwargs.get('additive', True)
start = kwargs.get('start', 0)
it = kwargs.get('it', last_it)
num = kwargs.get('length', last_num)
vmin = kwargs.get('vmin',None)
vmax = kwargs.get('vmax', None)
if component['type'] == 'constant':
tmp = generate_gaussian_linear(parameters['mu'], parameters['sigma'], 0, 0,
it=it, num=num, vmin=vmin, vmax=vmax)
elif component['type'] == 'incremental':
tmp = generate_gaussian_linear(0, 0, parameters['mu'], parameters['sigma'],
it=num, num=1, vmin=vmin, vmax=vmax)
elif component['type'] == 'periodic':
period = component['period']
mu_min, sigma_min = parameters['mu_min'],parameters['sigma_min']
mu_max, sigma_max = parameters['mu_max'],parameters['sigma_max']
if parameters['type'] == 'senoidal':
tmp = generate_senoidal_periodic_gaussian(period, mu_min, sigma_min, mu_max, sigma_max,
it=num, num=1, vmin=vmin, vmax=vmax)
else:
tmp = generate_linear_periodic_gaussian(period, mu_min, sigma_min, mu_max, sigma_max,
it=num, num=1, vmin=vmin, vmax=vmax)
last_num = num
last_it = it
signal = _append(additive, start, signal, tmp)
return signal

View File

@ -31,6 +31,7 @@ class EnsembleFTS(fts.FTS):
self.shortname = "EnsembleFTS" self.shortname = "EnsembleFTS"
self.name = "Ensemble FTS" self.name = "Ensemble FTS"
self.flrgs = {} self.flrgs = {}
self.is_wrapper = True
self.has_point_forecasting = True self.has_point_forecasting = True
self.has_interval_forecasting = True self.has_interval_forecasting = True
self.has_probability_forecasting = True self.has_probability_forecasting = True

View File

@ -46,10 +46,11 @@ class IncrementalEnsembleFTS(ensemble.EnsembleFTS):
partitioner = self.partitioner_method(data=data, **self.partitioner_params) partitioner = self.partitioner_method(data=data, **self.partitioner_params)
model = self.fts_method(partitioner=partitioner, **self.fts_params) model = self.fts_method(partitioner=partitioner, **self.fts_params)
if self.model.is_high_order: if model.is_high_order:
self.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)
self.models.pop(0) if len(self.models) > 0:
self.models.pop(0)
self.models.append(model) self.models.append(model)
def _point_smoothing(self, forecasts): def _point_smoothing(self, forecasts):

View File

@ -7,15 +7,21 @@ import numpy as np
import pandas as pd import pandas as pd
from pyFTS.partitioners import Grid from pyFTS.partitioners import Grid
from pyFTS.common import Transformations from pyFTS.common import Transformations
from pyFTS import hofts, song, yu, cheng, ismailefendi, sadaei, hwang
from pyFTS.models import chen from pyFTS.models import chen
from pyFTS.models.ensemble import ensemble from pyFTS.models.incremental import IncrementalEnsemble, TimeVariant
os.chdir("/home/petronio/dados/Dropbox/Doutorado/Codigos/") from pyFTS.data import AirPassengers
diff = Transformations.Differential(1)
passengers = pd.read_csv("DataSets/AirPassengers.csv", sep=",") passengers = AirPassengers.get_data()
model = IncrementalEnsemble.IncrementalEnsembleFTS(order=2, window_length=20, batch_size=5)
model.fit(passengers[:40])
model.predict(passengers[40:])
'''
passengers = np.array(passengers["Passengers"]) passengers = np.array(passengers["Passengers"])
e = ensemble.AllMethodEnsembleFTS(alpha=0.25, point_method="median", interval_method='quantile') e = ensemble.AllMethodEnsembleFTS(alpha=0.25, point_method="median", interval_method='quantile')
@ -115,5 +121,6 @@ print(_normal)
# distributions=[True,False], save=True, file="pictures/distribution_ahead_arma", # distributions=[True,False], save=True, file="pictures/distribution_ahead_arma",
# time_from=60, time_to=10, tam=[12,5]) # time_from=60, time_to=10, tam=[12,5])
'''

View File

@ -14,21 +14,8 @@ from pyFTS.benchmarks import benchmarks as bchmk, Measures
from pyFTS.models import chen, yu, cheng, ismailefendi, hofts, pwfts from pyFTS.models import chen, yu, cheng, ismailefendi, hofts, pwfts
from pyFTS.common import Transformations, Membership from pyFTS.common import Transformations, Membership
tdiff = Transformations.Differential(1) from pyFTS.data import artificial
cd = artificial.SignalEmulator()
from pyFTS.data import TAIEX, SP500, NASDAQ, Malaysia, Enrollments cd.stationary_gaussian(10,3,length=100)
cd.incremental_gaussian(0.5,0,start=100,length=200)
#from pyFTS.data import mackey_glass
#y = mackey_glass.get_data()
from pyFTS.partitioners import Grid
from pyFTS.models import pwfts, tsaur
x = [k for k in np.arange(-2*np.pi, 2*np.pi, 0.5)]
y = [np.sin(k) for k in x]
part = Grid.GridPartitioner(data=y, npart=35)
model = hofts.HighOrderFTS(order=2, partitioner=part)
model.fit(y)
forecasts = model.predict(y, steps_ahead=10)