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

View File

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

View File

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

View File

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