- Non Stationary Fuzzy Sets
This commit is contained in:
parent
fa231740a5
commit
c38a3747f0
@ -8,6 +8,8 @@ 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, Membership
|
from pyFTS.common import FuzzySet, Membership
|
||||||
|
from pyFTS.partitioners import partitioner
|
||||||
|
from pyFTS.nonstationary import perturbation
|
||||||
|
|
||||||
|
|
||||||
class MembershipFunction(object):
|
class MembershipFunction(object):
|
||||||
@ -32,23 +34,31 @@ class MembershipFunction(object):
|
|||||||
self.parameters = parameters
|
self.parameters = parameters
|
||||||
self.location = kwargs.get("location", None)
|
self.location = kwargs.get("location", None)
|
||||||
self.location_params = kwargs.get("location_params", None)
|
self.location_params = kwargs.get("location_params", None)
|
||||||
|
self.location_roots = kwargs.get("location_roots", 0)
|
||||||
self.width = kwargs.get("width", None)
|
self.width = kwargs.get("width", None)
|
||||||
self.width_params = kwargs.get("width_params", None)
|
self.width_params = kwargs.get("width_params", None)
|
||||||
|
self.width_roots = kwargs.get("width_roots", 0)
|
||||||
self.noise = kwargs.get("noise", None)
|
self.noise = kwargs.get("noise", None)
|
||||||
self.noise_params = kwargs.get("noise_params", None)
|
self.noise_params = kwargs.get("noise_params", None)
|
||||||
self.cache = {}
|
self.perturbated_parameters = {}
|
||||||
|
|
||||||
|
if self.location is not None and not isinstance(self.location, (list,set)):
|
||||||
|
self.location = [self.location]
|
||||||
|
self.location_params = [self.location_params]
|
||||||
|
self.location_roots = [self.location_roots]
|
||||||
|
|
||||||
|
if self.width is not None and not isinstance(self.width, (list, set)):
|
||||||
|
self.width = [self.width]
|
||||||
|
self.width_params = [self.width_params]
|
||||||
|
self.width_roots = [self.width_roots]
|
||||||
|
|
||||||
def perform_location(self, t, param):
|
def perform_location(self, t, param):
|
||||||
if self.location is None:
|
if self.location is None:
|
||||||
return param
|
return param
|
||||||
|
|
||||||
if not isinstance(self.location, (list,set)):
|
|
||||||
self.location = [self.location]
|
|
||||||
self.location_params = [self.location_params]
|
|
||||||
|
|
||||||
l = len(self.location)
|
l = len(self.location)
|
||||||
|
|
||||||
inc = sum([self.location[k](t, self.location_params[k]) for k in np.arange(0,l)] )
|
inc = sum([self.location[k](t + self.location_roots[k], self.location_params[k]) for k in np.arange(0,l)] )
|
||||||
|
|
||||||
if self.mf == Membership.gaussmf:
|
if self.mf == Membership.gaussmf:
|
||||||
#changes only the mean parameter
|
#changes only the mean parameter
|
||||||
@ -66,13 +76,9 @@ class MembershipFunction(object):
|
|||||||
if self.width is None:
|
if self.width is None:
|
||||||
return param
|
return param
|
||||||
|
|
||||||
if not isinstance(self.width, (list, set)):
|
|
||||||
self.width = [self.width]
|
|
||||||
self.width_params = [self.width_params]
|
|
||||||
|
|
||||||
l = len(self.width)
|
l = len(self.width)
|
||||||
|
|
||||||
inc = sum([self.width[k](t, self.width_params[k]) for k in np.arange(0, l)])
|
inc = sum([self.width[k](t + self.width_roots[k], self.width_params[k]) for k in np.arange(0, l)])
|
||||||
|
|
||||||
if self.mf == Membership.gaussmf:
|
if self.mf == Membership.gaussmf:
|
||||||
#changes only the variance parameter
|
#changes only the variance parameter
|
||||||
@ -81,7 +87,8 @@ class MembershipFunction(object):
|
|||||||
#changes only the smooth parameter
|
#changes only the smooth parameter
|
||||||
return [param[0] + inc, param[1]]
|
return [param[0] + inc, param[1]]
|
||||||
elif self.mf == Membership.trimf:
|
elif self.mf == Membership.trimf:
|
||||||
return [param[0] - inc, param[1], param[2] + inc]
|
tmp = inc/2
|
||||||
|
return [param[0] - tmp, param[1], param[2] + tmp]
|
||||||
elif self.mf == Membership.trapmf:
|
elif self.mf == Membership.trapmf:
|
||||||
l = (param[3]-param[0])
|
l = (param[3]-param[0])
|
||||||
rab = (param[1] - param[0]) / l
|
rab = (param[1] - param[0]) / l
|
||||||
@ -97,19 +104,83 @@ class MembershipFunction(object):
|
|||||||
:return: membership value of x at this fuzzy set
|
:return: membership value of x at this fuzzy set
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if t not in self.cache:
|
self.perturbate_parameters(t)
|
||||||
param = self.parameters
|
|
||||||
param = self.perform_location(t, param)
|
|
||||||
param = self.perform_width(t, param)
|
|
||||||
self.cache[t] = param
|
|
||||||
|
|
||||||
tmp = self.mf(x, self.cache[t])
|
tmp = self.mf(x, self.perturbated_parameters[t])
|
||||||
|
|
||||||
if self.noise is not None:
|
if self.noise is not None:
|
||||||
tmp += self.noise(t, self.noise_params)
|
tmp += self.noise(t, self.noise_params)
|
||||||
|
|
||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
|
def perturbate_parameters(self, t):
|
||||||
|
if t not in self.perturbated_parameters:
|
||||||
|
param = self.parameters
|
||||||
|
param = self.perform_location(t, param)
|
||||||
|
param = self.perform_width(t, param)
|
||||||
|
self.perturbated_parameters[t] = param
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
tmp = ""
|
||||||
|
if self.location is not None:
|
||||||
|
tmp += "Loc. Pert.: "
|
||||||
|
for ct, f in enumerate(self.location):
|
||||||
|
tmp += str(f.__name__) + "(" + str(self.location_params[ct]) + ") "
|
||||||
|
if self.width is not None:
|
||||||
|
tmp += "Wid. Pert.: "
|
||||||
|
for ct, f in enumerate(self.width):
|
||||||
|
tmp += str(f.__name__) + "(" + str(self.width_params[ct]) + ") "
|
||||||
|
return str(self.mf.__name__) + "(" + str(self.parameters) + ") " + tmp
|
||||||
|
|
||||||
|
def get_midpoint(self, t):
|
||||||
|
|
||||||
|
self.perturbate_parameters(t)
|
||||||
|
|
||||||
|
if self.mf == Membership.gaussmf:
|
||||||
|
return self.perturbated_parameters[t][0]
|
||||||
|
elif self.mf == Membership.sigmf:
|
||||||
|
return self.perturbated_parameters[t][1]
|
||||||
|
elif self.mf == Membership.trimf:
|
||||||
|
return self.perturbated_parameters[t][1]
|
||||||
|
elif self.mf == Membership.trapmf:
|
||||||
|
param = self.perturbated_parameters[t]
|
||||||
|
return (param[2] - param[1]) / 2
|
||||||
|
else:
|
||||||
|
return self.perturbated_parameters[t]
|
||||||
|
|
||||||
|
def get_lower(self, t):
|
||||||
|
|
||||||
|
self.perturbate_parameters(t)
|
||||||
|
param = self.perturbated_parameters[t]
|
||||||
|
|
||||||
|
if self.mf == Membership.gaussmf:
|
||||||
|
return param[0] - 3*param[1]
|
||||||
|
elif self.mf == Membership.sigmf:
|
||||||
|
return param[0] - param[1]
|
||||||
|
elif self.mf == Membership.trimf:
|
||||||
|
return param[0]
|
||||||
|
elif self.mf == Membership.trapmf:
|
||||||
|
return param[0]
|
||||||
|
else:
|
||||||
|
return param
|
||||||
|
|
||||||
|
def get_upper(self, t):
|
||||||
|
|
||||||
|
self.perturbate_parameters(t)
|
||||||
|
param = self.perturbated_parameters[t]
|
||||||
|
|
||||||
|
if self.mf == Membership.gaussmf:
|
||||||
|
return param[0] + 3*param[1]
|
||||||
|
elif self.mf == Membership.sigmf:
|
||||||
|
return param[0] + param[1]
|
||||||
|
elif self.mf == Membership.trimf:
|
||||||
|
return param[2]
|
||||||
|
elif self.mf == Membership.trapmf:
|
||||||
|
return param[3]
|
||||||
|
else:
|
||||||
|
return param
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FuzzySet(FuzzySet.FuzzySet):
|
class FuzzySet(FuzzySet.FuzzySet):
|
||||||
"""
|
"""
|
||||||
@ -127,4 +198,105 @@ class FuzzySet(FuzzySet.FuzzySet):
|
|||||||
def membership(self, x, t):
|
def membership(self, x, t):
|
||||||
return self.mf.membership(x,t)
|
return self.mf.membership(x,t)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name + ": " + str(self.mf)
|
||||||
|
|
||||||
|
|
||||||
|
class PolynomialNonStationaryPartitioner(partitioner.Partitioner):
|
||||||
|
"""
|
||||||
|
Non Stationary Universe of Discourse Partitioner
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, data, part, **kwargs):
|
||||||
|
""""""
|
||||||
|
super(PolynomialNonStationaryPartitioner, self).__init__(name=part.name, data=data, npart=part.partitions,
|
||||||
|
func=part.membership_function, names=part.setnames,
|
||||||
|
prefix=part.prefix, transformation=part.transformation,
|
||||||
|
indexer=part.indexer)
|
||||||
|
|
||||||
|
self.sets = []
|
||||||
|
|
||||||
|
loc_params, wid_params = self.get_polynomial_perturbations(data, **kwargs)
|
||||||
|
|
||||||
|
for ct, set in enumerate(part.sets):
|
||||||
|
loc_roots = np.roots(loc_params[ct])[0]
|
||||||
|
wid_roots = np.roots(wid_params[ct])[0]
|
||||||
|
mf = MembershipFunction(name=set.name, mf=set.mf, parameters=set.parameters,
|
||||||
|
location=perturbation.polynomial,
|
||||||
|
location_params=loc_params[ct],
|
||||||
|
location_roots=loc_roots, #**kwargs)
|
||||||
|
width=perturbation.polynomial,
|
||||||
|
width_params=wid_params[ct],
|
||||||
|
width_roots=wid_roots, **kwargs)
|
||||||
|
tmp = FuzzySet(set.name, mf, **kwargs)
|
||||||
|
|
||||||
|
self.sets.append(tmp)
|
||||||
|
|
||||||
|
def poly_width(self, par1, par2, rng, deg):
|
||||||
|
a = np.polyval(par1, rng)
|
||||||
|
b = np.polyval(par2, rng)
|
||||||
|
diff = [b[k] - a[k] for k in rng]
|
||||||
|
tmp = np.polyfit(rng, diff, deg=deg)
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
def get_polynomial_perturbations(self, data, **kwargs):
|
||||||
|
w = kwargs.get("window_size", int(len(data) / 5))
|
||||||
|
deg = kwargs.get("degree", 2)
|
||||||
|
xmax = [0]
|
||||||
|
tmax = [0]
|
||||||
|
xmin = [0]
|
||||||
|
tmin = [0]
|
||||||
|
lengs = [0]
|
||||||
|
tlengs = [0]
|
||||||
|
l = len(data)
|
||||||
|
|
||||||
|
for i in np.arange(0, l, w):
|
||||||
|
sample = data[i:i + w]
|
||||||
|
tx = max(sample)
|
||||||
|
xmax.append(tx)
|
||||||
|
tmax.append(np.ravel(np.argwhere(data == tx)).tolist()[0])
|
||||||
|
tn = min(sample)
|
||||||
|
xmin.append(tn)
|
||||||
|
tmin.append(np.ravel(np.argwhere(data == tn)).tolist()[0])
|
||||||
|
lengs.append((tx - tn)/self.partitions)
|
||||||
|
tlengs.append(i)
|
||||||
|
|
||||||
|
|
||||||
|
cmax = np.polyfit(tmax, xmax, deg=deg)
|
||||||
|
#cmax = cmax.tolist()
|
||||||
|
cmin = np.polyfit(tmin, xmin, deg=deg)
|
||||||
|
#cmin = cmin.tolist()
|
||||||
|
|
||||||
|
|
||||||
|
cmed = []
|
||||||
|
|
||||||
|
for d in np.arange(0, deg + 1):
|
||||||
|
cmed.append(np.linspace(cmin[d], cmax[d], self.partitions)[1:self.partitions - 1])
|
||||||
|
|
||||||
|
loc_params = [cmin.tolist()]
|
||||||
|
for i in np.arange(0, self.partitions - 2):
|
||||||
|
tmp = [cmed[k][i] for k in np.arange(0, deg + 1)]
|
||||||
|
loc_params.append(tmp)
|
||||||
|
loc_params.append(cmax.tolist())
|
||||||
|
|
||||||
|
rng = np.arange(0, l)
|
||||||
|
|
||||||
|
clen = []
|
||||||
|
|
||||||
|
for i in np.arange(1, self.partitions-1):
|
||||||
|
tmp = self.poly_width(loc_params[i - 1], loc_params[i + 1], rng, deg)
|
||||||
|
clen.append(tmp)
|
||||||
|
|
||||||
|
tmp = self.poly_width(loc_params[0], loc_params[1], rng, deg)
|
||||||
|
clen.insert(0, tmp)
|
||||||
|
|
||||||
|
tmp = self.poly_width(loc_params[self.partitions-2], loc_params[self.partitions-1], rng, deg)
|
||||||
|
clen.append(tmp)
|
||||||
|
|
||||||
|
tmp = (loc_params, clen)
|
||||||
|
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
def build(self, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@ -8,15 +8,11 @@ from pyFTS.common import FuzzySet, Membership
|
|||||||
|
|
||||||
|
|
||||||
def linear(x, parameters):
|
def linear(x, parameters):
|
||||||
return parameters[0]*x + parameters[1]
|
return np.polyval(parameters, x)
|
||||||
|
|
||||||
|
|
||||||
def polynomial(x, parameters):
|
def polynomial(x, parameters):
|
||||||
n = len(parameters)
|
return np.polyval(parameters, x)
|
||||||
tmp = 0.0
|
|
||||||
for k in np.arange(0,n):
|
|
||||||
tmp += parameters[k] * x**k
|
|
||||||
return tmp
|
|
||||||
|
|
||||||
|
|
||||||
def exponential(x, parameters):
|
def exponential(x, parameters):
|
||||||
@ -24,4 +20,4 @@ def exponential(x, parameters):
|
|||||||
|
|
||||||
|
|
||||||
def periodic(x, parameters):
|
def periodic(x, parameters):
|
||||||
return np.sin(x * parameters[0] + parameters[1])
|
return parameters[0] * np.sin(x * parameters[1])
|
@ -6,19 +6,22 @@ import matplotlib.pyplot as plt
|
|||||||
from pyFTS.common import Membership, Util
|
from pyFTS.common import Membership, Util
|
||||||
|
|
||||||
|
|
||||||
def plot_sets(uod, sets, num=10, tam=[5, 5], colors=None, save=False, file=None):
|
def plot_sets(uod, sets, start=0, end=10, tam=[5, 5], colors=None, save=False, file=None):
|
||||||
ticks = []
|
ticks = []
|
||||||
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=tam)
|
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=tam)
|
||||||
for t in np.arange(0,num,1):
|
for t in np.arange(start,end,1):
|
||||||
for ct, set in enumerate(sets):
|
for ct, set in enumerate(sets):
|
||||||
x = [2*t + set.membership(v, t) for v in uod]
|
set.membership(0, t)
|
||||||
if colors is not None: c = colors[ct]
|
param = set.mf.perturbated_parameters[t]
|
||||||
axes.plot(x, uod, c=c)
|
|
||||||
|
if set.mf.mf == Membership.trimf:
|
||||||
|
axes.plot([t, t+1, t], param)
|
||||||
|
|
||||||
ticks.extend(["t+"+str(t),""])
|
ticks.extend(["t+"+str(t),""])
|
||||||
|
|
||||||
axes.set_ylabel("Universe of Discourse")
|
axes.set_ylabel("Universe of Discourse")
|
||||||
axes.set_xlabel("Time")
|
axes.set_xlabel("Time")
|
||||||
plt.xticks([k for k in np.arange(0,2*num,1)], ticks, rotation='vertical')
|
plt.xticks([k for k in np.arange(0,2*end,1)], ticks, rotation='vertical')
|
||||||
|
|
||||||
plt.tight_layout()
|
plt.tight_layout()
|
||||||
|
|
||||||
|
@ -1,20 +1,38 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from pyFTS.common import Membership
|
from pyFTS.common import Membership
|
||||||
from pyFTS.nonstationary import common,pertubation,util
|
from pyFTS.nonstationary import common,perturbation,util
|
||||||
import importlib
|
from pyFTS.partitioners import Grid
|
||||||
|
|
||||||
importlib.reload(util)
|
|
||||||
|
|
||||||
uod = np.arange(0,20,0.1)
|
def generate_heteroskedastic_linear(mu_ini, sigma_ini, mu_inc, sigma_inc, it=10, num=35):
|
||||||
|
mu = mu_ini
|
||||||
|
sigma = sigma_ini
|
||||||
|
ret = []
|
||||||
|
for k in np.arange(0,it):
|
||||||
|
ret.extend(np.random.normal(mu, sigma, num))
|
||||||
|
mu += mu_inc
|
||||||
|
sigma += sigma_inc
|
||||||
|
return ret
|
||||||
|
|
||||||
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)
|
lmv1 = generate_heteroskedastic_linear(1,0.1,1,0.3)
|
||||||
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)
|
|
||||||
|
ns = 5 #number of fuzzy sets
|
||||||
|
ts = 200
|
||||||
|
train = lmv1[:ts]
|
||||||
|
w = 25
|
||||||
|
deg = 4
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
util.plot_sets(uod, fs.sets,tam=[15, 5], start=0, end=10)
|
||||||
|
|
||||||
|
for set in fs.sets:
|
||||||
|
print(set)
|
||||||
|
Loading…
Reference in New Issue
Block a user