- Non Stationary Fuzzy Sets

This commit is contained in:
Petrônio Cândido 2017-10-04 23:29:57 -03:00
parent fa231740a5
commit c38a3747f0
4 changed files with 232 additions and 43 deletions

View File

@ -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

View File

@ -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])

View File

@ -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()

View File

@ -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)