diff --git a/executables/bestest_hydronic_heat_pump/P_hp.py b/executables/bestest_hydronic_heat_pump/P_hp.py index 97bf7ec..161dbb7 100644 --- a/executables/bestest_hydronic_heat_pump/P_hp.py +++ b/executables/bestest_hydronic_heat_pump/P_hp.py @@ -1,45 +1,11 @@ -import os - -from physXAI.preprocessing.preprocessing import PreprocessingSingleStep -from physXAI.preprocessing.constructed import Feature from physXAI.models.models import LinearRegressionModel from physXAI.models.ann.ann_design import ClassicalANNModel, CMNNModel, LinANNModel -from physXAI.utils.logging import Logger - +from configuration import * """ Creates standard models to predict the power of the heat pump using the Boptest data. """ -# Setup up logger for saving -Logger.setup_logger(folder_name='P_hp', override=True) - -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - -# List of input features. Can include constructed features -inputs = ['oveHeaPumY_u', 'Func(logistic)', 'weaSta_reaWeaTDryBul_y', 'reaTZon_y'] -# Output feature -output = 'reaPHeaPum_y' - -""" -Example how to use constructed features. -The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' -The names of the constructed features should be added to the input list -""" -# x = Feature('weaSta_reaWeaTDryBul_y') # Create Feature for calculation -# x.lag(1) # Lags can be added directly based on the feature -# x.exp() -# y = Feature('reaTZon_y') -# z = x + y # Arithmetic operations can be performed on Features to create constructed Features -# z.rename('test') # Constructed features derive a name based on the arithmetic operation. -# It is recommended to rename features, so that they can be easily added to the input list - -# Create Training data -prep = PreprocessingSingleStep(inputs, output) -# Process Training data -td = prep.pipeline(file_path) - """Example usages of different models""" # m = LinearRegressionModel() # Linear Regression m = ClassicalANNModel(epochs=50) # Classical ANN @@ -52,14 +18,4 @@ # epochs=50) # Constrained Monotonic Neural Network (CMNN) # m = LinANNModel(epochs=50) # A hybrid model combining a Linear Regression model with an ANN (RBF) -# Training pipeline -model = m.pipeline(td) - -"""Example usage of online learning""" -m.epochs = 5 -model_ol = m.online_pipeline(td, os.path.join(Logger._logger, 'model.keras')) - -# Log setup of preprocessing and model as json -Logger.log_setup(prep, m) -# Log training data as pickle -Logger.save_training_data(td) +bestest_php.pipeline(m, online_epochs=5) diff --git a/executables/bestest_hydronic_heat_pump/P_hp_FeatureSelection.py b/executables/bestest_hydronic_heat_pump/P_hp_FeatureSelection.py index ab4b60e..da90ce0 100644 --- a/executables/bestest_hydronic_heat_pump/P_hp_FeatureSelection.py +++ b/executables/bestest_hydronic_heat_pump/P_hp_FeatureSelection.py @@ -1,42 +1,23 @@ from physXAI.feature_selection.recursive_feature_elimination import recursive_feature_elimination_pipeline from physXAI.models.models import LinearRegressionModel -from physXAI.preprocessing.constructed import Feature -from physXAI.preprocessing.preprocessing import PreprocessingSingleStep -from physXAI.utils.logging import Logger - +from configuration import * """ Feature selection for linear regression to predict the power of the heat pump using the Boptest data """ -# Setup up logger for saving -Logger.setup_logger(folder_name='P_hp_feature', override=True) - -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - -# List of all possible input features candidates. -inputs = ['oveHeaPumY_u', 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2', 'Func(logistic)', 'Func(logistic)_lag1', - 'Func(logistic)_lag2', 'weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaTDryBul_y_lag1', - 'weaSta_reaWeaTDryBul_y_lag2', 'reaTZon_y', 'reaTZon_y_lag1', 'reaTZon_y_lag2'] -# Output feature -output = 'reaPHeaPum_y' +# List of all possible input features candidates (overwrite default set in configuration.py) +bestest_php.inputs.extend(['oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2', 'Func(logistic)_lag1', 'Func(logistic)_lag2', + 'weaSta_reaWeaTDryBul_y_lag1', 'weaSta_reaWeaTDryBul_y_lag2', 'reaTZon_y_lag1', + 'reaTZon_y_lag2']) # Create lags -x1 = Feature('oveHeaPumY_u') -x1.lag(2) -x2 = Feature('Func(logistic)') -x2.lag(2) -x3 = Feature('weaSta_reaWeaTDryBul_y') -x3.lag(2) -x4 = Feature('reaTZon_y') -x4.lag(2) - -# Generic Preprocessing Pipeline -# Model is output model, so single step evaluation is choosen -prep = PreprocessingSingleStep(inputs, output) +u_hp.lag(2) +u_hp_logistic.lag(2) +t_amb.lag(2) +TAirRoom.lag(2) # Generic Model m = LinearRegressionModel() # Feature Selection -fs = recursive_feature_elimination_pipeline(file_path, prep, m, ascending_lag_order=True) +fs = bestest_php.recursive_feature_elimination_pipeline(m, ascending_lag_order=True) diff --git a/executables/bestest_hydronic_heat_pump/P_hp_pinn.py b/executables/bestest_hydronic_heat_pump/P_hp_pinn.py index 1e3ba2d..122cdf6 100644 --- a/executables/bestest_hydronic_heat_pump/P_hp_pinn.py +++ b/executables/bestest_hydronic_heat_pump/P_hp_pinn.py @@ -1,35 +1,17 @@ -from physXAI.preprocessing.preprocessing import PreprocessingSingleStep -from physXAI.preprocessing.constructed import Feature from physXAI.models.ann.ann_design import PINNModel -from physXAI.utils.logging import Logger +from configuration import * """ Creates a physics-informed model (PINN) to predict the power of the heat pump using the Boptest data """ -# Setup up logger for saving -Logger.setup_logger(folder_name='P_hp_pinn', override=True) -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - -# List of input features. Can include constructed features -inputs = ['oveHeaPumY_u', 'Func(logistic)', 'weaSta_reaWeaTDryBul_y', 'reaTZon_y'] """ Output feature(s). In addition to the standard data-driven loss, the PINN includes a physical loss function, which is created as a constructed feature """ -output = ['reaPHeaPum_y', 'pinn'] - -""" -The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' -The names of the constructed features should be added to the input list -""" -u_hp = Feature('oveHeaPumY_u') -u_hp_logistic = Feature('Func(logistic)') -t_amb = Feature('weaSta_reaWeaTDryBul_y') -TAirRoom = Feature('reaTZon_y') +bestest_php.outputs.append('pinn') """ Arithmetic operations can be performed on Features to create constructed Features @@ -38,11 +20,6 @@ pinn = (u_hp * 10000 * ((TAirRoom + 15 - t_amb) / ((TAirRoom + 15) * 0.55)) + (1110 + 500) * u_hp_logistic) pinn.rename('pinn') -# Create Training data -prep = PreprocessingSingleStep(inputs, output) -# Process Training data -td = prep.pipeline(file_path) - """ Create PINN model. pinn_weights are used to balance the individual loss therms of the PINN, their length should be `num_outputs - 1` @@ -50,10 +27,4 @@ """ m = PINNModel(pinn_weights=[1], epochs=50) -# Training pipeline -model = m.pipeline(td) - -# Log setup of preprocessing and model as json -Logger.log_setup(prep, m) -# Log training data as pickle -Logger.save_training_data(td) +bestest_php.pipeline(m) diff --git a/executables/bestest_hydronic_heat_pump/TAir.py b/executables/bestest_hydronic_heat_pump/TAir.py index 405d335..c61781e 100644 --- a/executables/bestest_hydronic_heat_pump/TAir.py +++ b/executables/bestest_hydronic_heat_pump/TAir.py @@ -1,39 +1,9 @@ -from physXAI.preprocessing.constructed import Feature from physXAI.models.ann.ann_design import CMNNModel -from physXAI.preprocessing.preprocessing import PreprocessingSingleStep -from physXAI.utils.logging import Logger - +from configuration import * """ Creates a constrained monotonic neural network to predict the air temperature using the Boptest data """ -# Setup up logger for saving -Logger.setup_logger(folder_name='TAir', override=True) - -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - -# List of input features. Can include constructed features and lagged inputs -inputs = ['reaTZon_y', 'reaTZon_y_lag1', 'reaTZon_y_lag2', 'weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaTDryBul_y_lag1', - 'weaSta_reaWeaHDirNor_y', 'oveHeaPumY_u', 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2'] -# Output feature -output = 'Change(T_zone)' - -""" -The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' -Lagged inputs can be added directly based on the feature -""" -x1 = Feature('reaTZon_y') -x1.lag(2) # reaTZon_y_lag1, reaTZon_y_lag2 -x2 = Feature('weaSta_reaWeaTDryBul_y') -x2.lag(1) # weaSta_reaWeaTDryBul_y_lag1 -x3 = Feature('oveHeaPumY_u') -x3.lag(2) # oveHeaPumY_u_lag1, oveHeaPumY_u_lag2 - -# Create Training data -prep = PreprocessingSingleStep(inputs, output) -# Process Training data -td = prep.pipeline(file_path) # Constrained Monotonic Neural Network (CMNN) m = CMNNModel(monotonies={ @@ -49,10 +19,4 @@ }, activation_split=[1, 1, 1], epochs=100) -# Training pipeline -model = m.pipeline(td) - -# Log setup of preprocessing and model as json -Logger.log_setup(prep, m) -# Log training data as pickle -Logger.save_training_data(td) +bestest_tair.pipeline(m) diff --git a/executables/bestest_hydronic_heat_pump/TAir_FeatureSelection.py b/executables/bestest_hydronic_heat_pump/TAir_FeatureSelection.py index bddc953..963e240 100644 --- a/executables/bestest_hydronic_heat_pump/TAir_FeatureSelection.py +++ b/executables/bestest_hydronic_heat_pump/TAir_FeatureSelection.py @@ -1,44 +1,34 @@ -from physXAI.feature_selection.recursive_feature_elimination import recursive_feature_elimination_pipeline from physXAI.models.models import LinearRegressionModel -from physXAI.preprocessing.constructed import Feature from physXAI.preprocessing.preprocessing import PreprocessingMultiStep -from physXAI.utils.logging import Logger +from configuration import * """ Feature selection for linear regression to predict the air temperature using the Boptest data """ -# Setup up logger for saving -Logger.setup_logger(folder_name='TAir_feature', override=True) -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - -# List of all possible input features candidates. -inputs = ['reaTZon_y', 'reaTZon_y_lag1', 'reaTZon_y_lag2', 'weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaTDryBul_y_lag1', - 'weaSta_reaWeaTDryBul_y_lag2', 'weaSta_reaWeaHDirNor_y', 'weaSta_reaWeaHDirNor_y_lag1', - 'weaSta_reaWeaHDirNor_y_lag2', 'oveHeaPumY_u', 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2'] -# Output feature -output = 'Change(T_zone)' +# List of all possible input features candidates (overwrite default set in configuration.py) +bestest_tair.inputs = ['reaTZon_y', 'reaTZon_y_lag1', 'reaTZon_y_lag2', 'weaSta_reaWeaTDryBul_y', + 'weaSta_reaWeaTDryBul_y_lag1', 'weaSta_reaWeaTDryBul_y_lag2', 'weaSta_reaWeaHDirNor_y', + 'weaSta_reaWeaHDirNor_y_lag1', 'weaSta_reaWeaHDirNor_y_lag2', 'oveHeaPumY_u', + 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2'] # Create lags -x1 = Feature('reaTZon_y') -x1.lag(2) -x2 = Feature('weaSta_reaWeaTDryBul_y') -x2.lag(2) -x3 = Feature('weaSta_reaWeaHDirNor_y') -x3.lag(2) -x4 = Feature('oveHeaPumY_u') -x4.lag(2) +TAirRoom.lag(2) +t_amb.lag(2) +q_sol = Feature('weaSta_reaWeaHDirNor_y') +q_sol.lag(2) +u_hp.lag(2) # Generic Preprocessing Pipeline # Model is state model, so multi-step evaluation is choosen # See example TAir_evaluateMultiStep.py for more information -prep = PreprocessingMultiStep(inputs, output, 48, 0, init_features=['reaTZon_y'], - overlapping_sequences=False, batch_size=1) +bestest_tair.warmup_width = 0 # overwrite default set in configuration.py +prep = bestest_tair.get_preprocessing_multi_step(init_features=['reaTZon_y'], overlapping_sequences=False, batch_size=1) # Generic Model m = LinearRegressionModel() # Feature Selection -fs = recursive_feature_elimination_pipeline(file_path, prep, m, use_multi_step_error=True, ascending_lag_order=True) +fs = bestest_tair.recursive_feature_elimination_pipeline(m, prep=prep, use_multi_step_error=True, + ascending_lag_order=True) diff --git a/executables/bestest_hydronic_heat_pump/TAir_evaluateMultiStep.py b/executables/bestest_hydronic_heat_pump/TAir_evaluateMultiStep.py index 5c5a1bc..9bd8f49 100644 --- a/executables/bestest_hydronic_heat_pump/TAir_evaluateMultiStep.py +++ b/executables/bestest_hydronic_heat_pump/TAir_evaluateMultiStep.py @@ -1,36 +1,12 @@ from physXAI.models.models import LinearRegressionModel -from physXAI.preprocessing.constructed import Feature -from physXAI.models.ann.ann_design import ClassicalANNModel from physXAI.preprocessing.preprocessing import PreprocessingMultiStep -from physXAI.utils.logging import Logger - +from configuration import * """ Creates a linear regression to predict the air temperature using the Boptest data The model is trained as a single step model, but evaluated as a multi step model """ -# Setup up logger for saving -Logger.setup_logger(folder_name='TAir', override=True) - -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" -# List of input features. Can include constructed features and lagged inputs -inputs = ['reaTZon_y', 'reaTZon_y_lag1', 'reaTZon_y_lag2', 'weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaTDryBul_y_lag1', - 'weaSta_reaWeaHDirNor_y', 'oveHeaPumY_u', 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2'] -# Output feature -output = 'Change(T_zone)' - -""" -The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' -Lagged inputs can be added directly based on the feature -""" -x1 = Feature('reaTZon_y') -x1.lag(2) # reaTZon_y_lag1, reaTZon_y_lag2 -x2 = Feature('weaSta_reaWeaTDryBul_y') -x2.lag(1) # weaSta_reaWeaTDryBul_y_lag1 -x3 = Feature('oveHeaPumY_u') -x3.lag(2) # oveHeaPumY_u_lag1, oveHeaPumY_u_lag2 # Create Training data """ @@ -42,18 +18,10 @@ overlapping_sequence should be False to avoid duplicate labels for single step prediction batch_size should be 1 as batches are processes differently in single step models """ -prep = PreprocessingMultiStep(inputs, output, 48, 0, init_features=['reaTZon_y'], - overlapping_sequences=False, batch_size=1) -# Process Training data -td = prep.pipeline(file_path) +bestest_tair.warmup_width = 0 # overwrite default set in configuration.py +prep = bestest_tair.get_preprocessing_multi_step(init_features=['reaTZon_y'], overlapping_sequences=False, batch_size=1) # Linear Regression m = LinearRegressionModel() -# Training pipeline -model = m.pipeline(td) - -# Log setup of preprocessing and model as json -Logger.log_setup(prep, m) -# Log training data as pickle -Logger.save_training_data(td) +bestest_tair.pipeline(m, prep) diff --git a/executables/bestest_hydronic_heat_pump/TAir_rnn.py b/executables/bestest_hydronic_heat_pump/TAir_rnn.py index 0a74b3b..1e66e0e 100644 --- a/executables/bestest_hydronic_heat_pump/TAir_rnn.py +++ b/executables/bestest_hydronic_heat_pump/TAir_rnn.py @@ -1,17 +1,9 @@ from physXAI.models.ann.ann_design import RNNModel -from physXAI.preprocessing.preprocessing import PreprocessingMultiStep -from physXAI.utils.logging import Logger - +from configuration import * """ Creates a recurrent neural network (RNN) to predict the air temperature using the Boptest data """ -# Setup up logger for saving -Logger.setup_logger(folder_name='TAir_rnn', override=True) - -# File path to data -file_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" - """ List of input features. Can include constructed features and lagged inputs. @@ -19,27 +11,10 @@ RNNs need to be initialized. Therefore a initialization model is trained based on the 'inits' features. The RNN directly predicts the air temperature instead of the air temperature change. """ -inputs = ['weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaHDirNor_y', 'oveHeaPumY_u'] -inits = ['reaTZon_y'] -output = 'reaTZon_y' - -# Number of time steps in the output (label) sequence. -label_width = 48 -# Number of time steps in the warmup sequence (for RNN state initialization). -warmup_width = 48 - -# Create Training data. For RNNs MultiStep training data is required -prep = PreprocessingMultiStep(inputs, output, label_width, warmup_width, init_features=inits) -# Process Training data -td = prep.pipeline(file_path) +bestest_tair.inputs = ['weaSta_reaWeaTDryBul_y', 'weaSta_reaWeaHDirNor_y', 'oveHeaPumY_u'] +bestest_tair.output = 'reaTZon_y' # Create RNN model. Models needs a rnn type for the output (rnn_layer) and the initialization (init_layer) model m = RNNModel(epochs=100, rnn_layer='LSTM', init_layer='LSTM') -# Training pipeline -model = m.pipeline(td) - -# Log setup of preprocessing and model as json -Logger.log_setup(prep, m) -# Log training data as pickle -Logger.save_training_data(td) +bestest_tair.pipeline(m) diff --git a/executables/bestest_hydronic_heat_pump/configuration.py b/executables/bestest_hydronic_heat_pump/configuration.py new file mode 100644 index 0000000..b2944f2 --- /dev/null +++ b/executables/bestest_hydronic_heat_pump/configuration.py @@ -0,0 +1,56 @@ +from physXAI.preprocessing.constructed import Feature +from physXAI.utils.test_case import TestCase + +# TODO: add Docstring + +# File path to data +data_path = r"data/bestest_hydronic_heat_pump/pid_data.csv" + +""" +Example how to use constructed features. +The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' +The names of the constructed features should be added to the input list +""" +# x = Feature('weaSta_reaWeaTDryBul_y') # Create Feature for calculation +# x.lag(1) # Lags can be added directly based on the feature +# x.exp() +# y = Feature('reaTZon_y') +# z = x + y # Arithmetic operations can be performed on Features to create constructed Features +# z.rename('test') # Constructed features derive a name based on the arithmetic operation. +# It is recommended to rename features, so that they can be easily added to the input list + +"""heat pump power prediction""" +# List of input features. Can include constructed features +u_hp = Feature('oveHeaPumY_u') +u_hp_logistic = Feature('Func(logistic)') +t_amb = Feature('weaSta_reaWeaTDryBul_y') +TAirRoom = Feature('reaTZon_y') +inputs_php = [u_hp, u_hp_logistic, t_amb, TAirRoom] + +# Output feature +output_php = ['reaPHeaPum_y'] + +# define test case +bestest_php = TestCase(inputs_php, output_php, data_path) + + +"""room temperature prediciton""" +# The constructed features are automatically added to the data via 'physXAI.preprocessing.constructed.py' +# Lagged inputs can be added directly based on the feature +TAirRoom.lag(2) # reaTZon_y_lag1, reaTZon_y_lag2 +t_amb.lag(1) # weaSta_reaWeaTDryBul_y_lag1 +u_hp.lag(2) # oveHeaPumY_u_lag1, oveHeaPumY_u_lag2 + +# List of input features. Can include constructed features and lagged inputs +inputs_tair = [TAirRoom, 'reaTZon_y_lag1', 'reaTZon_y_lag2', t_amb, 'weaSta_reaWeaTDryBul_y_lag1', + 'weaSta_reaWeaHDirNor_y', u_hp, 'oveHeaPumY_u_lag1', 'oveHeaPumY_u_lag2'] + +# Output feature +output_tair = 'Change(T_zone)' + +# Define test case, including parameter for multistep models +# Number of time steps in the output (label) sequence. +label_width = 48 +# Number of time steps in the warmup sequence (for RNN state initialization). +warmup_width = 48 +bestest_tair = TestCase(inputs_tair, output_tair, data_path, label_width=label_width, warmup_width=warmup_width) diff --git a/physXAI/utils/test_case.py b/physXAI/utils/test_case.py new file mode 100644 index 0000000..e996166 --- /dev/null +++ b/physXAI/utils/test_case.py @@ -0,0 +1,75 @@ +import os +from typing import Union +import inspect +from physXAI.feature_selection.recursive_feature_elimination import recursive_feature_elimination_pipeline +from physXAI.preprocessing.constructed import FeatureBase +from physXAI.preprocessing.preprocessing import PreprocessingSingleStep, PreprocessingMultiStep, PreprocessingData +from physXAI.models.models import AbstractModel, SingleStepModel, MultiStepModel +from physXAI.utils.logging import Logger + + +class TestCase: + + def __init__(self, inputs: list[Union[str, FeatureBase]], output: Union[str, list[Union[str, FeatureBase]]], + data_path: str, label_width: int = None, warmup_width: int = None): + # TODO: add docstrings + # label_width, warmup_width required if multistep should be used + self.inputs = inputs + self.output = output + self.data_path = data_path + + # only relevant for MultiStepModels + self.label_width = label_width + self.warmup_width = warmup_width + + def get_preprocessing_single_step(self, **kwargs) -> PreprocessingSingleStep: + return PreprocessingSingleStep(self.inputs, self.output, **kwargs) + + def get_preprocessing_multi_step(self, **kwargs) -> PreprocessingMultiStep: + assert self.label_width is not None, 'label_width is required for MultiStepModel' + assert self.warmup_width is not None, 'warmup_width is required for MultiStepModel' + + return PreprocessingMultiStep(self.inputs, self.output, self.label_width, self.warmup_width, **kwargs) + + def pipeline(self, m: AbstractModel, prep: PreprocessingData = None, plot: bool = True, save_model: bool = True, + online_epochs: int = -1): + + # Get the filename of executable file + caller_frame = inspect.currentframe().f_back + caller_filename = caller_frame.f_globals["__file__"] + caller_filename = os.path.splitext(os.path.basename(caller_filename))[0] + + # Setup up logger for saving + Logger.setup_logger(folder_name=caller_filename, override=True) + + # Create Training data + if prep is None: + if isinstance(m, SingleStepModel): + prep = self.get_preprocessing_single_step() + elif isinstance(m, MultiStepModel): + prep = self.get_preprocessing_multi_step() + else: + raise TypeError(f'unrecognized model type: {type(m)}') + + # Process Training data + td = prep.pipeline(self.data_path) + + # Training pipeline + model = m.pipeline(td, plot=plot, save_model=save_model) + + if online_epochs > 0: + assert save_model, 'save_model must be True if online learning is used' + m.epochs = online_epochs + model_ol = m.online_pipeline(td, load_path=os.path.join(Logger._logger, 'model.keras'), plot=plot) + + # Log setup of preprocessing and model as json + Logger.log_setup(prep, m) + # Log training data as pickle + Logger.save_training_data(td) + + def recursive_feature_elimination_pipeline(self, m: SingleStepModel, prep: PreprocessingData = None, **kwargs): + # Create Training data + if prep is None: + prep = self.get_preprocessing_single_step() + + return recursive_feature_elimination_pipeline(self.data_path, prep, m, **kwargs)