Non Stationary Fuzzy Time Series - NSFTS
This commit is contained in:
parent
80583cc202
commit
b3db1a60a3
@ -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)
|
||||||
|
@ -36,32 +36,40 @@ 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
|
||||||
:param fuzzyData: ordered list of fuzzy sets
|
:param fuzzyData: ordered list of fuzzy sets
|
||||||
:return: ordered list of FLR
|
:return: ordered list of FLR
|
||||||
"""
|
"""
|
||||||
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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user