emhass 0.11.2__py3-none-any.whl → 0.11.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,13 +13,14 @@ from sklearn.linear_model import ElasticNet
13
13
  from sklearn.neighbors import KNeighborsRegressor
14
14
  from sklearn.metrics import r2_score
15
15
 
16
- from skforecast.ForecasterAutoreg import ForecasterAutoreg
17
- from skforecast.model_selection import bayesian_search_forecaster
18
- from skforecast.model_selection import backtesting_forecaster
16
+ from skforecast.recursive import ForecasterRecursive
17
+ from skforecast.model_selection import bayesian_search_forecaster, backtesting_forecaster, TimeSeriesFold
19
18
 
20
19
  import warnings
20
+
21
21
  warnings.filterwarnings("ignore", category=DeprecationWarning)
22
22
 
23
+
23
24
  class MLForecaster:
24
25
  r"""
25
26
  A forecaster class using machine learning models with auto-regressive approach and features\
@@ -37,8 +38,16 @@ class MLForecaster:
37
38
 
38
39
  """
39
40
 
40
- def __init__(self, data: pd.DataFrame, model_type: str, var_model: str, sklearn_model: str,
41
- num_lags: int, emhass_conf: dict, logger: logging.Logger) -> None:
41
+ def __init__(
42
+ self,
43
+ data: pd.DataFrame,
44
+ model_type: str,
45
+ var_model: str,
46
+ sklearn_model: str,
47
+ num_lags: int,
48
+ emhass_conf: dict,
49
+ logger: logging.Logger,
50
+ ) -> None:
42
51
  r"""Define constructor for the forecast class.
43
52
 
44
53
  :param data: The data that will be used for train/test
@@ -72,8 +81,8 @@ class MLForecaster:
72
81
  # A quick data preparation
73
82
  self.data.index = pd.to_datetime(self.data.index)
74
83
  self.data.sort_index(inplace=True)
75
- self.data = self.data[~self.data.index.duplicated(keep='first')]
76
-
84
+ self.data = self.data[~self.data.index.duplicated(keep="first")]
85
+
77
86
  @staticmethod
78
87
  def add_date_features(data: pd.DataFrame) -> pd.DataFrame:
79
88
  """Add date features from the input DataFrame timestamp
@@ -84,32 +93,36 @@ class MLForecaster:
84
93
  :rtype: pd.DataFrame
85
94
  """
86
95
  df = copy.deepcopy(data)
87
- df['year'] = [i.year for i in df.index]
88
- df['month'] = [i.month for i in df.index]
89
- df['day_of_week'] = [i.dayofweek for i in df.index]
90
- df['day_of_year'] = [i.dayofyear for i in df.index]
91
- df['day'] = [i.day for i in df.index]
92
- df['hour'] = [i.hour for i in df.index]
96
+ df["year"] = [i.year for i in df.index]
97
+ df["month"] = [i.month for i in df.index]
98
+ df["day_of_week"] = [i.dayofweek for i in df.index]
99
+ df["day_of_year"] = [i.dayofyear for i in df.index]
100
+ df["day"] = [i.day for i in df.index]
101
+ df["hour"] = [i.hour for i in df.index]
93
102
  return df
94
103
 
95
104
  @staticmethod
96
105
  def neg_r2_score(y_true, y_pred):
97
106
  """The negative of the r2 score."""
98
107
  return -r2_score(y_true, y_pred)
99
-
108
+
100
109
  @staticmethod
101
110
  def generate_exog(data_last_window, periods, var_name):
102
111
  """Generate the exogenous data for future timestamps."""
103
- forecast_dates = pd.date_range(start=data_last_window.index[-1]+data_last_window.index.freq,
104
- periods=periods,
105
- freq=data_last_window.index.freq)
106
- exog = pd.DataFrame({var_name:[np.nan]*periods},
107
- index=forecast_dates)
112
+ forecast_dates = pd.date_range(
113
+ start=data_last_window.index[-1] + data_last_window.index.freq,
114
+ periods=periods,
115
+ freq=data_last_window.index.freq,
116
+ )
117
+ exog = pd.DataFrame({var_name: [np.nan] * periods}, index=forecast_dates)
108
118
  exog = MLForecaster.add_date_features(exog)
109
119
  return exog
110
-
111
- def fit(self, split_date_delta: Optional[str] = '48h', perform_backtest: Optional[bool] = False
112
- ) -> Tuple[pd.DataFrame, pd.DataFrame]:
120
+
121
+ def fit(
122
+ self,
123
+ split_date_delta: Optional[str] = "48h",
124
+ perform_backtest: Optional[bool] = False,
125
+ ) -> Tuple[pd.DataFrame, pd.DataFrame]:
113
126
  r"""The fit method to train the ML model.
