Non Stationary Fuzzy Time Series - NSFTS

This commit is contained in:
Petrônio Cândido 2017-10-05 14:30:57 -03:00
parent 80583cc202
commit b3db1a60a3
5 changed files with 182 additions and 27 deletions

View File

@ -14,6 +14,9 @@ class ConventionalFLRG(object):
def __init__(self, LHS): def __init__(self, LHS):
self.LHS = LHS self.LHS = LHS
self.RHS = set() self.RHS = set()
self.midpoint = None
self.lower = None
self.upper = None
def append(self, c): def append(self, c):
self.RHS.add(c) self.RHS.add(c)

View File

@ -36,20 +36,6 @@ class IndexedFLR(FLR):
return str(self.index) + ": "+ self.LHS.name + " -> " + self.RHS.name return str(self.index) + ": "+ self.LHS.name + " -> " + self.RHS.name
def generateNonRecurrentFLRs(fuzzyData):
"""
Create a ordered FLR set from a list of fuzzy sets without recurrence
:param fuzzyData: ordered list of fuzzy sets
:return: ordered list of FLR
"""
flrs = {}
for i in range(2,len(fuzzyData)):
tmp = FLR(fuzzyData[i-1],fuzzyData[i])
flrs[str(tmp)] = tmp
ret = [value for key, value in flrs.items()]
return ret
def generateRecurrentFLRs(fuzzyData): def generateRecurrentFLRs(fuzzyData):
""" """
Create a ordered FLR set from a list of fuzzy sets with recurrence Create a ordered FLR set from a list of fuzzy sets with recurrence
@ -58,10 +44,32 @@ def generateRecurrentFLRs(fuzzyData):
""" """
flrs = [] flrs = []
for i in np.arange(1,len(fuzzyData)): for i in np.arange(1,len(fuzzyData)):
flrs.append(FLR(fuzzyData[i-1],fuzzyData[i])) lhs = fuzzyData[i - 1]
rhs = fuzzyData[i]
if isinstance(lhs, list) and isinstance(rhs, list):
for l in lhs:
for r in rhs:
tmp = FLR(l, r)
flrs.append(tmp)
else:
tmp = FLR.FLR(lhs,rhs)
flrs.append(tmp)
return flrs return flrs
def generateNonRecurrentFLRs(fuzzyData):
"""
Create a ordered FLR set from a list of fuzzy sets without recurrence
:param fuzzyData: ordered list of fuzzy sets
:return: ordered list of FLR
"""
flrs = generateRecurrentFLRs(fuzzyData)
tmp = {}
for flr in flrs: tmp[str(flr)] = flr
ret = [value for key, value in tmp.items()]
return ret
def generateIndexedFLRs(sets, indexer, data, transformation=None): def generateIndexedFLRs(sets, indexer, data, transformation=None):
""" """
Create a season-indexed ordered FLR set from a list of fuzzy sets with recurrence Create a season-indexed ordered FLR set from a list of fuzzy sets with recurrence

View File

@ -7,7 +7,7 @@ IEEE Transactions on Fuzzy Systems, v. 16, n. 4, p. 1072-1086, 2008.
import numpy as np import numpy as np
from pyFTS import * from pyFTS import *
from pyFTS.common import FuzzySet as FS, Membership from pyFTS.common import FuzzySet as FS, Membership, FLR
from pyFTS.partitioners import partitioner from pyFTS.partitioners import partitioner
from pyFTS.nonstationary import perturbation from pyFTS.nonstationary import perturbation
@ -279,3 +279,30 @@ class PolynomialNonStationaryPartitioner(partitioner.Partitioner):
def build(self, data): def build(self, data):
pass pass
def fuzzify(inst, t, fuzzySets):
"""
Calculate the membership values for a data point given nonstationary fuzzy sets
:param inst: data points
:param t: time displacement of the instance
:param fuzzySets: list of fuzzy sets
:return: array of membership values
"""
ret = []
if not isinstance(inst, list):
inst = [inst]
for t, i in enumerate(inst):
mv = np.array([fs.membership(i, t) for fs in fuzzySets])
ret.append(mv)
return ret
def fuzzySeries(data, fuzzySets):
fts = []
for t, i in enumerate(data):
mv = np.array([fs.membership(i, t) for fs in fuzzySets])
ix = np.ravel(np.argwhere(mv > 0.0))
sets = [fuzzySets[i] for i in ix]
fts.append(sets)
return fts

View File

