diff --git a/pyFTS/models/nonstationary/flrg.py b/pyFTS/models/nonstationary/flrg.py index 085f93f..bfacb0b 100644 --- a/pyFTS/models/nonstationary/flrg.py +++ b/pyFTS/models/nonstationary/flrg.py @@ -18,7 +18,6 @@ class NonStationaryFLRG(flrg.FLRG): return (sets, t, w) - def __init__(self, LHS, **kwargs): super(NonStationaryFLRG, self).__init__(1, **kwargs) self.LHS = LHS diff --git a/pyFTS/models/nonstationary/nsfts.py b/pyFTS/models/nonstationary/nsfts.py index e344045..e534b48 100644 --- a/pyFTS/models/nonstationary/nsfts.py +++ b/pyFTS/models/nonstationary/nsfts.py @@ -27,6 +27,46 @@ class ConventionalNonStationaryFLRG(flrg.NonStationaryFLRG): return tmp + tmp2 +class WeightedNonStationaryFLRG(flrg.NonStationaryFLRG): + """First Order NonStationary Fuzzy Logical Relationship Group""" + + def __init__(self, LHS, **kwargs): + super(WeightedNonStationaryFLRG, self).__init__(1, **kwargs) + self.LHS = LHS + self.RHS = {} + self.count = 0.0 + self.strlhs = "" + self.w = None + + def get_key(self): + return self.LHS + + def append_rhs(self, c, **kwargs): + if c not in self.RHS: + self.RHS[c] = 1 + else: + self.RHS[c] += 1 + self.count += 1 + + def weights(self): + if self.w is None: + self.w = np.array([self.RHS[c] / self.count for c in self.RHS.keys()]) + return self.w + + def get_midpoint(self, sets, perturb): + mp = np.array([sets[c].get_midpoint(perturb) for c in self.RHS.keys()]) + midpoint = mp.dot(self.weights()) + return midpoint + + def __str__(self): + _str = "" + for k in self.RHS.keys(): + _str += ", " if len(_str) > 0 else "" + _str += k + " (" + str(round(self.RHS[k] / self.count, 3)) + ")" + + return self.get_key() + " -> " + _str + + class NonStationaryFTS(fts.FTS): """NonStationaryFTS Fuzzy Time Series""" def __init__(self, **kwargs): @@ -126,27 +166,24 @@ class NonStationaryFTS(fts.FTS): return perturb - def _fsset_key(self, ix): - return self.partitioner.ordered_sets[ix] - def _affected_sets(self, sample, perturb): if self.method == 'conditional': - affected_sets = [[ct, self.sets[self._fsset_key(ct)].membership(sample, perturb[ct])] - for ct in np.arange(len(self.partitioner.sets)) - if self.sets[self._fsset_key(ct)].membership(sample, perturb[ct]) > 0.0] - if len(affected_sets) == 0: + affected_sets = [[ct, self.partitioner.sets[key].membership(sample, perturb[ct])] + for ct, key in enumerate(self.partitioner.ordered_sets) + if self.partitioner.sets[key].membership(sample, perturb[ct]) > 0.0] + if len(affected_sets) == 0: if sample < self.partitioner.lower_set().get_lower(perturb[0]): affected_sets.append([0, 1]) elif sample > self.partitioner.upper_set().get_upper(perturb[-1]): affected_sets.append([len(self.sets) - 1, 1]) else: - affected_sets = [[ct, self.sets[self._fsset_key(ct)].membership(sample, perturb)] - for ct in np.arange(len(self.partitioner.sets)) - if self.sets[self._fsset_key(ct)].membership(sample, perturb) > 0.0] + affected_sets = [[ct, self.partitioner.sets[key].membership(sample, perturb)] + for ct, key in enumerate(self.partitioner.ordered_sets) + if self.partitioner.sets[key].membership(sample, perturb) > 0.0] if len(affected_sets) == 0: @@ -271,4 +308,52 @@ class NonStationaryFTS(fts.FTS): ret.append([sum(lower), sum(upper)]) - return ret \ No newline at end of file + return ret + + def __str__(self): + tmp = self.name + ":\n" + for r in self.flrgs: + tmp = "{0}{1}\n".format(tmp, str(self.flrgs[r])) + return tmp + + +class WeightedNonStationaryFTS(NonStationaryFTS): + """Weighted NonStationaryFTS Fuzzy Time Series""" + def __init__(self, **kwargs): + super(WeightedNonStationaryFTS, self).__init__(**kwargs) + self.name = "Weighted Non Stationary FTS" + self.shortname = "WNSFTS" + + def train(self, data, **kwargs): + + if self.method == 'unconditional': + window_size = kwargs.get('parameters', 1) + tmpdata = common.fuzzySeries(data, self.partitioner.sets, + self.partitioner.ordered_sets, + window_size, method='fuzzy') + else: + tmpdata = common.fuzzySeries(data, self.partitioner.sets, + self.partitioner.ordered_sets, + method='fuzzy', const_t=0) + + flrs = FLR.generate_recurrent_flrs(tmpdata) + self.generate_flrg(flrs) + + if self.method == 'conditional': + self.forecasts = self.forecast(data, no_update=True) + self.residuals = np.array(data[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(data[-self.memory_window:]).tolist() + + def generate_flrg(self, flrs, **kwargs): + for flr in flrs: + if flr.LHS.name in self.flrgs: + self.flrgs[flr.LHS.name].append_rhs(flr.RHS.name) + else: + self.flrgs[flr.LHS.name] = WeightedNonStationaryFLRG(flr.LHS.name) + self.flrgs[flr.LHS.name].append_rhs(flr.RHS.name) diff --git a/pyFTS/tests/nonstationary.py b/pyFTS/tests/nonstationary.py index a5b515d..76ca04c 100644 --- a/pyFTS/tests/nonstationary.py +++ b/pyFTS/tests/nonstationary.py @@ -30,9 +30,9 @@ test = dataset[1000:] from pyFTS.models.nonstationary import partitioners as nspart, nsfts, honsfts fs = nspart.simplenonstationary_gridpartitioner_builder(data=train,npart=35,transformation=None) print(fs) -model = honsfts.HighOrderNonStationaryFTS(partitioner=fs, order=2) -#model = nsfts.NonStationaryFTS(partitioner=fs) +#model = honsfts.HighOrderNonStationaryFTS(partitioner=fs, order=2) +model = nsfts.WeightedNonStationaryFTS(partitioner=fs) model.fit(train) -#print(model) +print(model) forecasts = model.predict(test) #print(forecasts) \ No newline at end of file