- Several bugfixes

- Issue #2 - PEP 8 compliance
  - Issue #3 - Code documentation with PEP 257 compliance
This commit is contained in:
Petrônio Cândido de Lima e Silva 2017-05-02 11:32:03 -03:00
parent 474a9d87a7
commit a4903fd932
25 changed files with 335 additions and 70 deletions

View File

@ -0,0 +1,3 @@
"""
pyFTS - A Python library for Fuzzy Time Series models
"""

View File

@ -1,12 +1,21 @@
# -*- coding: utf8 -*-
"""
pyFTS module for common benchmark metrics
"""
import numpy as np
import pandas as pd
from pyFTS.common import FuzzySet,SortedCollection
# Autocorrelation function estimative
def acf(data, k):
"""
Autocorrelation function estimative
:param data:
:param k:
:return:
"""
mu = np.mean(data)
sigma = np.var(data)
n = len(data)
@ -17,22 +26,45 @@ def acf(data, k):
return 1/((n-k)*sigma)*s
# Erro quadrático médio
def rmse(targets, forecasts):
"""
Root Mean Squared Error
:param targets:
:param forecasts:
:return:
"""
return np.sqrt(np.nanmean((targets - forecasts) ** 2))
def rmse_interval(targets, forecasts):
"""
Root Mean Squared Error
:param targets:
:param forecasts:
:return:
"""
fmean = [np.mean(i) for i in forecasts]
return np.sqrt(np.nanmean((fmean - targets) ** 2))
# Erro Percentual médio
def mape(targets, forecasts):
"""
Mean Average Percentual Error
:param targets:
:param forecasts:
:return:
"""
return np.mean(np.abs(targets - forecasts) / targets) * 100
def smape(targets, forecasts, type=2):
"""
Symmetric Mean Average Percentual Error
:param targets:
:param forecasts:
:param type:
:return:
"""
if type == 1:
return np.mean(np.abs(forecasts - targets) / ((forecasts + targets)/2))
elif type == 2:
@ -46,8 +78,13 @@ def mape_interval(targets, forecasts):
return np.mean(abs(fmean - targets) / fmean) * 100
# Theil's U Statistic
def UStatistic(targets, forecasts):
"""
Theil's U Statistic
:param targets:
:param forecasts:
:return:
"""
l = len(targets)
naive = []
y = []
@ -57,8 +94,13 @@ def UStatistic(targets, forecasts):
return np.sqrt(sum(y) / sum(naive))
# Theils Inequality Coefficient
def TheilsInequality(targets, forecasts):
"""
Theils Inequality Coefficient
:param targets:
:param forecasts:
:return:
"""
res = targets - forecasts
t = len(res)
us = np.sqrt(sum([u**2 for u in res]))
@ -67,8 +109,13 @@ def TheilsInequality(targets, forecasts):
return us / (ys + fs)
# Q Statistic for Box-Pierce test
def BoxPierceStatistic(data, h):
"""
Q Statistic for Box-Pierce test
:param data:
:param h:
:return:
"""
n = len(data)
s = 0
for k in np.arange(1,h+1):
@ -77,8 +124,13 @@ def BoxPierceStatistic(data, h):
return n*s
# Q Statistic for LjungBox test
def BoxLjungStatistic(data, h):
"""
Q Statistic for LjungBox test
:param data:
:param h:
:return:
"""
n = len(data)
s = 0
for k in np.arange(1,h+1):
@ -87,21 +139,21 @@ def BoxLjungStatistic(data, h):
return n*(n-2)*s
# Sharpness - Mean size of the intervals
def sharpness(forecasts):
"""Sharpness - Mean size of the intervals"""
tmp = [i[1] - i[0] for i in forecasts]
return np.mean(tmp)
# Resolution - Standard deviation of the intervals
def resolution(forecasts):
"""Resolution - Standard deviation of the intervals"""
shp = sharpness(forecasts)
tmp = [abs((i[1] - i[0]) - shp) for i in forecasts]
return np.mean(tmp)
# Percent of
def coverage(targets, forecasts):
"""Percent of"""
preds = []
for i in np.arange(0, len(forecasts)):
if targets[i] >= forecasts[i][0] and targets[i] <= forecasts[i][1]:
@ -133,8 +185,8 @@ def heavyside_cdf(bins, targets):
return df
# Continuous Ranked Probability Score
def crps(targets, densities):
"""Continuous Ranked Probability Score"""
l = len(densities.columns)
n = len(densities.index)
Ff = pmf_to_cdf(densities)

