- 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
|
||||
from pyFTS import *
|
||||
from pyFTS.common import FuzzySet, Membership
|
||||
from pyFTS.partitioners import partitioner
|
||||
from pyFTS.nonstationary import perturbation
|
||||
|
||||
|
||||
class MembershipFunction(object):
|
||||
@ -32,23 +34,31 @@ class MembershipFunction(object):
|
||||
self.parameters = parameters
|
||||
self.location = kwargs.get("location", 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_params = kwargs.get("width_params", None)
|
||||
self.width_roots = kwargs.get("width_roots", 0)
|
||||
self.noise = kwargs.get("noise", 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):
|
||||
if self.location is None:
|
||||
return param
|
||||
|
||||
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)] )
|
||||
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:
|
||||
#changes only the mean parameter
|
||||
@ -66,13 +76,9 @@ class MembershipFunction(object):
|
||||
if self.width is None:
|
||||
return param
|
||||
|
||||
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)])
|
||||
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:
|
||||
#changes only the variance parameter
|
||||
@ -81,7 +87,8 @@ 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]
|
||||
tmp = inc/2
|
||||
return [param[0] - tmp, param[1], param[2] + tmp]
|
||||
elif self.mf == Membership.trapmf:
|
||||
l = (param[3]-param[0])
|
||||
rab = (param[1] - param[0]) / l
|
||||
@ -97,19 +104,83 @@ class MembershipFunction(object):
|
||||
:return: membership value of x at this fuzzy set
|
||||
"""
|
||||
|
||||
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
|
||||
self.perturbate_parameters(t)
|
||||
|
||||
tmp = self.mf(x, self.cache[t])
|
||||
tmp = self.mf(x, self.perturbated_parameters[t])
|
||||
|
||||
if self.noise is not None:
|
||||
tmp += self.noise(t, self.noise_params)
|
||||
|
||||
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):
|
||||
"""
|
||||
@ -127,4 +198,105 @@ class FuzzySet(FuzzySet.FuzzySet):
|
||||
def membership(self, 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):
|
||||
return parameters[0]*x + parameters[1]
|
||||
return np.polyval(parameters, x)
|
||||
|
||||
|
||||
def polynomial(x, parameters):
|
||||
n = len(parameters)
|
||||
tmp = 0.0
|
||||
for k in np.arange(0,n):
|
||||
tmp += parameters[k] * x**k
|
||||
return tmp
|
||||
return np.polyval(parameters, x)
|
||||
|
||||
|
||||
def exponential(x, parameters):
|
||||
@ -24,4 +20,4 @@ def exponential(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
|
||||
|
||||
|
||||
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 = []
|
||||
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):
|
||||
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)
|
||||
set.membership(0, t)
|
||||
param = set.mf.perturbated_parameters[t]
|
||||
|
||||
if set.mf.mf == Membership.trimf:
|
||||
axes.plot([t, t+1, t], param)
|
||||
|
||||
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.xticks([k for k in np.arange(0,2*end,1)], ticks, rotation='vertical')
|
||||
|
||||
plt.tight_layout()
|
||||
|
||||
|
@ -1,20 +1,38 @@
|
||||
import numpy as np
|
||||
from pyFTS.common import Membership
|
||||
from pyFTS.nonstationary import common,pertubation,util
|
||||
import importlib
|
||||
from pyFTS.nonstationary import common,perturbation,util
|
||||
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)
|
||||
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)
|
||||
lmv1 = generate_heteroskedastic_linear(1,0.1,1,0.3)
|
||||
|
||||
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