114
127
 
115
128
  :param split_date_delta: The delta from now to `split_date_delta` that will be used \
@@ -121,73 +134,100 @@ class MLForecaster:
121
134
  :return: The DataFrame containing the forecast data results without and with backtest
122
135
  :rtype: Tuple[pd.DataFrame, pd.DataFrame]
123
136
  """
124
- self.logger.info("Performing a forecast model fit for "+self.model_type)
137
+ self.logger.info("Performing a forecast model fit for " + self.model_type)
125
138
  # Preparing the data: adding exogenous features
126
139
  self.data_exo = pd.DataFrame(index=self.data.index)
127
140
  self.data_exo = MLForecaster.add_date_features(self.data_exo)
128
141
  self.data_exo[self.var_model] = self.data[self.var_model]
129
- self.data_exo = self.data_exo.interpolate(method='linear', axis=0, limit=None)
142
+ self.data_exo = self.data_exo.interpolate(method="linear", axis=0, limit=None)
130
143
  # train/test split
131
- self.date_train = self.data_exo.index[-1]-pd.Timedelta('5days')+self.data_exo.index.freq # The last 5 days
132
- self.date_split = self.data_exo.index[-1]-pd.Timedelta(split_date_delta)+self.data_exo.index.freq # The last 48h
133
- self.data_train = self.data_exo.loc[:self.date_split-self.data_exo.index.freq,:]
134
- self.data_test = self.data_exo.loc[self.date_split:,:]
144
+ self.date_train = (
145
+ self.data_exo.index[-1] - pd.Timedelta("5days") + self.data_exo.index.freq
146
+ ) # The last 5 days
147
+ self.date_split = (
148
+ self.data_exo.index[-1]
149
+ - pd.Timedelta(split_date_delta)
150
+ + self.data_exo.index.freq
151
+ ) # The last 48h
152
+ self.data_train = self.data_exo.loc[
153
+ : self.date_split - self.data_exo.index.freq, :
154
+ ]
155
+ self.data_test = self.data_exo.loc[self.date_split :, :]
135
156
  self.steps = len(self.data_test)
136
157
  # Pick correct sklearn model
137
- if self.sklearn_model == 'LinearRegression':
158
+ if self.sklearn_model == "LinearRegression":
138
159
  base_model = LinearRegression()
139
- elif self.sklearn_model == 'ElasticNet':
160
+ elif self.sklearn_model == "ElasticNet":
140
161
  base_model = ElasticNet()
141
- elif self.sklearn_model == 'KNeighborsRegressor':
162
+ elif self.sklearn_model == "KNeighborsRegressor":
142
163
  base_model = KNeighborsRegressor()
143
164
  else:
144
- self.logger.error("Passed sklearn model "+self.sklearn_model+" is not valid. Defaulting to KNeighborsRegressor")
165
+ self.logger.error(
166
+ "Passed sklearn model "
167
+ + self.sklearn_model
168
+ + " is not valid. Defaulting to KNeighborsRegressor"
169
+ )
145
170
  base_model = KNeighborsRegressor()
146
171
  # Define the forecaster object
147
- self.forecaster = ForecasterAutoreg(
172
+ self.forecaster = ForecasterRecursive(
148
173
  regressor = base_model,
149
174
  lags = self.num_lags
150
175
  )
151
176
  # Fit and time it
152
- self.logger.info("Training a "+self.sklearn_model+" model")
177
+ self.logger.info("Training a " + self.sklearn_model + " model")
153
178
  start_time = time.time()
154
- self.forecaster.fit(y=self.data_train[self.var_model],
155
- exog=self.data_train.drop(self.var_model, axis=1))
179
+ self.forecaster.fit(
180
+ y=self.data_train[self.var_model],
181
+ exog=self.data_train.drop(self.var_model, axis=1),
182
+ )
156
183
  self.logger.info(f"Elapsed time for model fit: {time.time() - start_time}")
157
184
  # Make a prediction to print metrics
158
- predictions = self.forecaster.predict(steps=self.steps, exog=self.data_test.drop(self.var_model, axis=1))
159
- pred_metric = r2_score(self.data_test[self.var_model],predictions)
160
- self.logger.info(f"Prediction R2 score of fitted model on test data: {pred_metric}")
185
+ predictions = self.forecaster.predict(
186
+ steps=self.steps, exog=self.data_test.drop(self.var_model, axis=1)
187
+ )
188
+ pred_metric = r2_score(self.data_test[self.var_model], predictions)
189
+ self.logger.info(
190
+ f"Prediction R2 score of fitted model on test data: {pred_metric}"
191
+ )
161
192
  # Packing results in a DataFrame
162
- df_pred = pd.DataFrame(index=self.data_exo.index,columns=['train','test','pred'])
163
- df_pred['train'] = self.data_train[self.var_model]
164
- df_pred['test'] = self.data_test[self.var_model]
165
- df_pred['pred'] = predictions
193
+ df_pred = pd.DataFrame(
194
+ index=self.data_exo.index, columns=["train", "test", "pred"]
195
+ )
196
+ df_pred["train"] = self.data_train[self.var_model]
197
+ df_pred["test"] = self.data_test[self.var_model]
198
+ df_pred["pred"] = predictions
166
199
  df_pred_backtest = None
167
200
  if perform_backtest is True:
168
201
  # Using backtesting tool to evaluate the model
169
202
  self.logger.info("Performing simple backtesting of fitted model")
170
203
  start_time = time.time()
204
+ cv = TimeSeriesFold(
205
+ steps = self.num_lags,
206
+ initial_train_size = None,
207
+ fixed_train_size = False,
208
+ gap = 0,
209
+ allow_incomplete_fold = True,
210
+ refit = False
211
+ )
171
212
  metric, predictions_backtest = backtesting_forecaster(
172
213
  forecaster = self.forecaster,
173
214
  y = self.data_train[self.var_model],
174
215
  exog = self.data_train.drop(self.var_model, axis=1),
175
- initial_train_size = None,
176
- fixed_train_size = False,
177
- steps = self.num_lags,
216
+ cv = cv,
178
217
  metric = MLForecaster.neg_r2_score,
179
- refit = False,
180
- verbose = False
218
+ verbose = False,
219
+ show_progress = True
181
220
  )
182
221
  self.logger.info(f"Elapsed backtesting time: {time.time() - start_time}")
183
222
  self.logger.info(f"Backtest R2 score: {-metric}")
184
- df_pred_backtest = pd.DataFrame(index=self.data_exo.index,columns=['train','pred'])
185
- df_pred_backtest['train'] = self.data_exo[self.var_model]
186
- df_pred_backtest['pred'] = predictions_backtest
223
+ df_pred_backtest = pd.DataFrame(
224
+ index=self.data_exo.index, columns=["train", "pred"]
225
+ )
226
+ df_pred_backtest["train"] = self.data_exo[self.var_model]
227
+ df_pred_backtest["pred"] = predictions_backtest
187
228
  return df_pred, df_pred_backtest
188
-
189
- def predict(self, data_last_window: Optional[pd.DataFrame] = None
190
- ) -> pd.Series:
229
+
230
+ def predict(self, data_last_window: Optional[pd.DataFrame] = None) -> pd.Series:
191
231
  """The predict method to generate forecasts from a previously fitted ML model.
