From 84e6e1abbf650986122e4a91a3550bc975f3c92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=C3=B4nio=20C=C3=A2ndido=20de=20Lima=20e=20Silva?= Date: Fri, 24 Feb 2017 13:29:55 -0300 Subject: [PATCH] - Sliding Window benchmark - Refactoring of partitioners for OO design --- benchmarks/benchmarks.py | 156 +++++++++++++++++++++++++++++------- benchmarks/naive.py | 2 +- chen.py | 5 +- common/Util.py | 7 ++ fts.py | 10 ++- hofts.py | 6 +- ismailefendi.py | 7 +- partitioners/CMeans.py | 36 +++++---- partitioners/Entropy.py | 35 ++++---- partitioners/FCM.py | 44 +++++----- partitioners/Grid.py | 66 +++++++-------- partitioners/Huarng.py | 54 +++++++------ partitioners/partitioner.py | 38 +++++++++ pwfts.py | 4 +- sadaei.py | 5 +- sfts.py | 3 + tests/general.py | 31 +++++++ tests/sfts.py | 2 +- yu.py | 2 +- 19 files changed, 362 insertions(+), 151 deletions(-) create mode 100644 partitioners/partitioner.py create mode 100644 tests/general.py diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py index f499273..1224328 100644 --- a/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -23,13 +23,106 @@ styles = ['-','--','-.',':','.'] nsty = len(styles) +def get_point_methods(): + return [naive.Naive, chen.ConventionalFTS, yu.WeightedFTS, ismailefendi.ImprovedWeightedFTS, + sadaei.ExponentialyWeightedFTS, hofts.HighOrderFTS, pwfts.ProbabilisticWeightedFTS] + + +def sliding_window(data, windowsize, train=0.8,models=None,partitioners=[Grid.GridPartitioner], + partitions=[10], max_order=3,transformation=None,indexer=None): + if models is None: + models = get_point_methods() + + objs = {} + lcolors = {} + rmse = {} + smape = {} + u = {} + + for train,test in Util.sliding_window(data, windowsize, train): + for partition in partitions: + for partitioner in partitioners: + pttr = str(partitioner.__module__).split('.')[-1] + if transformation is not None: + data_train_fs = partitioner(transformation.apply(train), partition) + else: + data_train_fs = partitioner(train, partition) + + for count, model in enumerate(models, start=0): + + mfts = model("") + _key = mfts.shortname + " " + pttr+ " q = " +str(partition) + + mfts.partitioner = data_train_fs + if not mfts.isHighOrder: + + if _key not in objs: + objs[_key] = mfts + lcolors[_key] = colors[count % ncol] + rmse[_key] = [] + smape[_key] = [] + u[_key] = [] + + if transformation is not None: + mfts.appendTransformation(transformation) + + mfts.train(train, data_train_fs.sets) + + _rmse, _smape, _u = get_point_statistics(test, mfts, indexer) + rmse[_key].append(_rmse) + smape[_key].append(_smape) + u[_key].append(_u) + + else: + for order in np.arange(1, max_order + 1): + if order >= mfts.minOrder: + mfts = model("") + _key = mfts.shortname + " n = " + str(order) + " " + pttr + " q = " + str(partition) + mfts.partitioner = data_train_fs + + if _key not in objs: + objs[_key] = mfts + lcolors[_key] = colors[count % ncol] + rmse[_key] = [] + smape[_key] = [] + u[_key] = [] + + if transformation is not None: + mfts.appendTransformation(transformation) + + mfts.train(train, data_train_fs.sets, order=order) + + _rmse, _smape, _u = get_point_statistics(test, mfts, indexer) + rmse[_key].append(_rmse) + smape[_key].append(_smape) + u[_key].append(_u) + + ret = "Model\t&Order\t&Scheme\t&Partitions\t&RMSE AVG\t&RMSE STD\t& SMAPE AVG\t& SMAPE STD\t& U AVG\t& U STD \\\\ \n" + for k in sorted(objs.keys()): + mfts = objs[k] + ret += mfts.shortname + "\t &" + ret += str( mfts.order ) + "\t &" + ret += mfts.partitioner.name + "\t &" + ret += str(mfts.partitioner.partitions) + "\t &" + ret += str(round(np.mean(rmse[k]),2)) + "\t &" + ret += str(round(np.std(rmse[k]), 2)) + "\t &" + ret += str(round(np.mean(smape[k]), 2)) + "\t &" + ret += str(round(np.std(smape[k]), 2)) + "\t &" + ret += str(round(np.mean(u[k]), 2)) + "\t &" + ret += str(round(np.std(u[k]), 2)) + "\t &" + ret += str(len(mfts)) + "\\\\ \n" + + print(ret) + + + + def allPointForecasters(data_train, data_test, partitions, max_order=3, statistics=True, residuals=True, series=True, save=False, file=None, tam=[20, 5], models=None, transformation=None, distributions=False): if models is None: - models = [naive.Naive, chen.ConventionalFTS, yu.WeightedFTS, ismailefendi.ImprovedWeightedFTS, - sadaei.ExponentialyWeightedFTS, hofts.HighOrderFTS, pwfts.ProbabilisticWeightedFTS] + models = get_point_methods() objs = [] @@ -62,7 +155,7 @@ def allPointForecasters(data_train, data_test, partitions, max_order=3, statisti lcolors.append(colors[(count + order) % ncol]) if statistics: - print(getPointStatistics(data_test, objs)) + print(print_point_statistics(data_test, objs)) if residuals: print(ResidualAnalysis.compareResiduals(data_test, objs)) @@ -87,29 +180,38 @@ def allPointForecasters(data_train, data_test, partitions, max_order=3, statisti plotProbabilityDistributions(pmfs, lcolors,tam=tam) +def get_point_statistics(data, model, indexer=None): + if indexer is not None: + ndata = np.array(indexer.get_data(data[model.order:])) + else: + ndata = np.array(data[model.order:]) -def getPointStatistics(data, models, externalmodels = None, externalforecasts = None, indexers=None): + if model.isMultivariate or indexer is None: + forecasts = model.forecast(data) + elif not model.isMultivariate and indexer is not None: + forecasts = model.forecast(indexer.get_data(data)) + + if model.hasSeasonality: + nforecasts = np.array(forecasts) + else: + nforecasts = np.array(forecasts[:-1]) + ret = list() + ret.append(np.round(Measures.rmse(ndata, nforecasts), 2)) + ret.append(np.round(Measures.smape(ndata, nforecasts), 2)) + ret.append(np.round(Measures.UStatistic(ndata, nforecasts), 2)) + + return ret + + +def print_point_statistics(data, models, externalmodels = None, externalforecasts = None, indexers=None): ret = "Model & Order & RMSE & SMAPE & Theil's U \\\\ \n" for count,model in enumerate(models,start=0): - if indexers is not None and indexers[count] is not None: - ndata = np.array(indexers[count].get_data(data[model.order:])) - else: - ndata = np.array(data[model.order:]) - - if model.isMultivariate or indexers is None: - forecasts = model.forecast(data) - elif not model.isMultivariate and indexers is not None: - forecasts = model.forecast( indexers[count].get_data(data) ) - - if model.hasSeasonality: - nforecasts = np.array(forecasts) - else: - nforecasts = np.array(forecasts[:-1]) + _rmse, _smape, _u = get_point_statistics(data, model, indexers[count]) ret += model.shortname + " & " ret += str(model.order) + " & " - ret += str(round(Measures.rmse(ndata, nforecasts), 2)) + " & " - ret += str(round(Measures.smape(ndata, nforecasts), 2))+ " & " - ret += str(round(Measures.UStatistic(ndata, nforecasts), 2)) + ret += str(_rmse) + " & " + ret += str(_smape)+ " & " + ret += str(_u) #ret += str(round(Measures.TheilsInequality(np.array(data[fts.order:]), np.array(forecasts[:-1])), 4)) ret += " \\\\ \n" if externalmodels is not None: @@ -194,7 +296,7 @@ def plotDistribution(dist): def plotComparedSeries(original, models, colors, typeonlegend=False, save=False, file=None, tam=[20, 5], - intervals=True): + points=True, intervals=True, linewidth=1.5): fig = plt.figure(figsize=tam) ax = fig.add_subplot(111) @@ -203,10 +305,10 @@ def plotComparedSeries(original, models, colors, typeonlegend=False, save=False, legends = [] - ax.plot(original, color='black', label="Original", linewidth=1.5) + ax.plot(original, color='black', label="Original", linewidth=linewidth*1.5) for count, fts in enumerate(models, start=0): - if fts.hasPointForecasting and not intervals: + if fts.hasPointForecasting and points: forecasted = fts.forecast(original) mi.append(min(forecasted) * 0.95) ma.append(max(forecasted) * 1.05) @@ -214,7 +316,7 @@ def plotComparedSeries(original, models, colors, typeonlegend=False, save=False, forecasted.insert(0, None) lbl = fts.shortname if typeonlegend: lbl += " (Point)" - ax.plot(forecasted, color=colors[count], label=lbl, ls="-") + ax.plot(forecasted, color=colors[count], label=lbl, ls="-",linewidth=linewidth) if fts.hasIntervalForecasting and intervals: forecasted = fts.forecastInterval(original) @@ -227,8 +329,8 @@ def plotComparedSeries(original, models, colors, typeonlegend=False, save=False, upper.insert(0, None) lbl = fts.shortname if typeonlegend: lbl += " (Interval)" - ax.plot(lower, color=colors[count], label=lbl, ls="-") - ax.plot(upper, color=colors[count], ls="-") + ax.plot(lower, color=colors[count], label=lbl, ls="--",linewidth=linewidth) + ax.plot(upper, color=colors[count], ls="--",linewidth=linewidth) handles0, labels0 = ax.get_legend_handles_labels() lgd = ax.legend(handles0, labels0, loc=2, bbox_to_anchor=(1, 1)) diff --git a/benchmarks/naive.py b/benchmarks/naive.py index 7b6da95..7e6674e 100644 --- a/benchmarks/naive.py +++ b/benchmarks/naive.py @@ -6,7 +6,7 @@ from pyFTS import fts class Naive(fts.FTS): def __init__(self, name): - super(Naive, self).__init__(1, "Naïve" + name) + super(Naive, self).__init__(1, "Naïve " + name) self.name = "Naïve Model" self.detail = "Naïve Model" diff --git a/chen.py b/chen.py index 529f2d3..eb1ab49 100644 --- a/chen.py +++ b/chen.py @@ -20,10 +20,13 @@ class ConventionalFLRG(object): tmp2 = tmp2 + c.name return tmp + tmp2 + def __len__(self): + return len(self.RHS) + class ConventionalFTS(fts.FTS): def __init__(self, name): - super(ConventionalFTS, self).__init__(1, "CFTS") + super(ConventionalFTS, self).__init__(1, "CFTS " + name) self.name = "Conventional FTS" self.detail = "Chen" self.flrgs = {} diff --git a/common/Util.py b/common/Util.py index 62ac6bc..0b27ba4 100644 --- a/common/Util.py +++ b/common/Util.py @@ -1,6 +1,7 @@ import time import matplotlib.pyplot as plt import dill +import numpy as np current_milli_time = lambda: int(round(time.time() * 1000)) @@ -29,6 +30,12 @@ def enumerate2(xs, start=0, step=1): yield (start, x) start += step +def sliding_window(data, windowsize, train=0.8): + l = len(data) + ttrain = int(round(windowsize * train, 0)) + for count in np.arange(0,l,windowsize): + yield ( data[count : count + ttrain], data[count + ttrain : count + windowsize] ) + def persist_obj(obj, file): with open(file, 'wb') as _file: diff --git a/fts.py b/fts.py index d315d9f..a48fb04 100644 --- a/fts.py +++ b/fts.py @@ -25,6 +25,7 @@ class FTS(object): self.transformations_param = [] self.original_max = 0 self.original_min = 0 + self.partitioner = None def fuzzy(self, data): best = {"fuzzyset": "", "membership": 0.0} @@ -55,7 +56,7 @@ class FTS(object): def forecastAheadDistribution(self, data, steps): pass - def train(self, data, sets,order=1, parameters=None): + def train(self, data, sets, order=1, parameters=None): pass def getMidpoints(self, flrg): @@ -104,6 +105,12 @@ class FTS(object): tmp = tmp + str(self.flrgs[r]) + "\n" return tmp + def __len__(self): + return len(self.flrgs) + + def len_total(self): + return sum([len(k) for k in self.flrgs]) + def buildTreeWithoutOrder(self, node, lags, level): if level not in lags: @@ -168,3 +175,4 @@ class FTS(object): + diff --git a/hofts.py b/hofts.py index 30064e3..43a7af8 100644 --- a/hofts.py +++ b/hofts.py @@ -3,7 +3,7 @@ from pyFTS.common import FuzzySet,FLR from pyFTS import fts -class HighOrderFLRG: +class HighOrderFLRG(object): def __init__(self, order): self.LHS = [] self.RHS = {} @@ -34,6 +34,10 @@ class HighOrderFLRG: return self.strLHS() + " -> " + tmp + def __len__(self): + return len(self.RHS) + + class HighOrderFTS(fts.FTS): def __init__(self, name): super(HighOrderFTS, self).__init__(1, "HOFTS" + name) diff --git a/ismailefendi.py b/ismailefendi.py index 7afc5ad..60d1e44 100644 --- a/ismailefendi.py +++ b/ismailefendi.py @@ -3,7 +3,7 @@ from pyFTS.common import FuzzySet,FLR from pyFTS import fts -class ImprovedWeightedFLRG: +class ImprovedWeightedFLRG(object): def __init__(self, LHS): self.LHS = LHS self.RHS = {} @@ -28,10 +28,13 @@ class ImprovedWeightedFLRG: tmp2 = tmp2 + c + "(" + str(round(self.RHS[c] / self.count, 3)) + ")" return tmp + tmp2 + def __len__(self): + return len(self.RHS) + class ImprovedWeightedFTS(fts.FTS): def __init__(self, name): - super(ImprovedWeightedFTS, self).__init__(1, "IWFTS") + super(ImprovedWeightedFTS, self).__init__(1, "IWFTS " + name) self.name = "Improved Weighted FTS" self.detail = "Ismail & Efendi" self.setsDict = {} diff --git a/partitioners/CMeans.py b/partitioners/CMeans.py index baf15fa..b9eb31b 100644 --- a/partitioners/CMeans.py +++ b/partitioners/CMeans.py @@ -3,6 +3,7 @@ import math import random as rnd import functools, operator from pyFTS.common import FuzzySet, Membership +from pyFTS.partitioners import partitioner def distancia(x, y): @@ -75,21 +76,24 @@ def c_means(k, dados, tam): return centroides +class CMeansPartitioner(partitioner.Partitioner): + def __init__(self, npart,data,func = Membership.trimf): + super(CMeansPartitioner, self).__init__("CMeans ",data,npart,func) -def CMeansPartitionerTrimf(data, npart, names=None, prefix="A"): - sets = [] - dmax = max(data) - dmax += dmax * 0.10 - dmin = min(data) - dmin -= dmin * 0.10 - centroides = c_means(npart, data, 1) - centroides.append(dmax) - centroides.append(dmin) - centroides = list(set(centroides)) - centroides.sort() - for c in np.arange(1, len(centroides) - 1): - sets.append(FuzzySet.FuzzySet(prefix + str(c), Membership.trimf, - [round(centroides[c - 1], 3), round(centroides[c], 3), round(centroides[c + 1], 3)], - round(centroides[c], 3))) + def build(self, data): + sets = [] + dmax = max(data) + dmax += dmax * 0.10 + dmin = min(data) + dmin -= dmin * 0.10 + centroides = c_means(self.partitions, data, 1) + centroides.append(dmax) + centroides.append(dmin) + centroides = list(set(centroides)) + centroides.sort() + for c in np.arange(1, len(centroides) - 1): + sets.append(FuzzySet.FuzzySet(self.prefix + str(c), Membership.trimf, + [round(centroides[c - 1], 3), round(centroides[c], 3), round(centroides[c + 1], 3)], + round(centroides[c], 3))) - return sets + return sets diff --git a/partitioners/Entropy.py b/partitioners/Entropy.py index cbf6dc4..54af91e 100644 --- a/partitioners/Entropy.py +++ b/partitioners/Entropy.py @@ -3,7 +3,7 @@ import math import random as rnd import functools, operator from pyFTS.common import FuzzySet, Membership - +from pyFTS.partitioners import partitioner # C. H. Cheng, R. J. Chang, and C. A. Yeh, “Entropy-based and trapezoidal fuzzification-based fuzzy time series approach for forecasting IT project cost,” # Technol. Forecast. Social Change, vol. 73, no. 5, pp. 524–542, Jun. 2006. @@ -76,21 +76,24 @@ def bestSplit(data, npart): else: return [threshold] +class EntropyPartitioner(partitioner.Partitioner): + def __init__(self, data,npart,func = Membership.trimf): + super(EntropyPartitioner, self).__init__("Entropy" ,data,npart,func) -def EntropyPartitionerTrimf(data, npart, prefix="A"): - sets = [] - dmax = max(data) - dmax += dmax * 0.10 - dmin = min(data) - dmin -= dmin * 0.10 + def build(self, data): + sets = [] + dmax = max(data) + dmax += dmax * 0.10 + dmin = min(data) + dmin -= dmin * 0.10 - partitions = bestSplit(data, npart) - partitions.append(dmin) - partitions.append(dmax) - partitions = list(set(partitions)) - partitions.sort() - for c in np.arange(1, len(partitions) - 1): - sets.append(FuzzySet.FuzzySet(prefix + str(c), Membership.trimf, - [partitions[c - 1], partitions[c], partitions[c + 1]],partitions[c])) + partitions = bestSplit(data, self.partitions) + partitions.append(dmin) + partitions.append(dmax) + partitions = list(set(partitions)) + partitions.sort() + for c in np.arange(1, len(partitions) - 1): + sets.append(FuzzySet.FuzzySet(self.prefix + str(c), Membership.trimf, + [partitions[c - 1], partitions[c], partitions[c + 1]],partitions[c])) - return sets + return sets diff --git a/partitioners/FCM.py b/partitioners/FCM.py index 153150d..e940da5 100644 --- a/partitioners/FCM.py +++ b/partitioners/FCM.py @@ -3,19 +3,20 @@ import math import random as rnd import functools,operator from pyFTS.common import FuzzySet,Membership +from pyFTS.partitioners import partitioner #import CMeans # S. T. Li, Y. C. Cheng, and S. Y. Lin, “A FCM-based deterministic forecasting model for fuzzy time series,” # Comput. Math. Appl., vol. 56, no. 12, pp. 3052–3063, Dec. 2008. DOI: 10.1016/j.camwa.2008.07.033. -def distancia(x,y): +def fuzzy_distance(x, y): if isinstance(x, list): tmp = functools.reduce(operator.add, [(x[k] - y[k])**2 for k in range(0,len(x))]) else: tmp = (x - y) ** 2 return math.sqrt(tmp) -def pert(val, vals): +def membership(val, vals): soma = 0 for k in vals: if k == 0: @@ -55,7 +56,7 @@ def fuzzy_cmeans(k, dados, tam, m, deltadist=0.001): grupo_count = 0 for grupo in centroides: - dist_grupos[grupo_count] = distancia(grupo, instancia) + dist_grupos[grupo_count] = fuzzy_distance(grupo, instancia) grupo_count = grupo_count + 1 dist_grupos_total = functools.reduce(operator.add, [xk for xk in dist_grupos]) @@ -64,7 +65,7 @@ def fuzzy_cmeans(k, dados, tam, m, deltadist=0.001): if dist_grupos[grp] == 0: grupos[inst_count][grp] = 1 else: - grupos[inst_count][grp] = 1 / pert(dist_grupos[grp], dist_grupos) + grupos[inst_count][grp] = 1 / membership(dist_grupos[grp], dist_grupos) # grupos[inst_count][grp] = 1/(dist_grupos[grp] / dist_grupos_total) # grupos[inst_count][grp] = (1/(dist_grupos[grp]**2))**m_exp / (1/(dist_grupos_total**2))**m_exp @@ -90,7 +91,7 @@ def fuzzy_cmeans(k, dados, tam, m, deltadist=0.001): norm = functools.reduce(operator.add, [grupos[xk][grupo_count] for xk in range(0, tam_dados)]) centroides[grupo_count] = soma / norm - alteracaomedia = alteracaomedia + distancia(oldgrp, grupo) + alteracaomedia = alteracaomedia + fuzzy_distance(oldgrp, grupo) grupo_count = grupo_count + 1 alteracaomedia = alteracaomedia / k @@ -98,18 +99,23 @@ def fuzzy_cmeans(k, dados, tam, m, deltadist=0.001): return centroides -def FCMPartitionerTrimf(data,npart,names = None,prefix = "A"): - sets = [] - dmax = max(data) - dmax = dmax + dmax*0.10 - dmin = min(data) - dmin = dmin - dmin*0.10 - centroides = fuzzy_cmeans(npart, data, 1, 2) - centroides.append(dmax) - centroides.append(dmin) - centroides = list(set(centroides)) - centroides.sort() - for c in np.arange(1,len(centroides)-1): - sets.append(FuzzySet.FuzzySet(prefix+str(c),Membership.trimf,[round(centroides[c-1],3), round(centroides[c],3), round(centroides[c+1],3)], round(centroides[c],3) ) ) - return sets \ No newline at end of file +class FCMPartitioner(partitioner.Partitioner): + def __init__(self, data,npart,func = Membership.trimf): + super(FCMPartitioner, self).__init__("FCM ",data,npart,func) + + def build(self,data): + sets = [] + dmax = max(data) + dmax = dmax + dmax*0.10 + dmin = min(data) + dmin = dmin - dmin*0.10 + centroides = fuzzy_cmeans(self.partitions, data, 1, 2) + centroides.append(dmax) + centroides.append(dmin) + centroides = list(set(centroides)) + centroides.sort() + for c in np.arange(1,len(centroides)-1): + sets.append(FuzzySet.FuzzySet(self.prefix+str(c),Membership.trimf,[round(centroides[c-1],3), round(centroides[c],3), round(centroides[c+1],3)], round(centroides[c],3) ) ) + + return sets \ No newline at end of file diff --git a/partitioners/Grid.py b/partitioners/Grid.py index 2b8ceb8..2b64720 100644 --- a/partitioners/Grid.py +++ b/partitioners/Grid.py @@ -3,49 +3,39 @@ import math import random as rnd import functools, operator from pyFTS.common import FuzzySet, Membership +from pyFTS.partitioners import partitioner -# print(common.__dict__) +class GridPartitioner(partitioner.Partitioner): + def __init__(self, data,npart,func = Membership.trimf): + super(GridPartitioner, self).__init__("Grid",data,npart,func) -def GridPartitionerTrimf(data, npart, names=None, prefix="A"): - sets = [] - _min = min(data) - if _min < 0: - dmin = _min * 1.1 - else: - dmin = _min * 0.9 + def build(self, data): + sets = [] + _min = min(data) + if _min < 0: + dmin = _min * 1.1 + else: + dmin = _min * 0.9 - _max = max(data) - if _max > 0: - dmax = _max * 1.1 - else: - dmax = _max * 0.9 + _max = max(data) + if _max > 0: + dmax = _max * 1.1 + else: + dmax = _max * 0.9 - dlen = dmax - dmin - partlen = dlen / npart + dlen = dmax - dmin + partlen = dlen / self.partitions - count = 0 - for c in np.arange(dmin, dmax, partlen): - sets.append( - FuzzySet.FuzzySet(prefix + str(count), Membership.trimf, [c - partlen, c, c + partlen],c)) - count += 1 - - return sets + count = 0 + for c in np.arange(dmin, dmax, partlen): + if self.membership_function == Membership.trimf: + sets.append( + FuzzySet.FuzzySet(self.prefix + str(count), Membership.trimf, [c - partlen, c, c + partlen],c)) + elif self.membership_function == Membership.gaussmf: + sets.append( + FuzzySet.FuzzySet(self.prefix + str(count), Membership.gaussmf, [c, partlen / 3], c)) + count += 1 -def GridPartitionerGaussmf(data, npart, names=None, prefix="A"): - sets = [] - dmax = max(data) - dmax += dmax * 0.10 - dmin = min(data) - dmin -= dmin * 0.10 - dlen = dmax - dmin - partlen = math.ceil(dlen / npart) - partition = math.ceil(dmin) - for c in range(npart): - sets.append( - FuzzySet.FuzzySet(prefix + str(c), Membership.gaussmf, [partition, partlen/3], - partition)) - partition += partlen - - return sets + return sets diff --git a/partitioners/Huarng.py b/partitioners/Huarng.py index 491e752..bd2a2ac 100644 --- a/partitioners/Huarng.py +++ b/partitioners/Huarng.py @@ -7,31 +7,37 @@ from pyFTS.common import FuzzySet, Membership, Transformations # K. H. Huarng, “Effective lengths of intervals to improve forecasting in fuzzy time series,” # Fuzzy Sets Syst., vol. 123, no. 3, pp. 387–394, Nov. 2001. +from pyFTS.partitioners import partitioner -def GridPartitionerTrimf(data, prefix="A"): - data2 = Transformations.differential(data) - davg = np.abs( np.mean(data2) / 2 ) - if davg <= 1.0: - base = 0.1 - elif 1 < davg <= 10: - base = 1.0 - elif 10 < davg <= 100: - base = 10 - else: - base = 100 +class HuarngPartitioner(partitioner.Partitioner): + def __init__(self, npart,data,func = Membership.trimf): + super(HuarngPartitioner, self).__init__("Huarng",data,npart,func) - sets = [] - dmax = max(data) - dmax += dmax * 0.10 - dmin = min(data) - dmin -= dmin * 0.10 - dlen = dmax - dmin - npart = math.ceil(dlen / base) - partition = math.ceil(dmin) - for c in range(npart): - sets.append( - FuzzySet.FuzzySet(prefix + str(c), Membership.trimf, [partition - base, partition, partition + base], partition)) - partition += base + def build(self, data): + data2 = Transformations.differential(data) + davg = np.abs( np.mean(data2) / 2 ) - return sets + if davg <= 1.0: + base = 0.1 + elif 1 < davg <= 10: + base = 1.0 + elif 10 < davg <= 100: + base = 10 + else: + base = 100 + + sets = [] + dmax = max(data) + dmax += dmax * 0.10 + dmin = min(data) + dmin -= dmin * 0.10 + dlen = dmax - dmin + npart = math.ceil(dlen / base) + partition = math.ceil(dmin) + for c in range(npart): + sets.append( + FuzzySet.FuzzySet(self.prefix + str(c), Membership.trimf, [partition - base, partition, partition + base], partition)) + partition += base + + return sets diff --git a/partitioners/partitioner.py b/partitioners/partitioner.py new file mode 100644 index 0000000..e9b45d2 --- /dev/null +++ b/partitioners/partitioner.py @@ -0,0 +1,38 @@ +from pyFTS.common import FuzzySet, Membership +import numpy as np + +class Partitioner(object): + def __init__(self,name,data,npart,func = Membership.trimf, names=None, prefix="A"): + self.name = name + self.partitions = npart + self.sets = [] + self.membership_function = func + self.setnames = names + self.prefix = prefix + _min = min(data) + if _min < 0: + self.min = _min * 1.1 + else: + self.min = _min * 0.9 + + _max = max(data) + if _max > 0: + self.max = _max * 1.1 + else: + self.max = _max * 0.9 + self.sets = self.build(data) + + def build(self,data): + pass + + def plot(self,ax): + ax.set_title(self.name) + ax.set_ylim([0, 1]) + ax.set_xlim([self.min, self.max]) + 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) \ No newline at end of file diff --git a/pwfts.py b/pwfts.py index 2c4db5e..805bb30 100644 --- a/pwfts.py +++ b/pwfts.py @@ -43,8 +43,8 @@ class ProbabilisticWeightedFLRG(hofts.HighOrderFLRG): class ProbabilisticWeightedFTS(ifts.IntervalFTS): def __init__(self, name): - super(ProbabilisticWeightedFTS, self).__init__("PFTS") - self.shortname = "PFTS " + name + super(ProbabilisticWeightedFTS, self).__init__("PWFTS") + self.shortname = "PWFTS " + name self.name = "Probabilistic FTS" self.detail = "Silva, P.; Guimarães, F.; Sadaei, H." self.flrgs = {} diff --git a/sadaei.py b/sadaei.py index 4be9efd..1258f4e 100644 --- a/sadaei.py +++ b/sadaei.py @@ -2,7 +2,7 @@ import numpy as np from pyFTS.common import FuzzySet,FLR from pyFTS import fts -class ExponentialyWeightedFLRG: +class ExponentialyWeightedFLRG(object): def __init__(self, LHS, c): self.LHS = LHS self.RHS = [] @@ -31,6 +31,9 @@ class ExponentialyWeightedFLRG: cc = cc + 1 return tmp + tmp2 + def __len__(self): + return len(self.RHS) + class ExponentialyWeightedFTS(fts.FTS): def __init__(self, name): diff --git a/sfts.py b/sfts.py index c49cf30..1688930 100644 --- a/sfts.py +++ b/sfts.py @@ -21,6 +21,9 @@ class SeasonalFLRG(FLR.FLR): tmp2 = tmp2 + c.name return tmp + tmp2 + def __len__(self): + return len(self.RHS) + class SeasonalFTS(fts.FTS): def __init__(self, name): diff --git a/tests/general.py b/tests/general.py new file mode 100644 index 0000000..81b10f2 --- /dev/null +++ b/tests/general.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +import os +import numpy as np +import pandas as pd +import matplotlib as plt +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D + +import pandas as pd +from pyFTS.partitioners import Grid, Entropy, FCM +from pyFTS.common import FLR,FuzzySet,Membership,Transformations +from pyFTS import fts,hofts,ifts,pwfts,tree, chen +from pyFTS.benchmarks import benchmarks as bchmk +from pyFTS.benchmarks import Measures +from numpy import random + +#print(FCM.FCMPartitionerTrimf.__module__) + +gauss = random.normal(0,1.0,2000) +#gauss_teste = random.normal(0,1.0,400) + + +os.chdir("/home/petronio/dados/Dropbox/Doutorado/Disciplinas/AdvancedFuzzyTimeSeriesModels/") + +#from pyFTS.common import Util + + +bchmk.sliding_window(gauss,500,train=0.7,partitioners=[Grid.GridPartitioner, FCM.FCMPartitioner, Entropy.EntropyPartitioner]) + diff --git a/tests/sfts.py b/tests/sfts.py index 5645b20..87d649d 100644 --- a/tests/sfts.py +++ b/tests/sfts.py @@ -61,4 +61,4 @@ for max_part in [10, 20, 30, 40, 50]: models.append(model) ixs.append(ix) -print(bchmk.getPointStatistics(sample, models, indexers=ixs)) \ No newline at end of file +print(bchmk.print_point_statistics(sample, models, indexers=ixs)) \ No newline at end of file diff --git a/yu.py b/yu.py index 42f2706..5464b58 100644 --- a/yu.py +++ b/yu.py @@ -32,7 +32,7 @@ class WeightedFLRG(fts.FTS): class WeightedFTS(fts.FTS): def __init__(self, name): - super(WeightedFTS, self).__init__(1, "WFTS") + super(WeightedFTS, self).__init__(1, "WFTS " + name) self.name = "Weighted FTS" self.detail = "Yu"