View File

@ -0,0 +1,3 @@
"""
pyFTS module for benchmarking the FTS models
"""

View File

@ -7,11 +7,14 @@ from pyFTS import fts
class ARIMA(fts.FTS):
"""
Façade for statsmodels.tsa.arima_model
"""
def __init__(self, order, **kwargs):
super(ARIMA, self).__init__(1, "ARIMA")
self.name = "ARIMA"
self.detail = "Auto Regressive Integrated Moving Average"
self.isHighOrder = True
self.is_high_order = True
self.model = None
self.model_fit = None
self.trained_data = None
@ -19,7 +22,7 @@ class ARIMA(fts.FTS):
self.d = 0
self.q = 0
self.benchmark_only = True
self.minOrder = 1
self.min_order = 1
def train(self, data, sets, order=1, parameters=None):
if parameters is not None:

View File

@ -5,12 +5,13 @@ from pyFTS import fts
class Naive(fts.FTS):
"""Naïve Forecasting method"""
def __init__(self, order, name, **kwargs):
super(Naive, self).__init__(1, "Naive " + name)
self.name = "Naïve Model"
self.detail = "Naïve Model"
self.benchmark_only = True
self.isHighOrder = False
self.is_high_order = False
def forecast(self, data, **kwargs):
return [k for k in data]

View File

@ -8,13 +8,14 @@ from pyFTS import fts
class QuantileRegression(fts.FTS):
"""Façade for statsmodels.regression.quantile_regression"""
def __init__(self, order, **kwargs):
super(QuantileRegression, self).__init__(1, "QR")
self.name = "QR"
self.detail = "Quantile Regression"
self.isHighOrder = True
self.hasPointForecasting = True
self.hasIntervalForecasting = True
self.is_high_order = True
self.has_point_forecasting = True
self.has_interval_forecasting = True
self.benchmark_only = True
self.minOrder = 1
self.alpha = 0.5

View File

@ -1,9 +1,18 @@
import numpy as np
from pyFTS.common import FuzzySet
"""
This module implements functions for Fuzzy Logical Relationship generation
"""
class FLR(object):
"""Fuzzy Logical Relationship"""
def __init__(self, LHS, RHS):
"""
Creates a Fuzzy Logical Relationship
:param LHS: Left Hand Side fuzzy set
:param RHS: Right Hand Side fuzzy set
"""
self.LHS = LHS
self.RHS = RHS
@ -12,7 +21,14 @@ class FLR(object):
class IndexedFLR(FLR):
"""Season Indexed Fuzzy Logical Relationship"""
def __init__(self, index, LHS, RHS):
"""
Create a Season Indexed Fuzzy Logical Relationship
:param index: seasonal index
:param LHS: Left Hand Side fuzzy set
:param RHS: Right Hand Side fuzzy set
"""
super(IndexedFLR, self).__init__(LHS, RHS)
self.index = index
@ -21,6 +37,11 @@ class IndexedFLR(FLR):
def generateNonRecurrentFLRs(fuzzyData):
"""
Create a ordered FLR set from a list of fuzzy sets without recurrence
:param fuzzyData: ordered list of fuzzy sets
:return: ordered list of FLR
"""
flrs = {}
for i in range(2,len(fuzzyData)):
tmp = FLR(fuzzyData[i-1],fuzzyData[i])
@ -30,6 +51,11 @@ def generateNonRecurrentFLRs(fuzzyData):
def generateRecurrentFLRs(fuzzyData):
"""
Create a ordered FLR set from a list of fuzzy sets with recurrence
:param fuzzyData: ordered list of fuzzy sets
:return: ordered list of FLR
"""
flrs = []
for i in np.arange(1,len(fuzzyData)):
flrs.append(FLR(fuzzyData[i-1],fuzzyData[i]))
@ -37,6 +63,13 @@ def generateRecurrentFLRs(fuzzyData):
def generateIndexedFLRs(sets, indexer, data):
"""
Create a season-indexed ordered FLR set from a list of fuzzy sets with recurrence
:param sets: fuzzy sets
:param indexer: seasonality indexer
:param data: original data
:return: ordered list of FLR
"""
flrs = []
index = indexer.get_season_of_data(data)
ndata = indexer.get_data(data)