192
232
 
193
233
  :param data_last_window: The data that will be used to generate the new forecast, this \
@@ -199,21 +239,33 @@ class MLForecaster:
199
239
  :rtype: pd.Series
200
240
  """
201
241
  if data_last_window is None:
202
- predictions = self.forecaster.predict(steps=self.num_lags, exog=self.data_test.drop(self.var_model, axis=1))
242
+ predictions = self.forecaster.predict(
243
+ steps=self.num_lags, exog=self.data_test.drop(self.var_model, axis=1)
244
+ )
203
245
  else:
204
- data_last_window = data_last_window.interpolate(method='linear', axis=0, limit=None)
246
+ data_last_window = data_last_window.interpolate(
247
+ method="linear", axis=0, limit=None
248
+ )
205
249
  if self.is_tuned:
206
- exog = MLForecaster.generate_exog(data_last_window, self.lags_opt, self.var_model)
207
- predictions = self.forecaster.predict(steps=self.lags_opt,
208
- last_window=data_last_window[self.var_model],
209
- exog=exog.drop(self.var_model, axis=1))
250
+ exog = MLForecaster.generate_exog(
251
+ data_last_window, self.lags_opt, self.var_model
252
+ )
253
+ predictions = self.forecaster.predict(
254
+ steps=self.lags_opt,
255
+ last_window=data_last_window[self.var_model],
256
+ exog=exog.drop(self.var_model, axis=1),
257
+ )
210
258
  else:
211
- exog = MLForecaster.generate_exog(data_last_window, self.num_lags, self.var_model)
212
- predictions = self.forecaster.predict(steps=self.num_lags,
213
- last_window=data_last_window[self.var_model],
214
- exog=exog.drop(self.var_model, axis=1))
259
+ exog = MLForecaster.generate_exog(
260
+ data_last_window, self.num_lags, self.var_model
261
+ )
262
+ predictions = self.forecaster.predict(
263
+ steps=self.num_lags,
264
+ last_window=data_last_window[self.var_model],
265
+ exog=exog.drop(self.var_model, axis=1),
266
+ )
215
267
  return predictions
216
-
268
+
217
269
  def tune(self, debug: Optional[bool] = False) -> pd.DataFrame:
218
270
  """Tuning a previously fitted model using bayesian optimization.