@ -1,12 +1,124 @@
import numpy as np import numpy as np
from pyFTS.common import FuzzySet, FLR from pyFTS.common import FuzzySet, FLR
from pyFTS import fts, sfts from pyFTS import fts, chen
from pyFTS.nonstationary import common
class NonStationaryFTS(sfts.SeasonalFTS): class NonStationaryFLRG(chen.ConventionalFLRG):
"""First Order NonStationary Fuzzy Logical Relationship Group"""
def __init__(self, LHS):
super(NonStationaryFLRG, self).__init__(LHS)
def get_midpoint(self, t):
if self.midpoint is None:
tmp = []
for r in self.RHS:
tmp.append(r.get_midpoint(t))
self.midpoint = sum(tmp)/len(tmp)
return self.midpoint
def get_lower(self, t):
if self.lower is None:
tmp = []
for r in self.RHS:
tmp.append(r.get_midpoint(t))
self.lower = min(tmp)
return self.lower
def get_upper(self, t):
if self.upper is None:
tmp = []
for r in self.RHS:
tmp.append(r.get_midpoint(t))
self.upper = max(tmp)
return self.upper
class NonStationaryFTS(fts.FTS):
"""NonStationaryFTS Fuzzy Time Series""" """NonStationaryFTS Fuzzy Time Series"""
def __init__(self, name, **kwargs): def __init__(self, name, **kwargs):
super(NonStationaryFTS, self).__init__(1, "NSFTS " + name, **kwargs) super(NonStationaryFTS, self).__init__(1, "NSFTS " + name, **kwargs)
self.name = "Non Stationary FTS" self.name = "Non Stationary FTS"
self.detail = "" self.detail = ""
self.flrgs = {} self.flrgs = {}
def generateFLRG(self, flrs):
flrgs = {}
for flr in flrs:
if flr.LHS.name in flrgs:
flrgs[flr.LHS.name].append(flr.RHS)
else:
flrgs[flr.LHS.name] = NonStationaryFLRG(flr.LHS)
flrgs[flr.LHS.name].append(flr.RHS)
return (flrgs)
def train(self, data, sets=None,order=1,parameters=None):
if sets is not None:
self.sets = sets
else:
self.sets = self.partitioner.sets
ndata = self.doTransformations(data)
tmpdata = common.fuzzySeries(ndata, self.sets)
flrs = FLR.generateNonRecurrentFLRs(tmpdata)
self.flrgs = self.generateFLRG(flrs)
def forecast(self, data, **kwargs):
time_displacement = kwargs.get("time_displacement",0)
ndata = np.array(self.doTransformations(data))
l = len(ndata)
ret = []
for k in np.arange(0, l):
tdisp = k + time_displacement
affected_sets = [ [set, set.membership(ndata[k], tdisp)]
for set in self.sets if set.membership(ndata[k], tdisp) > 0.0]
tmp = []
for aset in affected_sets:
if aset[0] in self.flrgs:
tmp.append(self.flrgs[aset[0].name].get_midpoint(tdisp) * aset[1])
else:
tmp.append(aset[0].get_midpoint(tdisp) * aset[1])
ret.append(sum(tmp))
ret = self.doInverseTransformations(ret, params=[data[self.order - 1:]])
return ret
def forecastInterval(self, data, **kwargs):
time_displacement = kwargs.get("time_displacement",0)
ndata = np.array(self.doTransformations(data))
l = len(ndata)
ret = []
for k in np.arange(0, l):
tdisp = k + time_displacement
affected_sets = [ [set.name, set.membership(ndata[k], tdisp)]
for set in self.sets if set.membership(ndata[k], tdisp) > 0.0]
upper = []
lower = []
for aset in affected_sets:
lower.append(self.flrgs[aset[0]].get_lower(tdisp) * aset[1])
upper.append(self.flrgs[aset[0]].get_upper(tdisp) * aset[1])
ret.append([sum(lower), sum(upper)])
ret = self.doInverseTransformations(ret, params=[data[self.order - 1:]])
return ret

View File

@ -1,7 +1,8 @@
import numpy as np import numpy as np
from pyFTS.common import Membership from pyFTS.common import Membership
from pyFTS.nonstationary import common,perturbation,util from pyFTS.nonstationary import common,perturbation,util,nsfts
from pyFTS.partitioners import Grid from pyFTS.partitioners import Grid
import matplotlib.pyplot as plt
def generate_heteroskedastic_linear(mu_ini, sigma_ini, mu_inc, sigma_inc, it=10, num=35): def generate_heteroskedastic_linear(mu_ini, sigma_ini, mu_inc, sigma_inc, it=10, num=35):
@ -17,22 +18,26 @@ def generate_heteroskedastic_linear(mu_ini, sigma_ini, mu_inc, sigma_inc, it=10,
lmv1 = generate_heteroskedastic_linear(1,0.1,1,0.3) lmv1 = generate_heteroskedastic_linear(1,0.1,1,0.3)
ns = 5 #number of fuzzy sets ns = 5 #number of fuzzy sets
ts = 200 ts = 200
train = lmv1[:ts] train = lmv1[:ts]
test = lmv1[ts:]
w = 25 w = 25
deg = 4 deg = 4
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=[10,5])
tmp_fs = Grid.GridPartitioner(train[:35], 10) tmp_fs = Grid.GridPartitioner(train[:35], 10)
fs = common.PolynomialNonStationaryPartitioner(train, tmp_fs, window_size=35, degree=1) fs = common.PolynomialNonStationaryPartitioner(train, tmp_fs, window_size=35, degree=1)
uod = np.arange(0, 2, step=0.02) nsfts1 = nsfts.NonStationaryFTS("", partitioner=fs)
util.plot_sets(uod, fs.sets,tam=[15, 5], start=0, end=10) nsfts1.train(train[:35])
for set in fs.sets: tmp = nsfts1.forecast(test, time_displacement=200)
print(set)
axes.plot(test)
axes.plot(tmp)
print(tmp)