View File

@ -4,7 +4,17 @@ from pyFTS.common import Membership
class FuzzySet:
"""
Fuzzy Set
"""
def __init__(self, name, mf, parameters, centroid):
"""
Create a Fuzzy Set
:param name: fuzzy set name
:param mf: membership function
:param parameters: parameters of the membership function
:param centroid: fuzzy set center of mass
"""
self.name = name
self.mf = mf
self.parameters = parameters
@ -17,6 +27,11 @@ class FuzzySet:
self.upper = parameters[0] + parameters[1]*3
def membership(self, x):
"""
Calculate the membership value of a given input
:param x: input value
:return: membership value of x at this fuzzy set
"""
return self.mf(x, self.parameters)
def __str__(self):
@ -24,11 +39,23 @@ class FuzzySet:
def fuzzyInstance(inst, fuzzySets):
"""
Calculate the membership values for a data point given fuzzy sets
:param inst: data point
:param fuzzySets: list of fuzzy sets
:return: array of membership values
"""
mv = np.array([fs.membership(inst) for fs in fuzzySets])
return mv
def fuzzyInstances(data, fuzzySets):
"""
Calculate the membership values for a data point given fuzzy sets
:param inst: data point
:param fuzzySets: list of fuzzy sets
:return: array of membership values
"""
ret = []
for inst in data:
mv = np.array([fs.membership(inst) for fs in fuzzySets])
@ -37,10 +64,22 @@ def fuzzyInstances(data, fuzzySets):
def getMaxMembershipFuzzySet(inst, fuzzySets):
"""
Fuzzify a data point, returning the fuzzy set with maximum membership value
:param inst: data point
:param fuzzySets: list of fuzzy sets
:return: fuzzy set with maximum membership
"""
mv = fuzzyInstance(inst, fuzzySets)
return fuzzySets[np.argwhere(mv == max(mv))[0, 0]]
def getMaxMembershipFuzzySetIndex(inst, fuzzySets):
"""
Fuzzify a data point, returning the fuzzy set with maximum membership value
:param inst: data point
:param fuzzySets: list of fuzzy sets
:return: fuzzy set with maximum membership
"""
mv = fuzzyInstance(inst, fuzzySets)
return np.argwhere(mv == max(mv))[0, 0]

View File

@ -4,6 +4,12 @@ from pyFTS import *
def trimf(x, parameters):
"""
Triangular fuzzy membership function
:param x: data point
:param parameters: a list with 3 real values
:return: the membership value of x given the parameters
"""
xx = round(x, 3)
if xx < parameters[0]:
return 0
@ -16,6 +22,12 @@ def trimf(x, parameters):
def trapmf(x, parameters):
"""
Trapezoidal fuzzy membership function
:param x: data point
:param parameters: a list with 4 real values
:return: the membership value of x given the parameters
"""
if x < parameters[0]:
return 0
elif parameters[0] <= x < parameters[1]:
@ -29,6 +41,12 @@ def trapmf(x, parameters):
def gaussmf(x, parameters):
"""
Gaussian fuzzy membership function
:param x: data point
:param parameters: a list with 2 real values (mean and variance)
:return: the membership value of x given the parameters
"""
return math.exp((-(x - parameters[0])**2)/(2 * parameters[1]**2))
#return math.exp(-0.5 * ((x - parameters[0]) / parameters[1]) ** 2)

View File

@ -4,6 +4,9 @@ from pyFTS import *
class Transformation(object):
"""
Data transformation used to pre and post processing of the FTS
"""
def __init__(self, parameters):
self.isInversible = True
@ -21,7 +24,9 @@ class Transformation(object):
class Differential(Transformation):
"""
Differentiation data transform
"""
def __init__(self, parameters):
super(Differential, self).__init__(parameters)
self.lag = parameters
@ -61,7 +66,9 @@ class Differential(Transformation):
class AdaptiveExpectation(Transformation):
"""
Adaptive Expectation post processing
"""
def __init__(self, parameters):
super(AdaptiveExpectation, self).__init__(parameters)
self.h = parameters

View File