219
271
 
@@ -223,43 +275,76 @@ class MLForecaster:
223
275
  :rtype: pd.DataFrame
224
276
  """
225
277
  # Regressor hyperparameters search space
226
- if self.sklearn_model == 'LinearRegression':
278
+ if self.sklearn_model == "LinearRegression":
227
279
  if debug:
280
+
228
281
  def search_space(trial):
229
- search_space = {'fit_intercept': trial.suggest_categorical('fit_intercept', [True]),
230
- 'lags': trial.suggest_categorical('lags', [3])}
282
+ search_space = {
283
+ "fit_intercept": trial.suggest_categorical(
284
+ "fit_intercept", [True]
285
+ ),
286
+ "lags": trial.suggest_categorical("lags", [3]),
287
+ }
231
288
  return search_space
232
289
  else:
290
+
233
291
  def search_space(trial):
234
- search_space = {'fit_intercept': trial.suggest_categorical('fit_intercept', [True, False]),
235
- 'lags': trial.suggest_categorical('lags', [6, 12, 24, 36, 48, 60, 72])}
292
+ search_space = {
293
+ "fit_intercept": trial.suggest_categorical(
294
+ "fit_intercept", [True, False]
295
+ ),
296
+ "lags": trial.suggest_categorical(
297
+ "lags", [6, 12, 24, 36, 48, 60, 72]
298
+ ),
299
+ }
236
300
  return search_space
237
- elif self.sklearn_model == 'ElasticNet':
301
+ elif self.sklearn_model == "ElasticNet":
238
302
  if debug:
303
+
239
304
  def search_space(trial):
240
- search_space = {'selection': trial.suggest_categorical('selection', ['random']),
241
- 'lags': trial.suggest_categorical('lags', [3])}
305
+ search_space = {
306
+ "selection": trial.suggest_categorical("selection", ["random"]),
307
+ "lags": trial.suggest_categorical("lags", [3]),
308
+ }
242
309
  return search_space
243
310
  else:
311
+
244
312
  def search_space(trial):
245
- search_space = {'alpha': trial.suggest_float('alpha', 0.0, 2.0),
246
- 'l1_ratio': trial.suggest_float('l1_ratio', 0.0, 1.0),
247
- 'selection': trial.suggest_categorical('selection', ['cyclic', 'random']),
248
- 'lags': trial.suggest_categorical('lags', [6, 12, 24, 36, 48, 60, 72])}
313
+ search_space = {
314
+ "alpha": trial.suggest_float("alpha", 0.0, 2.0),
315
+ "l1_ratio": trial.suggest_float("l1_ratio", 0.0, 1.0),
316
+ "selection": trial.suggest_categorical(
317
+ "selection", ["cyclic", "random"]
318
+ ),
319
+ "lags": trial.suggest_categorical(
320
+ "lags", [6, 12, 24, 36, 48, 60, 72]
321
+ ),
322
+ }
249
323
  return search_space
250
- elif self.sklearn_model == 'KNeighborsRegressor':
324
+ elif self.sklearn_model == "KNeighborsRegressor":
251
325
  if debug:
326
+
252
327
  def search_space(trial):
253
- search_space = {'weights': trial.suggest_categorical('weights', ['uniform']),
254
- 'lags': trial.suggest_categorical('lags', [3])}
328
+ search_space = {
329
+ "weights": trial.suggest_categorical("weights", ["uniform"]),
330
+ "lags": trial.suggest_categorical("lags", [3]),
331
+ }
255
332
  return search_space
256
333
  else:
334
+
257
335
  def search_space(trial):
258
- search_space = {'n_neighbors': trial.suggest_int('n_neighbors', 2, 20),
259
- 'leaf_size': trial.suggest_int('leaf_size', 20, 40),
260
- 'weights': trial.suggest_categorical('weights', ['uniform', 'distance']),
261
- 'lags': trial.suggest_categorical('lags', [6, 12, 24, 36, 48, 60, 72])}
336
+ search_space = {
337
+ "n_neighbors": trial.suggest_int("n_neighbors", 2, 20),
338
+ "leaf_size": trial.suggest_int("leaf_size", 20, 40),
339
+ "weights": trial.suggest_categorical(
340
+ "weights", ["uniform", "distance"]
341
+ ),
342
+ "lags": trial.suggest_categorical(
343
+ "lags", [6, 12, 24, 36, 48, 60, 72]
344
+ ),
345
+ }
262
346
  return search_space
347
+
263
348
  # Bayesian search hyperparameter and lags with skforecast/optuna
264
349
  # Lags used as predictors
265
350
  if debug:
@@ -271,36 +356,50 @@ class MLForecaster:
271
356
  # The optimization routine call
272
357
  self.logger.info("Bayesian hyperparameter optimization with backtesting")
273
358
  start_time = time.time()
359
+ cv = TimeSeriesFold(
360
+ steps = num_lags,
361
+ initial_train_size = len(self.data_exo.loc[:self.date_train]),
362
+ fixed_train_size = True,
363
+ gap = 0,
364
+ skip_folds = None,
365
+ allow_incomplete_fold = True,
366
+ refit = refit
367
+ )
274
368
  self.optimize_results, self.optimize_results_object = bayesian_search_forecaster(
275
369
  forecaster = self.forecaster,
276
370
  y = self.data_train[self.var_model],
277
371
  exog = self.data_train.drop(self.var_model, axis=1),
372
+ cv = cv,
278
373
  search_space = search_space,
279
- steps = num_lags,
280
374
  metric = MLForecaster.neg_r2_score,
281
- refit = refit,
282
- initial_train_size = len(self.data_exo.loc[:self.date_train]),
283
- fixed_train_size = True,
284
375
  n_trials = 10,
285
376
  random_state = 123,
286
- return_best = True,
287
- verbose = False,
288
- engine = 'optuna'
377
+ return_best = True
289
378
  )
290
379
  self.logger.info(f"Elapsed time: {time.time() - start_time}")
291
380
  self.is_tuned = True
292
- predictions_opt = self.forecaster.predict(steps=self.num_lags, exog=self.data_test.drop(self.var_model, axis=1))
293
- freq_hours = self.data_exo.index.freq.delta.seconds/3600
294
- self.lags_opt = int(np.round(len(self.optimize_results.iloc[0]['lags'])))
295
- self.days_needed = int(np.round(self.lags_opt*freq_hours/24))
296
- df_pred_opt = pd.DataFrame(index=self.data_exo.index,columns=['train','test','pred_optim'])
297
- df_pred_opt['train'] = self.data_train[self.var_model]
298
- df_pred_opt['test'] = self.data_test[self.var_model]
299
- df_pred_opt['pred_optim'] = predictions_opt
300
- pred_optim_metric_train = -self.optimize_results.iloc[0]['neg_r2_score']
301
- self.logger.info(f"R2 score for optimized prediction in train period: {pred_optim_metric_train}")
302
- pred_optim_metric_test = r2_score(df_pred_opt.loc[predictions_opt.index,'test'],
303
- df_pred_opt.loc[predictions_opt.index,'pred_optim'])
304
- self.logger.info(f"R2 score for optimized prediction in test period: {pred_optim_metric_test}")
305
- self.logger.info("Number of optimal lags obtained: "+str(self.lags_opt))
381
+ predictions_opt = self.forecaster.predict(
382
+ steps=self.num_lags, exog=self.data_test.drop(self.var_model, axis=1)
383
+ )
384
+ freq_hours = self.data_exo.index.freq.delta.seconds / 3600
385
+ self.lags_opt = int(np.round(len(self.optimize_results.iloc[0]["lags"])))
386
+ self.days_needed = int(np.round(self.lags_opt * freq_hours / 24))
387
+ df_pred_opt = pd.DataFrame(
388
+ index=self.data_exo.index, columns=["train", "test", "pred_optim"]
389
+ )
390
+ df_pred_opt["train"] = self.data_train[self.var_model]
391
+ df_pred_opt["test"] = self.data_test[self.var_model]
392
+ df_pred_opt["pred_optim"] = predictions_opt
393
+ pred_optim_metric_train = -self.optimize_results.iloc[0]["neg_r2_score"]
394
+ self.logger.info(
395
+ f"R2 score for optimized prediction in train period: {pred_optim_metric_train}"
396
+ )
397
+ pred_optim_metric_test = r2_score(
398
+ df_pred_opt.loc[predictions_opt.index, "test"],
399
+ df_pred_opt.loc[predictions_opt.index, "pred_optim"],
400
+ )
401
+ self.logger.info(
402
+ f"R2 score for optimized prediction in test period: {pred_optim_metric_test}"
403
+ )
404
+ self.logger.info("Number of optimal lags obtained: " + str(self.lags_opt))
306
405
  return df_pred_opt
@@ -76,8 +76,16 @@ class MLRegressor:
76
76
 
77
77
  """
