From fa231740a57e884006b70421c2e4f517775785dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=C3=B4nio=20C=C3=A2ndido?= Date: Fri, 29 Sep 2017 16:00:51 -0300 Subject: [PATCH] Nonstationary Fuzzy Sets --- pyFTS/nonstationary/common.py | 31 ++++++++++++++----- .../{pertubation.py => perturbation.py} | 0 pyFTS/nonstationary/util.py | 25 +++++++++++++++ pyFTS/partitioners/Util.py | 1 + pyFTS/seasonal/common.py | 5 +-- pyFTS/tests/nonstationary.py | 20 ++++++++++++ setup.py | 4 ++- 7 files changed, 75 insertions(+), 11 deletions(-) rename pyFTS/nonstationary/{pertubation.py => perturbation.py} (100%) create mode 100644 pyFTS/nonstationary/util.py create mode 100644 pyFTS/tests/nonstationary.py diff --git a/pyFTS/nonstationary/common.py b/pyFTS/nonstationary/common.py index cbffd59..9d4d34f 100644 --- a/pyFTS/nonstationary/common.py +++ b/pyFTS/nonstationary/common.py @@ -36,12 +36,19 @@ class MembershipFunction(object): self.width_params = kwargs.get("width_params", None) self.noise = kwargs.get("noise", None) self.noise_params = kwargs.get("noise_params", None) + self.cache = {} def perform_location(self, t, param): if self.location is None: return param - inc = self.location(t, self.location_params) + if not isinstance(self.location, (list,set)): + self.location = [self.location] + self.location_params = [self.location_params] + + l = len(self.location) + + inc = sum([self.location[k](t, self.location_params[k]) for k in np.arange(0,l)] ) if self.mf == Membership.gaussmf: #changes only the mean parameter @@ -59,7 +66,13 @@ class MembershipFunction(object): if self.width is None: return param - inc = self.width(t, self.width_params) + if not isinstance(self.width, (list, set)): + self.width = [self.width] + self.width_params = [self.width_params] + + l = len(self.width) + + inc = sum([self.width[k](t, self.width_params[k]) for k in np.arange(0, l)]) if self.mf == Membership.gaussmf: #changes only the variance parameter @@ -68,12 +81,12 @@ class MembershipFunction(object): #changes only the smooth parameter return [param[0] + inc, param[1]] elif self.mf == Membership.trimf: - return [param[0] + inc, param[1], param[2] - inc] + return [param[0] - inc, param[1], param[2] + inc] elif self.mf == Membership.trapmf: l = (param[3]-param[0]) rab = (param[1] - param[0]) / l rcd = (param[3] - param[2]) / l - return [param[0] + inc, param[1] + inc*rab, param[2] - inc*rcd, param[3] - inc] + return [param[0] - inc, param[1] - inc*rab, param[2] + inc*rcd, param[3] + inc] else: return param @@ -84,11 +97,13 @@ class MembershipFunction(object): :return: membership value of x at this fuzzy set """ - param = self.parameters - param = self.perform_location(t, param) - param = self.perform_width(t, param) + if t not in self.cache: + param = self.parameters + param = self.perform_location(t, param) + param = self.perform_width(t, param) + self.cache[t] = param - tmp = self.mf(x, param) + tmp = self.mf(x, self.cache[t]) if self.noise is not None: tmp += self.noise(t, self.noise_params) diff --git a/pyFTS/nonstationary/pertubation.py b/pyFTS/nonstationary/perturbation.py similarity index 100% rename from pyFTS/nonstationary/pertubation.py rename to pyFTS/nonstationary/perturbation.py diff --git a/pyFTS/nonstationary/util.py b/pyFTS/nonstationary/util.py new file mode 100644 index 0000000..07094c6 --- /dev/null +++ b/pyFTS/nonstationary/util.py @@ -0,0 +1,25 @@ +import numpy as np +import pandas as pd +import matplotlib as plt +import matplotlib.colors as pltcolors +import matplotlib.pyplot as plt +from pyFTS.common import Membership, Util + + +def plot_sets(uod, sets, num=10, tam=[5, 5], colors=None, save=False, file=None): + ticks = [] + fig, axes = plt.subplots(nrows=1, ncols=1, figsize=tam) + for t in np.arange(0,num,1): + for ct, set in enumerate(sets): + x = [2*t + set.membership(v, t) for v in uod] + if colors is not None: c = colors[ct] + axes.plot(x, uod, c=c) + ticks.extend(["t+"+str(t),""]) + + axes.set_ylabel("Universe of Discourse") + axes.set_xlabel("Time") + plt.xticks([k for k in np.arange(0,2*num,1)], ticks, rotation='vertical') + + plt.tight_layout() + + Util.showAndSaveImage(fig, file, save) diff --git a/pyFTS/partitioners/Util.py b/pyFTS/partitioners/Util.py index 3056f74..8893ec5 100644 --- a/pyFTS/partitioners/Util.py +++ b/pyFTS/partitioners/Util.py @@ -11,6 +11,7 @@ all_methods = [Grid.GridPartitioner, Entropy.EntropyPartitioner, FCM.FCMPartitio mfs = [Membership.trimf, Membership.gaussmf, Membership.trapmf] + def plot_sets(data, sets, titles, tam=[12, 10], save=False, file=None): num = len(sets) #fig = plt.figure(figsize=tam) diff --git a/pyFTS/seasonal/common.py b/pyFTS/seasonal/common.py index 07a5edb..cdc44d5 100644 --- a/pyFTS/seasonal/common.py +++ b/pyFTS/seasonal/common.py @@ -1,7 +1,8 @@ import numpy as np import pandas as pd from enum import Enum -from pyFTS.common import FuzzySet +from pyFTS.common import FuzzySet, Membership +from pyFTS.partitioners import partitioner, Grid class DateTime(Enum): @@ -47,4 +48,4 @@ class FuzzySet(FuzzySet.FuzzySet): def membership(self, x): dp = strip_datepart(x, self.datepart) - return self.mf.membership(dp) \ No newline at end of file + return self.mf.membership(dp) diff --git a/pyFTS/tests/nonstationary.py b/pyFTS/tests/nonstationary.py new file mode 100644 index 0000000..1f96337 --- /dev/null +++ b/pyFTS/tests/nonstationary.py @@ -0,0 +1,20 @@ +import numpy as np +from pyFTS.common import Membership +from pyFTS.nonstationary import common,pertubation,util +import importlib + +importlib.reload(util) + +uod = np.arange(0,20,0.1) + +kwargs = {'location': pertubation.linear, 'location_params': [1,0], + 'width': pertubation.linear, 'width_params': [1,0]} + +mf1 = common.MembershipFunction('A1',Membership.trimf,[0,1,2], **kwargs) +mf2 = common.MembershipFunction('A2',Membership.trimf,[1,2,3], **kwargs) +mf3 = common.MembershipFunction('A3',Membership.trimf,[2,3,4], **kwargs) +mf4 = common.MembershipFunction('A4',Membership.trimf,[3,4,5], **kwargs) + +sets = [mf1, mf2, mf3, mf4] + +util.plot_sets(uod, sets) diff --git a/setup.py b/setup.py index b9a18d4..8b4997f 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,9 @@ from distutils.core import setup setup( name = 'pyFTS', - packages = ['pyFTS','pyFTS.benchmarks','pyFTS.common','pyFTS.data', 'pyFTS.ensemble','pyFTS.models','pyFTS.models.seasonal','pyFTS.partitioners','pyFTS.probabilistic','pyFTS.tests'], + packages = ['pyFTS','pyFTS.benchmarks','pyFTS.common','pyFTS.data', 'pyFTS.ensemble', + 'pyFTS.models','pyFTS.seasonal','pyFTS.partitioners','pyFTS.probabilistic', + 'pyFTS.tests','pyFTS.nonstationary'], package_data = {'benchmarks':['*'], 'common':['*'], 'data':['*'], 'ensemble':['*'], 'models':['*'], 'seasonal':['*'], 'partitioners':['*'], 'probabilistic':['*'], 'tests':['*']}, version = '1.1.1', description = 'Fuzzy Time Series for Python',