@ -15,10 +15,10 @@ class EnsembleFTS(fts.FTS):
self.shortname = "Ensemble FTS " + name
self.name = "Ensemble FTS"
self.flrgs = {}
self.hasPointForecasting = True
self.hasIntervalForecasting = True
self.hasDistributionForecasting = True
self.isHighOrder = True
self.has_point_forecasting = True
self.has_interval_forecasting = True
self.has_probability_forecasting = True
self.is_high_order = True
self.models = []
self.parameters = []
@ -40,7 +40,7 @@ class EnsembleFTS(fts.FTS):
mfts = model("")
mfts.partitioner = data_train_fs
if not mfts.isHighOrder:
if not mfts.is_high_order:
if transformation is not None:
mfts.appendTransformation(transformation)
@ -49,7 +49,7 @@ class EnsembleFTS(fts.FTS):
self.models.append(mfts)
else:
for order in np.arange(1, max_order + 1):
if order >= mfts.minOrder:
if order >= mfts.min_order:
mfts = model("")
mfts.partitioner = data_train_fs

76
fts.py
View File

@ -3,21 +3,31 @@ import pandas as pd
from pyFTS import tree
from pyFTS.common import FuzzySet, SortedCollection
class FTS(object):
"""
Fuzzy Time Series
"""
def __init__(self, order, name, **kwargs):
"""
Create a Fuzzy Time Series model
:param order: model order
:param name: model name
:param kwargs: model specific parameters
"""
self.sets = {}
self.flrgs = {}
self.order = order
self.shortname = name
self.name = name
self.detail = name
self.isHighOrder = False
self.minOrder = 1
self.hasSeasonality = False
self.hasPointForecasting = True
self.hasIntervalForecasting = False
self.hasDistributionForecasting = False
self.isMultivariate = False
self.is_high_order = False
self.min_order = 1
self.has_seasonality = False
self.has_point_forecasting = True
self.has_interval_forecasting = False
self.has_probability_forecasting = False
self.is_multivariate = False
self.dump = False
self.transformations = []
self.transformations_param = []
@ -28,6 +38,11 @@ class FTS(object):
self.benchmark_only = False
def fuzzy(self, data):
"""
Fuzzify a data point
:param data: data point
:return: maximum membership fuzzy set
"""
best = {"fuzzyset": "", "membership": 0.0}
for f in self.sets:
@ -39,24 +54,71 @@ class FTS(object):
return best
def forecast(self, data, **kwargs):
"""
Point forecast one step ahead
:param data: time series with minimal length to the order of the model
:param kwargs:
:return:
"""
pass
def forecastInterval(self, data, **kwargs):
"""
Interval forecast one step ahead
:param data:
:param kwargs:
:return:
"""
pass
def forecastDistribution(self, data, **kwargs):
"""
Probabilistic forecast one step ahead
:param data:
:param kwargs:
:return:
"""
pass
def forecastAhead(self, data, steps, **kwargs):
"""
Point forecast n steps ahead
:param data:
:param steps:
:param kwargs:
:return:
"""
pass
def forecastAheadInterval(self, data, steps, **kwargs):
"""
Interval forecast n steps ahead
:param data:
:param steps:
:param kwargs:
:return:
"""
pass
def forecastAheadDistribution(self, data, steps, **kwargs):
"""
Probabilistic forecast n steps ahead
:param data:
:param steps:
:param kwargs:
:return:
"""
pass
def train(self, data, sets, order=1, parameters=None):
"""
:param data:
:param sets:
:param order:
:param parameters:
:return:
"""
pass
def getMidpoints(self, flrg):

View File

@ -46,7 +46,7 @@ class HighOrderFTS(fts.FTS):
self.detail = "Chen"
self.order = 1
self.setsDict = {}
self.isHighOrder = True
self.is_high_order = True
def generateFLRG(self, flrs):
flrgs = {}

View File

@ -4,10 +4,10 @@ from pyFTS import fts
class HighOrderFTS(fts.FTS):
def __init__(self, order, **kwargs):
def __init__(self, order, name, **kwargs):
super(HighOrderFTS, self).__init__(1, name)
self.isHighOrder = True
self.minOrder = 2
self.is_high_order = True
self.min_order = 2
self.name = "Hwang High Order FTS"
self.shortname = "Hwang" + name
self.detail = "Hwang"

