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):
self.LHS = LHS
self.RHS = set()
self.midpoint = None
self.lower = None
self.upper = None
def append(self, c):
self.RHS.add(c)

View File

@ -36,20 +36,6 @@ class IndexedFLR(FLR):
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):
"""
Create a ordered FLR set from a list of fuzzy sets with recurrence
@ -58,10 +44,32 @@ def generateRecurrentFLRs(fuzzyData):
"""
flrs = []
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
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):
"""
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
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.nonstationary import perturbation
@ -279,3 +279,30 @@ class PolynomialNonStationaryPartitioner(partitioner.Partitioner):
def build(self, data):
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
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"""
def __init__(self, name, **kwargs):
super(NonStationaryFTS, self).__init__(1, "NSFTS " + name, **kwargs)
self.name = "Non Stationary FTS"
self.detail = ""
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
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
import matplotlib.pyplot as plt
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)
ns = 5 #number of fuzzy sets
ts = 200
train = lmv1[:ts]
test = lmv1[ts:]
w = 25
deg = 4
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=[10,5])
tmp_fs = Grid.GridPartitioner(train[:35], 10)
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:
print(set)
tmp = nsfts1.forecast(test, time_displacement=200)
axes.plot(test)
axes.plot(tmp)
print(tmp)