diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index 963d678..f2f3aca 100644 Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ diff --git a/pyFTS/common/fts.py b/pyFTS/common/fts.py index 77b9c96..0ed9ef4 100644 --- a/pyFTS/common/fts.py +++ b/pyFTS/common/fts.py @@ -101,7 +101,8 @@ class FTS(object): :keyword explain: try to explain, step by step, the one-step-ahead point forecasting result given the input data. :keyword generators: for multivariate methods on multi step ahead forecasting, generators is a dict where the keys are the variables names (except the target_variable) and the values are lambda functions that - accept one value (the actual value of the variable) and return the next value. + accept one value (the actual value of the variable) and return the next value or trained FTS + models that accept the actual values and forecast new ones. :return: a numpy array with the forecasted data """ diff --git a/pyFTS/models/multivariate/mvfts.py b/pyFTS/models/multivariate/mvfts.py index c8c54f2..410fb10 100644 --- a/pyFTS/models/multivariate/mvfts.py +++ b/pyFTS/models/multivariate/mvfts.py @@ -2,6 +2,7 @@ from pyFTS.common import fts, FuzzySet, FLR, Membership from pyFTS.partitioners import Grid from pyFTS.models.multivariate import FLR as MVFLR, common, flrg as mvflrg from itertools import product +from types import LambdaType import numpy as np import pandas as pd @@ -52,11 +53,15 @@ class MVFTS(fts.FTS): def apply_transformations(self, data, params=None, updateUoD=False, **kwargs): ndata = data.copy(deep=True) for var in self.explanatory_variables: - if self.uod_clip and var.partitioner.type == 'common': - ndata[var.data_label] = np.clip(ndata[var.data_label].values, - var.partitioner.min, var.partitioner.max) + try: + values = ndata[var.data_label].values #if isinstance(ndata, pd.DataFrame) else ndata[var.data_label] + if self.uod_clip and var.partitioner.type == 'common': + ndata[var.data_label] = np.clip(values, + var.partitioner.min, var.partitioner.max) - ndata[var.data_label] = var.apply_transformations(ndata[var.data_label].values) + ndata[var.data_label] = var.apply_transformations(values) + except: + pass return ndata @@ -120,7 +125,7 @@ class MVFTS(fts.FTS): ret = [] ndata = self.apply_transformations(data) c = 0 - for index, row in ndata.iterrows(): + for index, row in ndata.iterrows() if isinstance(ndata, pd.DataFrame) else enumerate(ndata): data_point = self.format_data(row) flrs = self.generate_lhs_flrs(data_point) mvs = [] @@ -159,7 +164,8 @@ class MVFTS(fts.FTS): raise Exception('You must provide parameter \'generators\'! generators is a dict where the keys' + ' are the variables names (except the target_variable) and the values are ' + 'lambda functions that accept one value (the actual value of the variable) ' - ' and return the next value.') + ' and return the next value or trained FTS models that accept the actual values and ' + 'forecast new ones.') ndata = self.apply_transformations(data) @@ -174,13 +180,20 @@ class MVFTS(fts.FTS): ret.append(tmp) - last_data_point = sample.loc[sample.index[-1]] - new_data_point = {} for var in self.explanatory_variables: if var.name != self.target_variable.name: - new_data_point[var.data_label] = generators[var.name](last_data_point[var.data_label]) + if isinstance(generators[var.name], LambdaType): + last_data_point = ndata.loc[sample.index[-1]] + new_data_point[var.data_label] = generators[var.name](last_data_point[var.data_label]) + elif isinstance(generators[var.name], fts.FTS): + model = generators[var.name] + last_data_point = ndata.loc[[sample.index[-model.order]]] + if not model.is_multivariate: + last_data_point = last_data_point[var.data_label].values + + new_data_point[var.data_label] = model.forecast(last_data_point)[0] new_data_point[self.target_variable.data_label] = tmp diff --git a/pyFTS/models/multivariate/variable.py b/pyFTS/models/multivariate/variable.py index 17dcd4a..0c97958 100644 --- a/pyFTS/models/multivariate/variable.py +++ b/pyFTS/models/multivariate/variable.py @@ -30,9 +30,13 @@ class Variable: self.mask = kwargs.get('mask', None) """The mask for format the data column on Pandas Dataframe""" self.transformation = kwargs.get('transformation', None) + """Pre processing transformation for the variable""" self.transformation_params = kwargs.get('transformation_params', None) self.partitioner = None + """UoD partitioner for the variable data""" self.alpha_cut = kwargs.get('alpha_cut', 0.0) + """Minimal membership value to be considered on fuzzyfication process""" + if kwargs.get('data', None) is not None: self.build(**kwargs) diff --git a/pyFTS/tests/multivariate.py b/pyFTS/tests/multivariate.py index 3cfcc0b..5a53d52 100644 --- a/pyFTS/tests/multivariate.py +++ b/pyFTS/tests/multivariate.py @@ -128,30 +128,21 @@ vtemp = variable.Variable("Temperature", data_label="temperature", alias='temper from pyFTS.models.multivariate import mvfts, wmvfts, cmvfts, grid -vars = [vhour, vday, vload] +from pyFTS.models.multivariate import mvfts, wmvfts, cmvfts, grid -#fs = grid.GridCluster(explanatory_variables=vars, target_variable=vload) +mtemp = wmvfts.WeightedMVFTS(explanatory_variables=[vhour, vmonth, vtemp], target_variable=vtemp) +mtemp.fit(train_mv) -#model = mvfts.MVFTS(explanatory_variables=vars, target_variable=vload) -model = wmvfts.WeightedMVFTS(explanatory_variables=vars, target_variable=vload) -#model = cmvfts.ClusteredMVFTS(explanatory_variables=vars, target_variable=vload,order=2, knn=3, partitioner=fs) -model.fit(train_mv) -print(model.shortname) -Util.persist_obj(model, model.shortname) -#''' +from pyFTS.models.multivariate import mvfts, wmvfts, cmvfts, grid -#model = Util.load_obj('MVFTS') +mload = wmvfts.WeightedMVFTS(explanatory_variables=[vhour, vday, vtemp, vload], target_variable=vload) +mload.fit(train_mv) -with open("rules.txt","w") as file: - file.write(str(model)) -forecasts = model.predict(test_mv.iloc[:100]) -forecasts.insert(0,None) +time_generator = lambda x : pd.to_datetime(x) + pd.to_timedelta(1, unit='h') +temp_generator = mtemp -fig, ax = plt.subplots(nrows=1, ncols=1, figsize=[15,3]) -ax.plot(test_mv['load'].values[:100],label='Original') -ax.plot(forecasts, label='predicted') -handles, labels = ax.get_legend_handles_labels() -lgd = ax.legend(handles, labels, loc=2, bbox_to_anchor=(1, 1)) -Util.show_and_save_image(fig, model.shortname, True) +forecasts = mload.predict(test_mv.iloc[:1], steps_ahead=48, generators={'Hour': time_generator, + 'DayOfWeek': time_generator, + "Temperature": mtemp}) \ No newline at end of file