View File

@ -13,9 +13,9 @@ class IntervalFTS(hofts.HighOrderFTS):
self.name = "Interval FTS"
self.detail = "Silva, P.; Guimarães, F.; Sadaei, H. (2016)"
self.flrgs = {}
self.hasPointForecasting = False
self.hasIntervalForecasting = True
self.isHighOrder = True
self.has_point_forecasting = False
self.has_point_forecasting = True
self.is_high_order = True
def getUpper(self, flrg):
if flrg.strLHS() in self.flrgs:

View File

@ -33,7 +33,7 @@ class ImprovedWeightedFLRG(object):
class ImprovedWeightedFTS(fts.FTS):
def __init__(self, order, **kwargs):
def __init__(self, order, name, **kwargs):
super(ImprovedWeightedFTS, self).__init__(1, "IWFTS " + name)
self.name = "Improved Weighted FTS"
self.detail = "Ismail & Efendi"

View File

@ -4,6 +4,9 @@ from pyFTS import fts, sfts, chen
class ContextualSeasonalFLRG(object):
"""
Contextual Seasonal Fuzzy Logical Relationship Group
"""
def __init__(self, seasonality):
self.season = seasonality
self.flrgs = {}
@ -24,16 +27,19 @@ class ContextualSeasonalFLRG(object):
class ContextualMultiSeasonalFTS(sfts.SeasonalFTS):
def __init__(self, order, name, **kwargs):
"""
Contextual Multi-Seasonal Fuzzy Time Series
"""
def __init__(self, order, name, indexer, **kwargs):
super(ContextualMultiSeasonalFTS, self).__init__("CMSFTS")
self.name = "Contextual Multi Seasonal FTS"
self.shortname = "CMSFTS " + name
self.detail = ""
self.seasonality = 1
self.hasSeasonality = True
self.hasPointForecasting = True
self.isHighOrder = True
self.isMultivariate = True
self.has_seasonality = True
self.has_point_forecasting = True
self.is_high_order = True
self.is_multivariate = True
self.indexer = indexer
self.flrgs = {}

View File

@ -4,7 +4,10 @@ from pyFTS import fts, sfts
class MultiSeasonalFTS(sfts.SeasonalFTS):
def __init__(self, order, name, **kwargs):
"""
Multi-Seasonal Fuzzy Time Series
"""
def __init__(self, order, name, indexer, **kwargs):
super(MultiSeasonalFTS, self).__init__("MSFTS")
self.name = "Multi Seasonal FTS"
self.shortname = "MSFTS " + name

View File

@ -2,6 +2,9 @@ import numpy as np
from enum import Enum
class SeasonalIndexer(object):
"""
Seasonal Indexer. Responsible to find the seasonal index of a data point inside its data set
"""
def __init__(self,num_seasons):
self.num_seasons = num_seasons

View File

@ -0,0 +1,3 @@
"""
Module for pyFTS Universe of Discourse partitioners.
"""

View File

@ -3,7 +3,21 @@ import numpy as np
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):
"""
Universe of Discourse partitioner scheme. Split data on several fuzzy sets
:param name: partitioner name
:param data: original data to be partitioned
:param npart: number of partitions
:param func: membership function
:param names: list of partitions names. If None is given the partitions will be auto named with prefix
:param prefix: prefix of auto generated partition names
:param transformation: data transformation to be applied on data
"""
self.name = name
self.partitions = npart
self.sets = []
@ -31,9 +45,19 @@ class Partitioner(object):
self.sets = self.build(ndata)
def build(self, data):
"""
Perform the partitioning of the Universe of Discourse
:param data:
:return:
"""
pass
def plot(self, ax):
"""
Plot the
:param ax:
:return:
"""
ax.set_title(self.name)
ax.set_ylim([0, 1])
ax.set_xlim([self.min, self.max])

View File

