- Seasonal partitioner
This commit is contained in:
parent
7a2dd7e54c
commit
1d583e8b0a
@ -11,14 +11,19 @@ class FuzzySet(FuzzySet.FuzzySet):
|
||||
"""
|
||||
Composite Fuzzy Set
|
||||
"""
|
||||
def __init__(self, name):
|
||||
def __init__(self, name, superset=False):
|
||||
"""
|
||||
Create an empty composite fuzzy set
|
||||
:param name: fuzzy set name
|
||||
"""
|
||||
super(FuzzySet, self).__init__(self, name=name, mf=None, parameters=None, centroid=None)
|
||||
self.mf = []
|
||||
self.parameters = []
|
||||
super(FuzzySet, self).__init__(self, name, None, None, None, type='composite')
|
||||
self.superset = superset
|
||||
if self.superset:
|
||||
self.sets = []
|
||||
else:
|
||||
self.mf = []
|
||||
self.parameters = []
|
||||
|
||||
|
||||
def membership(self, x):
|
||||
"""
|
||||
@ -26,7 +31,10 @@ class FuzzySet(FuzzySet.FuzzySet):
|
||||
:param x: input value
|
||||
:return: membership value of x at this fuzzy set
|
||||
"""
|
||||
return min([self.mf[ct](x, self.parameters[ct]) for ct in np.arange(0, len(self.mf))])
|
||||
if self.superset:
|
||||
return max([s.membership(x) for s in self.sets])
|
||||
else:
|
||||
return min([self.mf[ct](x, self.parameters[ct]) for ct in np.arange(0, len(self.mf))])
|
||||
|
||||
def append(self, mf, parameters):
|
||||
"""
|
||||
@ -37,3 +45,12 @@ class FuzzySet(FuzzySet.FuzzySet):
|
||||
"""
|
||||
self.mf.append(mf)
|
||||
self.parameters.append(parameters)
|
||||
|
||||
def append_set(self, set):
|
||||
"""
|
||||
Adds a new function to composition
|
||||
:param mf:
|
||||
:param parameters:
|
||||
:return:
|
||||
"""
|
||||
self.sets.append(set)
|
@ -7,7 +7,7 @@ class FuzzySet(object):
|
||||
"""
|
||||
Fuzzy Set
|
||||
"""
|
||||
def __init__(self, name, mf, parameters, centroid):
|
||||
def __init__(self, name, mf, parameters, centroid, alpha=1.0, type='common'):
|
||||
"""
|
||||
Create a Fuzzy Set
|
||||
:param name: fuzzy set name
|
||||
@ -19,6 +19,8 @@ class FuzzySet(object):
|
||||
self.mf = mf
|
||||
self.parameters = parameters
|
||||
self.centroid = centroid
|
||||
self.alpha = alpha
|
||||
self.type = type
|
||||
":param Z: Partition function in respect to the membership function"
|
||||
self.Z = None
|
||||
if self.mf == Membership.trimf:
|
||||
@ -35,7 +37,7 @@ class FuzzySet(object):
|
||||
:param x: input value
|
||||
:return: membership value of x at this fuzzy set
|
||||
"""
|
||||
return self.mf(x, self.parameters)
|
||||
return self.mf(x, self.parameters) * self.alpha
|
||||
|
||||
def partition_function(self,uod=None, nbins=100):
|
||||
"""
|
||||
|
@ -7,13 +7,25 @@ from pyFTS.partitioners import partitioner, Grid
|
||||
|
||||
class DateTime(Enum):
|
||||
year = 1
|
||||
month = 2
|
||||
day_of_month = 3
|
||||
day_of_year = 4
|
||||
day_of_week = 5
|
||||
month = 12
|
||||
day_of_month = 30
|
||||
day_of_year = 364
|
||||
day_of_week = 7
|
||||
hour = 6
|
||||
minute = 7
|
||||
second = 8
|
||||
hour_of_day = 24
|
||||
hour_of_week = 168
|
||||
hour_of_month = 744
|
||||
hour_of_year = 8736
|
||||
minute_of_hour = 60
|
||||
minute_of_day = 1440
|
||||
minute_of_week = 10080
|
||||
minute_of_month = 44640
|
||||
minute_of_year = 524160
|
||||
second_of_minute = 60.00001
|
||||
second_of_hour = 3600
|
||||
second_of_day = 86400
|
||||
|
||||
|
||||
def strip_datepart(self, date, date_part):
|
||||
@ -27,12 +39,45 @@ def strip_datepart(self, date, date_part):
|
||||
tmp = date.day
|
||||
elif date_part == DateTime.day_of_week:
|
||||
tmp = date.weekday()
|
||||
elif date_part == DateTime.hour:
|
||||
elif date_part == DateTime.hour or date_part == DateTime.hour_of_day:
|
||||
tmp = date.hour
|
||||
elif date_part == DateTime.minute:
|
||||
elif date_part == DateTime.hour_of_week:
|
||||
wk = (date.weekday()-1) * 24
|
||||
tmp = date.hour + wk
|
||||
elif date_part == DateTime.hour_of_month:
|
||||
wk = (date.day-1) * 24
|
||||
tmp = date.hour + wk
|
||||
elif date_part == DateTime.hour_of_year:
|
||||
wk = (date.timetuple().tm_yday-1) * 24
|
||||
tmp = date.hour + wk
|
||||
elif date_part == DateTime.minute or date_part == DateTime.minute_of_hour:
|
||||
tmp = date.minute
|
||||
elif date_part == DateTime.second:
|
||||
elif date_part == DateTime.minute_of_day:
|
||||
wk = date.hour * 60
|
||||
tmp = date.minute + wk
|
||||
elif date_part == DateTime.minute_of_week:
|
||||
wk1 = (date.weekday()-1) * 1440 #24 * 60
|
||||
wk2 = date.hour * 60
|
||||
tmp = date.minute + wk1 + wk2
|
||||
elif date_part == DateTime.minute_of_month:
|
||||
wk1 = (date.day - 1) * 1440 #24 * 60
|
||||
wk2 = date.hour * 60
|
||||
tmp = date.minute + wk1 + wk2
|
||||
elif date_part == DateTime.minute_of_year:
|
||||
wk1 = (date.timetuple().tm_yday - 1) * 1440 #24 * 60
|
||||
wk2 = date.hour * 60
|
||||
tmp = date.minute + wk1 + wk2
|
||||
elif date_part == DateTime.second or date_part == DateTime.second_of_minute:
|
||||
tmp = date.second
|
||||
elif date_part == DateTime.second_of_hour:
|
||||
wk1 = date.minute * 60
|
||||
tmp = date.second + wk1
|
||||
elif date_part == DateTime.second_of_day:
|
||||
wk1 = date.hour * 3600 #60 * 60
|
||||
wk2 = date.minute * 60
|
||||
tmp = date.second + wk1 + wk2
|
||||
else:
|
||||
raise Exception("Unknown DateTime value!")
|
||||
|
||||
return tmp
|
||||
|
||||
@ -42,8 +87,8 @@ class FuzzySet(FuzzySet.FuzzySet):
|
||||
Temporal/Seasonal Fuzzy Set
|
||||
"""
|
||||
|
||||
def __init__(self, datepart, name, mf, parameters, centroid):
|
||||
super(FuzzySet, self).__init__(name, mf, parameters, centroid)
|
||||
def __init__(self, datepart, name, mf, parameters, centroid, alpha=1.0):
|
||||
super(FuzzySet, self).__init__(name, mf, parameters, centroid, alpha)
|
||||
self.datepart = datepart
|
||||
|
||||
def membership(self, x):
|
||||
|
101
pyFTS/models/seasonal/partitioner.py
Normal file
101
pyFTS/models/seasonal/partitioner.py
Normal file
@ -0,0 +1,101 @@
|
||||
from pyFTS.common import Membership
|
||||
from pyFTS.common.Composite import FuzzySet as Composite
|
||||
from pyFTS.partitioners import partitioner, Grid
|
||||
from pyFTS.models.seasonal.common import DateTime, FuzzySet, strip_datepart
|
||||
import numpy as np
|
||||
import matplotlib.pylab as plt
|
||||
|
||||
|
||||
class TimeGridPartitioner(partitioner.Partitioner):
|
||||
"""Even Length DateTime Grid Partitioner"""
|
||||
|
||||
def __init__(self, data, npart, season, func=Membership.trimf, names=None):
|
||||
"""
|
||||
Even Length Grid Partitioner
|
||||
:param data: Training data of which the universe of discourse will be extracted. The universe of discourse is the open interval between the minimum and maximum values of the training data.
|
||||
:param npart: The number of universe of discourse partitions, i.e., the number of fuzzy sets that will be created
|
||||
:param func: Fuzzy membership function (pyFTS.common.Membership)
|
||||
"""
|
||||
super(TimeGridPartitioner, self).__init__("TimeGrid", data, npart, func=func, names=names, transformation=None,
|
||||
indexer=None, preprocess=False)
|
||||
|
||||
self.season = season
|
||||
if self.season == DateTime.year:
|
||||
ndata = [strip_datepart(k, season) for k in data]
|
||||
self.min = min(ndata)
|
||||
self.max = max(ndata)
|
||||
else:
|
||||
tmp = (self.season.value / self.partitions) / 2
|
||||
self.min = tmp
|
||||
self.max = self.season.value + tmp
|
||||
|
||||
self.sets = self.build(None)
|
||||
|
||||
def build(self, data):
|
||||
sets = []
|
||||
|
||||
if self.season == DateTime.year:
|
||||
dlen = (self.max - self.min)
|
||||
partlen = dlen / self.partitions
|
||||
else:
|
||||
partlen = self.season.value / self.partitions
|
||||
pl2 = partlen / 2
|
||||
|
||||
count = 0
|
||||
for c in np.arange(self.min, self.max, partlen):
|
||||
set_name = self.prefix + str(count) if self.setnames is None else self.setnames[count]
|
||||
if self.membership_function == Membership.trimf:
|
||||
if c == self.min:
|
||||
tmp = Composite(set_name, superset=True)
|
||||
tmp.append_set(FuzzySet(self.season, set_name, Membership.trimf,
|
||||
[self.season.value - pl2, self.season.value,
|
||||
self.season.value + 0.0000001], self.season.value, alpha=.5))
|
||||
tmp.append_set(FuzzySet(self.season, set_name, Membership.trimf,
|
||||
[c - partlen, c, c + partlen], c))
|
||||
tmp.centroid = c
|
||||
sets.append(tmp)
|
||||
else:
|
||||
sets.append(FuzzySet(self.season, set_name, Membership.trimf,
|
||||
[c - partlen, c, c + partlen], c))
|
||||
elif self.membership_function == Membership.gaussmf:
|
||||
sets.append(FuzzySet(self.season, set_name, Membership.gaussmf, [c, partlen / 3], c))
|
||||
elif self.membership_function == Membership.trapmf:
|
||||
q = partlen / 4
|
||||
if c == self.min:
|
||||
tmp = Composite(set_name, superset=True)
|
||||
tmp.append_set(FuzzySet(self.season, set_name, Membership.trimf,
|
||||
[self.season.value - pl2, self.season.value,
|
||||
self.season.value + 0.0000001], 0))
|
||||
tmp.append_set(FuzzySet(self.season, set_name, Membership.trapmf,
|
||||
[c - partlen, c - q, c + q, c + partlen], c))
|
||||
tmp.centroid = c
|
||||
sets.append(tmp)
|
||||
else:
|
||||
sets.append(FuzzySet(self.season, set_name, Membership.trapmf,
|
||||
[c - partlen, c - q, c + q, c + partlen], c))
|
||||
count += 1
|
||||
|
||||
self.min = 0
|
||||
|
||||
return sets
|
||||
|
||||
def plot(self, ax):
|
||||
"""
|
||||
Plot the
|
||||
:param ax:
|
||||
:return:
|
||||
"""
|
||||
ax.set_title(self.name)
|
||||
ax.set_ylim([0, 1])
|
||||
ax.set_xlim([0, self.season.value])
|
||||
ticks = []
|
||||
x = []
|
||||
for s in self.sets:
|
||||
if s.type == 'common':
|
||||
self.plot_set(ax, s)
|
||||
elif s.type == 'composite':
|
||||
for ss in s.sets:
|
||||
self.plot_set(ax, ss)
|
||||
# ticks.append(str(round(s.centroid, 0)) + '\n' + s.name)
|
||||
# x.append(s.centroid)
|
||||
# plt.xticks(x, ticks)
|
@ -8,7 +8,8 @@ class Partitioner(object):
|
||||
Universe of Discourse partitioner. Split data on several fuzzy sets
|
||||
"""
|
||||
|
||||
def __init__(self, name, data, npart, func=Membership.trimf, names=None, prefix="A", transformation=None, indexer=None):
|
||||
def __init__(self, name, data, npart, func=Membership.trimf, names=None, prefix="A",
|
||||
transformation=None, indexer=None, preprocess=True):
|
||||
"""
|
||||
Universe of Discourse partitioner scheme. Split data on several fuzzy sets
|
||||
:param name: partitioner name
|
||||
@ -28,31 +29,33 @@ class Partitioner(object):
|
||||
self.transformation = transformation
|
||||
self.indexer = indexer
|
||||
|
||||
if self.indexer is not None:
|
||||
ndata = self.indexer.get_data(data)
|
||||
else:
|
||||
ndata = data
|
||||
if preprocess:
|
||||
|
||||
if transformation is not None:
|
||||
ndata = transformation.apply(ndata)
|
||||
else:
|
||||
ndata = data
|
||||
if self.indexer is not None:
|
||||
ndata = self.indexer.get_data(data)
|
||||
else:
|
||||
ndata = data
|
||||
|
||||
_min = min(ndata)
|
||||
if _min < 0:
|
||||
self.min = _min * 1.1
|
||||
else:
|
||||
self.min = _min * 0.9
|
||||
if transformation is not None:
|
||||
ndata = transformation.apply(ndata)
|
||||
else:
|
||||
ndata = data
|
||||
|
||||
_max = max(ndata)
|
||||
if _max > 0:
|
||||
self.max = _max * 1.1
|
||||
else:
|
||||
self.max = _max * 0.9
|
||||
_min = min(ndata)
|
||||
if _min < 0:
|
||||
self.min = _min * 1.1
|
||||
else:
|
||||
self.min = _min * 0.9
|
||||
|
||||
self.sets = self.build(ndata)
|
||||
_max = max(ndata)
|
||||
if _max > 0:
|
||||
self.max = _max * 1.1
|
||||
else:
|
||||
self.max = _max * 0.9
|
||||
|
||||
del(ndata)
|
||||
self.sets = self.build(ndata)
|
||||
|
||||
del(ndata)
|
||||
|
||||
def build(self, data):
|
||||
"""
|
||||
@ -74,16 +77,25 @@ class Partitioner(object):
|
||||
ticks = []
|
||||
x = []
|
||||
for s in self.sets:
|
||||
if s.mf == Membership.trimf:
|
||||
ax.plot([s.parameters[0], s.parameters[1], s.parameters[2]], [0, 1, 0])
|
||||
elif s.mf == Membership.gaussmf:
|
||||
tmpx = [kk for kk in np.arange(s.lower, s.upper)]
|
||||
tmpy = [s.membership(kk) for kk in np.arange(s.lower, s.upper)]
|
||||
ax.plot(tmpx, tmpy)
|
||||
if s.type == 'common':
|
||||
self.plot_set(ax, s)
|
||||
elif s.type == 'composite':
|
||||
for ss in s.sets:
|
||||
self.plot_set(ax, ss)
|
||||
ticks.append(str(round(s.centroid,0))+'\n'+s.name)
|
||||
x.append(s.centroid)
|
||||
plt.xticks(x,ticks)
|
||||
|
||||
def plot_set(self, ax, s):
|
||||
if s.mf == Membership.trimf:
|
||||
ax.plot([s.parameters[0], s.parameters[1], s.parameters[2]], [0, s.alpha, 0])
|
||||
elif s.mf == Membership.gaussmf:
|
||||
tmpx = [kk for kk in np.arange(s.lower, s.upper)]
|
||||
tmpy = [s.membership(kk) for kk in np.arange(s.lower, s.upper)]
|
||||
ax.plot(tmpx, tmpy)
|
||||
elif s.mf == Membership.trapmf:
|
||||
ax.plot(s.parameters, [0, s.alpha, s.alpha, 0])
|
||||
|
||||
|
||||
def __str__(self):
|
||||
tmp = self.name + ":\n"
|
||||
|
19
pyFTS/tests/seasonal.py
Normal file
19
pyFTS/tests/seasonal.py
Normal file
@ -0,0 +1,19 @@
|
||||
import matplotlib.pylab as plt
|
||||
from pyFTS.models.seasonal import partitioner, common
|
||||
from pyFTS.partitioners import Util
|
||||
from pyFTS.common import Membership
|
||||
|
||||
|
||||
#fs = partitioner.TimeGridPartitioner(None, 12, common.DateTime.day_of_year, func=Membership.trapmf,
|
||||
# names=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])
|
||||
|
||||
|
||||
#fs = partitioner.TimeGridPartitioner(None, 24, common.DateTime.minute_of_day, func=Membership.trapmf)
|
||||
|
||||
fs = partitioner.TimeGridPartitioner(None, 7, common.DateTime.hour_of_week, func=Membership.trapmf)
|
||||
|
||||
|
||||
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[6, 8])
|
||||
|
||||
fs.plot(ax)
|
||||
plt.show()
|
Loading…
Reference in New Issue
Block a user