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.
- emhass/command_line.py +702 -373
- emhass/data/associations.csv +1 -1
- emhass/forecast.py +671 -346
- emhass/machine_learning_forecaster.py +204 -105
- emhass/machine_learning_regressor.py +26 -7
- emhass/optimization.py +1017 -471
- emhass/retrieve_hass.py +226 -79
- emhass/static/data/param_definitions.json +5 -4
- emhass/utils.py +689 -455
- emhass/web_server.py +339 -225
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/METADATA +17 -8
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/RECORD +16 -16
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/WHEEL +1 -1
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/LICENSE +0 -0
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/entry_points.txt +0 -0
- {emhass-0.11.2.dist-info → emhass-0.11.3.dist-info}/top_level.txt +0 -0
@@ -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.
|
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__(
|
41
|
-
|
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=
|
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[
|
88
|
-
df[
|
89
|
-
df[
|
90
|
-
df[
|
91
|
-
df[
|
92
|
-
df[
|
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(
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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(
|
112
|
-
|
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=
|
142
|
+
self.data_exo = self.data_exo.interpolate(method="linear", axis=0, limit=None)
|
130
143
|
# train/test split
|
131
|
-
self.date_train =
|
132
|
-
|
133
|
-
|
134
|
-
self.
|
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 ==
|
158
|
+
if self.sklearn_model == "LinearRegression":
|
138
159
|
base_model = LinearRegression()
|
139
|
-
elif self.sklearn_model ==
|
160
|
+
elif self.sklearn_model == "ElasticNet":
|
140
161
|
base_model = ElasticNet()
|
141
|
-
elif self.sklearn_model ==
|
162
|
+
elif self.sklearn_model == "KNeighborsRegressor":
|
142
163
|
base_model = KNeighborsRegressor()
|
143
164
|
else:
|
144
|
-
self.logger.error(
|
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 =
|
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(
|
155
|
-
|
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(
|
159
|
-
|
160
|
-
|
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(
|
163
|
-
|
164
|
-
|
165
|
-
df_pred[
|
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
|
-
|
176
|
-
fixed_train_size = False,
|
177
|
-
steps = self.num_lags,
|
216
|
+
cv = cv,
|
178
217
|
metric = MLForecaster.neg_r2_score,
|
179
|
-
|
180
|
-
|
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(
|
185
|
-
|
186
|
-
|
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(
|
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(
|
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(
|
207
|
-
|
208
|
-
|
209
|
-
|
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(
|
212
|
-
|
213
|
-
|
214
|
-
|
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 ==
|
278
|
+
if self.sklearn_model == "LinearRegression":
|
227
279
|
if debug:
|
280
|
+
|
228
281
|
def search_space(trial):
|
229
|
-
search_space
|
230
|
-
|
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
|
235
|
-
|
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 ==
|
301
|
+
elif self.sklearn_model == "ElasticNet":
|
238
302
|
if debug:
|
303
|
+
|
239
304
|
def search_space(trial):
|
240
|
-
search_space
|
241
|
-
|
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
|
246
|
-
|
247
|
-
|
248
|
-
|
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 ==
|
324
|
+
elif self.sklearn_model == "KNeighborsRegressor":
|
251
325
|
if debug:
|
326
|
+
|
252
327
|
def search_space(trial):
|
253
|
-
search_space
|
254
|
-
|
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
|
259
|
-
|
260
|
-
|
261
|
-
|
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(
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
df_pred_opt
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
self.
|
305
|
-
self.logger.info(
|
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__(
|
80
|
-
|
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(
|
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(
|
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(
|
227
|
-
|
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()
|