@ -13,31 +13,31 @@ class ProbabilisticWeightedFLRG(hofts.HighOrderFLRG):
def __init__(self, order):
super(ProbabilisticWeightedFLRG, self).__init__(order)
self.RHS = {}
self.frequencyCount = 0.0
self.frequency_count = 0.0
def appendRHS(self, c):
self.frequencyCount += 1.0
self.frequency_count += 1.0
if c.name in self.RHS:
self.RHS[c.name] += 1.0
else:
self.RHS[c.name] = 1.0
def appendRHSFuzzy(self, c, mv):
self.frequencyCount += mv
self.frequency_count += mv
if c.name in self.RHS:
self.RHS[c.name] += mv
else:
self.RHS[c.name] = mv
def get_probability(self, c):
return self.RHS[c] / self.frequencyCount
return self.RHS[c] / self.frequency_count
def __str__(self):
tmp2 = ""
for c in sorted(self.RHS):
if len(tmp2) > 0:
tmp2 = tmp2 + ", "
tmp2 = tmp2 + "(" + str(round(self.RHS[c] / self.frequencyCount, 3)) + ")" + c
tmp2 = tmp2 + "(" + str(round(self.RHS[c] / self.frequency_count, 3)) + ")" + c
return self.strLHS() + " -> " + tmp2
@ -48,11 +48,11 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
self.name = "Probabilistic FTS"
self.detail = "Silva, P.; Guimarães, F.; Sadaei, H."
self.flrgs = {}
self.globalFrequency = 0
self.hasPointForecasting = True
self.hasIntervalForecasting = True
self.hasDistributionForecasting = True
self.isHighOrder = True
self.global_frequency_count = 0
self.has_point_forecasting = True
self.has_interval_forecasting = True
self.has_probability_forecasting = True
self.is_high_order = True
self.auto_update = kwargs.get('update',False)
def train(self, data, sets, order=1,parameters=None):
@ -108,7 +108,7 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
for c, e in enumerate(_sets, start=0):
flrgs[flrg.strLHS()].appendRHSFuzzy(e,rhs_mv[c]*max(lhs_mv))
self.globalFrequency += max(lhs_mv)
self.global_frequency_count += max(lhs_mv)
return (flrgs)
@ -130,7 +130,7 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
flrgs[flrg.strLHS()].appendRHS(flrs[k-1].RHS)
if self.dump: print("RHS: " + str(flrs[k-1]))
self.globalFrequency += 1
self.global_frequency_count += 1
return (flrgs)
def update_model(self,data):
@ -147,7 +147,7 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
self.flrgs[flrg.strLHS()] = flrg
self.flrgs[flrg.strLHS()].appendRHS(fzzy[self.order])
self.globalFrequency += 1
self.global_frequency_count += 1
def add_new_PWFLGR(self, flrg):
if flrg.strLHS() not in self.flrgs:
@ -155,11 +155,11 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
for fs in flrg.LHS: tmp.appendLHS(fs)
tmp.appendRHS(flrg.LHS[-1])
self.flrgs[tmp.strLHS()] = tmp;
self.globalFrequency += 1
self.global_frequency_count += 1
def get_probability(self, flrg):
if flrg.strLHS() in self.flrgs:
return self.flrgs[flrg.strLHS()].frequencyCount / self.globalFrequency
return self.flrgs[flrg.strLHS()].frequency_count / self.global_frequency_count
else:
self.add_new_PWFLGR(flrg)
return self.get_probability(flrg)
@ -572,6 +572,6 @@ class ProbabilisticWeightedFTS(ifts.IntervalFTS):
def __str__(self):
tmp = self.name + ":\n"
for r in sorted(self.flrgs):
p = round(self.flrgs[r].frequencyCount / self.globalFrequency, 3)
p = round(self.flrgs[r].frequencyCount / self.global_frequency_count, 3)
tmp = tmp + "(" + str(p) + ") " + str(self.flrgs[r]) + "\n"
return tmp

View File

@ -2,6 +2,7 @@ import numpy as np
from pyFTS.common import FuzzySet,FLR
from pyFTS import fts
class ExponentialyWeightedFLRG(object):
def __init__(self, LHS, c):
self.LHS = LHS

View File

@ -31,9 +31,9 @@ class SeasonalFTS(fts.FTS):
self.name = "Seasonal FTS"
self.detail = "Chen"
self.seasonality = 1
self.hasSeasonality = True
self.hasPointForecasting = True
self.isHighOrder = False
self.has_seasonality = True
self.has_point_forecasting = True
self.is_high_order = False
def generateFLRG(self, flrs):
flrgs = []

View File

@ -0,0 +1,3 @@
"""
Module for testing pyFTS modules and models
"""