78
78
 
79
- def __init__(self: MLRegressor, data: pd.DataFrame, model_type: str, regression_model: str,
80
- features: list, target: str, timestamp: str, logger: logging.Logger) -> None:
79
+ def __init__(
80
+ self: MLRegressor,
81
+ data: pd.DataFrame,
82
+ model_type: str,
83
+ regression_model: str,
84
+ features: list,
85
+ target: str,
86
+ timestamp: str,
87
+ logger: logging.Logger,
88
+ ) -> None:
81
89
  r"""Define constructor for the forecast class.
82
90
 
83
91
  :param data: The data that will be used for train/test
@@ -116,7 +124,9 @@ class MLRegressor:
116
124
  self.grid_search = None
117
125
 
118
126
  @staticmethod
119
- def add_date_features(data: pd.DataFrame, date_features: list, timestamp: str) -> pd.DataFrame:
127
+ def add_date_features(
128
+ data: pd.DataFrame, date_features: list, timestamp: str
129
+ ) -> pd.DataFrame:
120
130
  """Add date features from the input DataFrame timestamp.
121
131
 
122
132
  :param data: The input DataFrame
@@ -215,16 +225,25 @@ class MLRegressor:
215
225
  self.data_exo = self.data_exo.drop(self.target, axis=1)
216
226
  if self.timestamp is not None:
217
227
  self.data_exo = self.data_exo.drop(self.timestamp, axis=1)
218
- X = self.data_exo
219
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
228
+ X = self.data_exo
229
+ X_train, X_test, y_train, y_test = train_test_split(
230
+ X, y, test_size=0.2, random_state=42
231
+ )
220
232
  self.steps = len(X_test)
221
233
  base_model, param_grid = self.get_regression_model()
222
234
  if base_model is None:
223
235
  return False
224
236
  self.model = make_pipeline(StandardScaler(), base_model)
225
237
  # Create a grid search object
226
- self.grid_search = GridSearchCV(self.model, param_grid, cv=5, scoring="neg_mean_squared_error",
227
- refit=True, verbose=0, n_jobs=-1)
238
+ self.grid_search = GridSearchCV(
239
+ self.model,
240
+ param_grid,
241
+ cv=5,
242
+ scoring="neg_mean_squared_error",
243
+ refit=True,
244
+ verbose=0,
245
+ n_jobs=-1,
246
+ )
228
247
  # Fit the grid search object to the data
229
248
  self.logger.info("Training a %s model", self.regression_model)
230
249
  start_time = time.time()