diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py index 117986a..7d23254 100644 --- a/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -11,19 +11,58 @@ from mpl_toolkits.mplot3d import Axes3D from pyFTS.benchmarks import Measures from pyFTS.partitioners import Grid from pyFTS.common import Membership, FuzzySet, FLR, Transformations, Util -from pyFTS import pfts +from pyFTS import fts, chen, yu, ismailefendi, sadaei, hofts, hwang, pfts, ifts + + +def allPointForecasters(data_train, data_test, partitions, max_order=2,save=False, file=None, tam=[20, 5]): + models = [chen.ConventionalFTS, yu.WeightedFTS, ismailefendi.ImprovedWeightedFTS, sadaei.ExponentialyWeightedFTS, + hwang.HighOrderFTS, hofts.HighOrderFTS, pfts.ProbabilisticFTS ] + + objects = [] + + data_train_fs = Grid.GridPartitionerTrimf(data_train,partitions) + + for model in models: + fts = model("") + if not fts.isHighOrder: + fts.train(data_train, data_train_fs) + objects.append(fts) + else: + for order in np.arange(1,max_order+1): + fts.train(data_train, data_train_fs, order=order) + fts.shortname += str(order) + objects.append(fts) + + print(getPointStatistics(data_test, objects)) + + +def getPointStatistics(original, models, externalmodels = None, externalforecasts = None): + ret = "Model & RMSE & MAPE \\ \n" + for fts in models: + forecasts = fts.forecast(original) + ret += fts.shortname + " & " + ret += str(round(Measures.rmse(original[fts.order:], forecasts[:-1]), 2)) + " & " + ret += str(round(Measures.mape(original[fts.order:], forecasts[:-1]), 2)) + " & " + ret += " \\ \n" + l = len(externalmodels) + for k in np.arange(0,l): + ret += externalmodels[k] + " & " + ret += str(round(Measures.rmse(original[fts.order:], externalforecasts[k][:-1]), 2)) + " & " + ret += str(round(Measures.mape(original[fts.order:], externalforecasts[k][:-1]), 2)) + " & " + ret += " \\ \n" + return ret def getIntervalStatistics(original, models): ret = "Model & RMSE & MAPE & Sharpness & Resolution & Coverage \\ \n" for fts in models: - forecasts = fts.forecast(original) - ret = ret + fts.shortname + " & " - ret = ret + str(round(Measures.rmse_interval(original[fts.order - 1:], forecasts), 2)) + " & " - ret = ret + str(round(Measures.mape_interval(original[fts.order - 1:], forecasts), 2)) + " & " - ret = ret + str(round(Measures.sharpness(forecasts), 2)) + " & " - ret = ret + str(round(Measures.resolution(forecasts), 2)) + " & " - ret = ret + str(round(Measures.coverage(original[fts.order - 1:], forecasts), 2)) + " \\ \n" + forecasts = fts.forecastInterval(original) + ret += fts.shortname + " & " + ret += str(round(Measures.rmse_interval(original[fts.order:], forecasts[:-1]), 2)) + " & " + ret += str(round(Measures.mape_interval(original[fts.order:], forecasts[:-1]), 2)) + " & " + ret += str(round(Measures.sharpness(forecasts), 2)) + " & " + ret += str(round(Measures.resolution(forecasts), 2)) + " & " + ret += str(round(Measures.coverage(original[fts.order:], forecasts[:-1]), 2)) + " \\ \n" return ret diff --git a/chen.py b/chen.py index fb6c7b4..86ffbfd 100644 --- a/chen.py +++ b/chen.py @@ -1,6 +1,6 @@ import numpy as np from pyFTS.common import FuzzySet, FLR -from pyFTS import fts +from pyFTS import fts class ConventionalFLRG: @@ -38,7 +38,7 @@ class ConventionalFTS(fts.FTS): flrgs[flr.LHS.name].append(flr.RHS) return (flrgs) - def train(self, data, sets): + def train(self, data, sets,order=1,parameters=None): self.sets = sets tmpdata = FuzzySet.fuzzySeries(data, sets) flrs = FLR.generateNonRecurrentFLRs(tmpdata) diff --git a/common/Transformations.py b/common/Transformations.py index 869b6f8..5bb1e12 100644 --- a/common/Transformations.py +++ b/common/Transformations.py @@ -3,10 +3,10 @@ import math from pyFTS import * -def differential(original): +def differential(original, lags=1): n = len(original) - diff = [original[t - 1] - original[t] for t in np.arange(1, n)] - diff.insert(0, 0) + diff = [original[t - lags] - original[t] for t in np.arange(lags, n)] + for t in np.arange(0, lags): diff.insert(0, None) return np.array(diff) @@ -24,3 +24,12 @@ def Z(original): sigma = np.std(original) z = [(k - mu)/sigma for k in original] return z + + +# retrieved from Sadaei and Lee (2014) - Multilayer Stock ForecastingModel Using Fuzzy Time Series +def roi(original): + n = len(original) + roi = [] + for t in np.arange(0, n-1): + roi.append( (original[t+1] - original[t])/original[t] ) + return roi diff --git a/fts.py b/fts.py index 67dabd1..e8ee012 100644 --- a/fts.py +++ b/fts.py @@ -10,6 +10,7 @@ class FTS: self.shortname = name self.name = name self.detail = name + self.isHighOrder = False self.hasSeasonality = False self.hasPointForecasting = True self.hasIntervalForecasting = False @@ -45,7 +46,7 @@ class FTS: def forecastAheadDistribution(self, data, steps): pass - def train(self, data, sets, order=1): + def train(self, data, sets,order=1, parameters=None): pass def getMidpoints(self, flrg): diff --git a/hofts.py b/hofts.py index ec0bd6c..7c5b144 100644 --- a/hofts.py +++ b/hofts.py @@ -41,6 +41,7 @@ class HighOrderFTS(fts.FTS): self.detail = "Chen" self.order = 1 self.setsDict = {} + self.isHighOrder = True def generateFLRG(self, flrs): flrgs = {} @@ -58,7 +59,7 @@ class HighOrderFTS(fts.FTS): flrgs[flrg.strLHS()].appendRHS(flrs[k].RHS) return (flrgs) - def train(self, data, sets, order): + def train(self, data, sets, order=1,parameters=None): self.order = order self.sets = sets for s in self.sets: self.setsDict[s.name] = s diff --git a/hwang.py b/hwang.py index 736b16a..db080e1 100644 --- a/hwang.py +++ b/hwang.py @@ -6,33 +6,35 @@ from pyFTS import fts class HighOrderFTS(fts.FTS): def __init__(self, order, name): super(HighOrderFTS, self).__init__(order, name) + self.isHighOrder = True - def forecast(self, data, t): + def forecast(self, data): cn = np.array([0.0 for k in range(len(self.sets))]) ow = np.array([[0.0 for k in range(len(self.sets))] for z in range(self.order - 1)]) rn = np.array([[0.0 for k in range(len(self.sets))] for z in range(self.order - 1)]) ft = np.array([0.0 for k in range(len(self.sets))]) - for s in range(len(self.sets)): - cn[s] = self.sets[s].membership(data[t]) - for w in range(self.order - 1): - ow[w, s] = self.sets[s].membership(data[t - w]) - rn[w, s] = ow[w, s] * cn[s] - ft[s] = max(ft[s], rn[w, s]) - mft = max(ft) - out = 0.0 - count = 0.0 - for s in range(len(self.sets)): - if ft[s] == mft: - out = out + self.sets[s].centroid - count = count + 1.0 - return out / count + ret = [] - def train(self, data, sets): + for t in np.arange(self.order, len(data)): + + for s in range(len(self.sets)): + cn[s] = self.sets[s].membership(data[t]) + for w in range(self.order - 1): + ow[w, s] = self.sets[s].membership(data[t - w]) + rn[w, s] = ow[w, s] * cn[s] + ft[s] = max(ft[s], rn[w, s]) + mft = max(ft) + out = 0.0 + count = 0.0 + for s in range(len(self.sets)): + if ft[s] == mft: + out = out + self.sets[s].centroid + count = count + 1.0 + ret.append(out / count) + + return ret + + def train(self, data, sets, order=2, parameters=None): self.sets = sets - - def predict(self, data, t): - return self.forecast(data, t) - - def predictDiff(self, data, t): - return data[t] + self.forecast(Transformations.differential(data), t) + self.order = order \ No newline at end of file diff --git a/ifts.py b/ifts.py index bb257ae..32800c3 100644 --- a/ifts.py +++ b/ifts.py @@ -15,6 +15,7 @@ class IntervalFTS(hofts.HighOrderFTS): self.flrgs = {} self.hasPointForecasting = False self.hasIntervalForecasting = True + self.isHighOrder = True def getUpper(self, flrg): if flrg.strLHS() in self.flrgs: diff --git a/ismailefendi.py b/ismailefendi.py index 01ebb60..eac4d39 100644 --- a/ismailefendi.py +++ b/ismailefendi.py @@ -1,6 +1,6 @@ import numpy as np from pyFTS.common import FuzzySet,FLR -import fts +from pyFTS import fts class ImprovedWeightedFLRG: @@ -46,7 +46,7 @@ class ImprovedWeightedFTS(fts.FTS): flrgs[flr.LHS.name].append(flr.RHS) return (flrgs) - def train(self, data, sets): + def train(self, data, sets,order=1,parameters=None): self.sets = sets for s in self.sets: self.setsDict[s.name] = s diff --git a/pfts.py b/pfts.py index 1e80105..1826e74 100644 --- a/pfts.py +++ b/pfts.py @@ -46,6 +46,7 @@ class ProbabilisticFTS(ifts.IntervalFTS): self.hasPointForecasting = True self.hasIntervalForecasting = True self.hasDistributionForecasting = True + self.isHighOrder = True def generateFLRG(self, flrs): flrgs = {} diff --git a/sadaei.py b/sadaei.py index 0fb02f4..1bd75de 100644 --- a/sadaei.py +++ b/sadaei.py @@ -1,6 +1,6 @@ import numpy as np from pyFTS.common import FuzzySet,FLR -import fts +from pyFTS import fts class ExponentialyWeightedFLRG: def __init__(self, LHS, c): @@ -49,8 +49,8 @@ class ExponentialyWeightedFTS(fts.FTS): flrgs[flr.LHS.name].append(flr.RHS) return (flrgs) - def train(self, data, sets, c): - self.c = c + def train(self, data, sets,order=1,parameters=2): + self.c = parameters self.sets = sets tmpdata = FuzzySet.fuzzySeries(data, sets) flrs = FLR.generateRecurrentFLRs(tmpdata) diff --git a/sfts.py b/sfts.py index 6565143..4070f21 100644 --- a/sfts.py +++ b/sfts.py @@ -44,9 +44,9 @@ class SeasonalFTS(fts.FTS): return (flrgs) - def train(self, data, sets, seasonality): + def train(self, data, sets, order=1,parameters=12): self.sets = sets - self.seasonality = seasonality + self.seasonality = parameters tmpdata = FuzzySet.fuzzySeries(data, sets) flrs = FLR.generateRecurrentFLRs(tmpdata) self.flrgs = self.generateFLRG(flrs) diff --git a/yu.py b/yu.py index 6a11a11..effbc99 100644 --- a/yu.py +++ b/yu.py @@ -1,6 +1,6 @@ import numpy as np from pyFTS.common import FuzzySet,FLR -import fts +from pyFTS import fts class WeightedFLRG(fts.FTS): @@ -46,7 +46,7 @@ class WeightedFTS(fts.FTS): flrgs[flr.LHS.name].append(flr.RHS) return (flrgs) - def train(self, data, sets): + def train(self, data, sets,order=1,parameters=None): self.sets = sets tmpdata = FuzzySet.fuzzySeries(data, sets) flrs = FLR.generateRecurrentFLRs(tmpdata)