diff --git a/pyFTS/models/nonstationary/common.py b/pyFTS/models/nonstationary/common.py index a47f9dd..20b10d2 100644 --- a/pyFTS/models/nonstationary/common.py +++ b/pyFTS/models/nonstationary/common.py @@ -58,7 +58,6 @@ class FuzzySet(FS.FuzzySet): if self.location is None: inc = t else: - l = len(self.location) inc = sum([self.location[k](t + self.location_roots[k], self.location_params[k]) for k in np.arange(0, l)]) diff --git a/pyFTS/models/nonstationary/cvfts.py b/pyFTS/models/nonstationary/cvfts.py index 66c6b3b..334eba4 100644 --- a/pyFTS/models/nonstationary/cvfts.py +++ b/pyFTS/models/nonstationary/cvfts.py @@ -30,6 +30,7 @@ class HighOrderNonstationaryFLRG(hofts.HighOrderFTS): def __len__(self): return len(self.RHS) + class ConditionalVarianceFTS(hofts.HighOrderFTS): def __init__(self, **kwargs): super(ConditionalVarianceFTS, self).__init__(**kwargs) @@ -45,6 +46,12 @@ class ConditionalVarianceFTS(hofts.HighOrderFTS): self.uod_clip = False self.order = 1 self.min_order = 1 + self.inputs = [] + self.forecasts = [] + self.residuals = [] + self.variance_residual = 0. + self.mean_residual = 0. + self.memory_window = kwargs.get("memory_window",5) def train(self, ndata, **kwargs): @@ -52,6 +59,21 @@ class ConditionalVarianceFTS(hofts.HighOrderFTS): flrs = FLR.generate_non_recurrent_flrs(tmpdata) self.generate_flrg(flrs) + self.forecasts = self.forecast(ndata, no_update=True) + self.residuals = np.array(ndata[1:]) - np.array(self.forecasts[:-1]) + + self.variance_residual = np.var(self.residuals) # np.max(self.residuals + self.mean_residual = np.mean(self.residuals) + + self.residuals = self.residuals[-self.memory_window:].tolist() + self.forecasts = self.forecasts[-self.memory_window:] + self.inputs = np.array(ndata[-self.memory_window:]).tolist() + + print(self.mean_residual) + print(self.variance_residual) + print([self.original_min,self.original_max]) + + def generate_flrg(self, flrs, **kwargs): for flr in flrs: if flr.LHS.name in self.flrgs: @@ -64,7 +86,38 @@ class ConditionalVarianceFTS(hofts.HighOrderFTS): def _smooth(self, a): return .1 * a[0] + .3 * a[1] + .6 * a[2] - def perturbation_factors(self, data): + def perturbation_factors(self, data, **kwargs): + + _max = 0 + _min = 0 + if data < self.original_min: + _min = data - self.original_min if data < 0 else self.original_min - data + elif data > self.original_max: + _max = data - self.original_max if data > 0 else self.original_max - data + self.min_stack.pop(2) + self.min_stack.insert(0, _min) + _min = min(self.min_stack) + self.max_stack.pop(2) + self.max_stack.insert(0, _max) + _max = max(self.max_stack) + + _range = (_max - _min)/2 + + translate = np.linspace(_min, _max, self.partitioner.partitions) + + var = np.std(self.residuals) + + var = 0 if var < 1 else var + + loc = (self.mean_residual + np.mean(self.residuals)) + + location = [_range + w + loc + k for k in np.linspace(-var,var) for w in translate] + + perturb = [[location[k], var] for k in np.arange(0, self.partitioner.partitions)] + + return perturb + + def perturbation_factors__old(self, data): _max = 0 _min = 0 if data < self.original_min: @@ -107,39 +160,59 @@ class ConditionalVarianceFTS(hofts.HighOrderFTS): ret = [] + no_update = kwargs.get("no_update",False) + for k in np.arange(0, l): sample = ndata[k] - perturb = self.perturbation_factors(sample) + if not no_update: + perturb = self.perturbation_factors(sample) + else: + perturb = [[0, 1] for k in np.arange(0, self.partitioner.partitions)] affected_sets = self._affected_sets(sample, perturb) - tmp = [] + numerator = [] + denominator = [] if len(affected_sets) == 1: ix = affected_sets[0][0] aset = self.partitioner.ordered_sets[ix] if aset in self.flrgs: - tmp.append(self.flrgs[aset].get_midpoint(perturb[ix])) + numerator.append(self.flrgs[aset].get_midpoint(perturb[ix])) else: fuzzy_set = self.sets[aset] - tmp.append(fuzzy_set.get_midpoint(perturb[ix])) + numerator.append(fuzzy_set.get_midpoint(perturb[ix])) + denominator.append(1) else: for aset in affected_sets: ix = aset[0] fs = self.partitioner.ordered_sets[ix] tdisp = perturb[ix] if fs in self.flrgs: - tmp.append(self.flrgs[fs].get_midpoint(tdisp) * aset[1]) + numerator.append(self.flrgs[fs].get_midpoint(tdisp) * aset[1]) else: fuzzy_set = self.sets[fs] - tmp.append(fuzzy_set.get_midpoint(tdisp) * aset[1]) + numerator.append(fuzzy_set.get_midpoint(tdisp) * aset[1]) + denominator.append(aset[1]) - pto = sum(tmp) + if sum(denominator) > 0: + pto = sum(numerator) /sum(denominator) + else: + pto = sum(numerator) ret.append(pto) + if not no_update: + self.forecasts.append(pto) + self.residuals.append(self.inputs[-1] - self.forecasts[-1]) + self.inputs.append(sample) + + self.inputs.pop(0) + self.forecasts.pop(0) + self.residuals.pop(0) + return ret diff --git a/pyFTS/models/nonstationary/util.py b/pyFTS/models/nonstationary/util.py index f694387..7da2a95 100644 --- a/pyFTS/models/nonstationary/util.py +++ b/pyFTS/models/nonstationary/util.py @@ -62,6 +62,7 @@ def plot_sets_conditional(model, data, step=1, size=[5, 5], colors=None, fig, axes = plt.subplots(nrows=1, ncols=1, figsize=size) for t in range: + model.forecast([data[t]]) perturb = model.perturbation_factors(data[t]) for ct, key in enumerate(model.partitioner.ordered_sets): diff --git a/pyFTS/tests/general.py b/pyFTS/tests/general.py index 98487c3..52e367f 100644 --- a/pyFTS/tests/general.py +++ b/pyFTS/tests/general.py @@ -19,7 +19,7 @@ dataset = TAIEX.get_data() #print(len(dataset)) from pyFTS.partitioners import Grid, Util as pUtil -partitioner = Grid.GridPartitioner(data=dataset[:800], npart=10)#, transformation=tdiff) +partitioner = Grid.GridPartitioner(data=dataset[:800], npart=10, transformation=tdiff) from pyFTS.common import Util as cUtil @@ -28,9 +28,9 @@ from pyFTS.benchmarks import benchmarks as bchmk, Util as bUtil, Measures, knn, from pyFTS.models import pwfts, song, chen, ifts, hofts from pyFTS.models.ensemble import ensemble -#model = chen.ConventionalFTS(partitioner=partitioner) -model = hofts.HighOrderFTS(partitioner=partitioner,order=2) -#model.append_transformation(tdiff) +model = chen.ConventionalFTS(partitioner=partitioner) +#model = hofts.HighOrderFTS(partitioner=partitioner,order=2) +model.append_transformation(tdiff) model.fit(dataset[:800]) cUtil.plot_rules(model, size=[20,20], rules_by_axis=5, columns=1) diff --git a/pyFTS/tests/nonstationary.py b/pyFTS/tests/nonstationary.py index 4e91127..c715c4e 100644 --- a/pyFTS/tests/nonstationary.py +++ b/pyFTS/tests/nonstationary.py @@ -3,7 +3,7 @@ import numpy as np from pyFTS.common import Membership, Transformations from pyFTS.models.nonstationary import common, perturbation, partitioners, util from pyFTS.models.nonstationary import nsfts, cvfts -from pyFTS.partitioners import Grid +from pyFTS.partitioners import Grid, Entropy import matplotlib.pyplot as plt from pyFTS.common import Util as cUtil import pandas as pd @@ -45,23 +45,44 @@ from pyFTS.common import Util from pyFTS.data import TAIEX taiex = TAIEX.get_data() -taiex_diff = tdiff.apply(taiex) +#taiex_diff = tdiff.apply(taiex) -train = taiex_diff[:600] -test = taiex_diff[600:1500] +train = taiex[:600] +test = taiex[600:800] -fs_tmp = Grid.GridPartitioner(data=train, npart=20) #, transformation=tdiff) +#fs_tmp = Grid.GridPartitioner(data=train, npart=7, transformation=tdiff) +#fs_tmp = Entropy.EntropyPartitioner(data=train, npart=7, transformation=tdiff) +fs_tmp = Grid.GridPartitioner(data=train, npart=20) fs = partitioners.SimpleNonStationaryPartitioner(train, fs_tmp) print(fs) -model = cvfts.ConditionalVarianceFTS(partitioner=fs) +model = cvfts.ConditionalVarianceFTS(partitioner=fs,memory_window=3) model.fit(train) print(model) #tmpp4 = model.predict(test, type='point') -tmp = model.predict(test, type='interval') +#tmp = model.predict(test, type='interval') -#util.plot_sets_conditional(model, test, step=1, tam=[10, 5]) \ No newline at end of file +#util.plot_sets_conditional(model, tdiff.apply(test), step=5, size=[10, 5]) +#util.plot_sets_conditional(model, test, step=5, size=[10, 5]) + +fig, axes = plt.subplots(nrows=2, ncols=1, figsize=[10, 5]) + +axes[0].plot(test[1:], label="Test Data") + +forecasts = model.predict(test, type='point') + +axes[0].plot(forecasts[:-1], label="CVFTS Forecasts") + +handles0, labels0 = axes[0].get_legend_handles_labels() +lgd = axes[0].legend(handles0, labels0, loc=2) + +residuals = np.array(test[1:]) - np.array(forecasts[:-1]) + +axes[1].plot(residuals) +axes[1].set_title("Residuals") + +print("fim") \ No newline at end of file