Modelo MultiInputOutput con búsqueda aleatoria utilizando Scikit Pipelines.
Estoy tratando de comparar diferentes estrategias de regresión para un problema de pronóstico:
- Usando algoritmos que admiten por defecto regresión de entrada y salida múltiples (es decir, Regresión lineal, Árboles, etc.).
- Usando algoritmos como envoltorio para hacer una regresión de entrada y salida múltiples (es decir, SVR, XGboost).
- Usando el regresor encadenado para explotar las correlaciones entre mis objetivos (ya que mi pronóstico en t + 1 está autocorrelacionado con el objetivo en t + 2).
La documentación de scikit para los envoltorios de entrada y salida múltiples no es muy buena, pero se menciona que:
https://scikit-learn.org/stable/modules/generated/sklearn.multioutput.MultiOutputRegressor.html
set_params(**params)[fuente]
Establezca los parámetros de este estimador.
El método funciona tanto en estimadores simples como en objetos anidados (como Pipeline).
Estos últimos tienen parámetros de la forma __ para que sea posible
actualice cada componente de un objeto anidado.
Por lo tanto, estoy construyendo mi canalización como:
pipeline_xgboost = Pipeline([('escala', StandardScaler()),
('seleccionador_de_varianza', VarianceThreshold(threshold=0.03)),
('estimador', xgb.XGBRegressor())])
Y luego creo el envoltorio como:
mimo_wrapper = MultiOutputRegressor(pipeline_xgboost)
Siguiendo la documentación de las canalizaciones de scikit, estoy definiendo mis parámetros de xgboost como:
parameters = [
{
'estimador__reg_alpha': [0.0001, 0.001, 0.01, 0.1, 1, 10, 100],
'estimador__max_depth': [10, 100, 1000]
etc...
}
Y luego ejecuto mi validación cruzada como:
randomized_search = RandomizedSearchCV(mimo_wrapper, parameters, random_state=0, n_iter=5,
n_jobs=-1, refit=True, cv=3, verbose=True,
pre_dispatch='2*n_jobs', error_score='raise',
return_train_score=True,
scoring='neg_mean_absolute_error')
Sin embargo, obtengo el siguiente problema:
ValueError: Invalid parameter reg_alpha for estimator Pipeline(steps=[('escala', StandardScaler()),
('seleccionador_de_varianza', VarianceThreshold(threshold=0.03)),
('estimador',
XGBRegressor(base_score=None, booster=None,
colsample_bylevel=None, colsample_bynode=None,
colsample_bytree=None, gamma=None, gpu_id=None,
importance_type='gain',
interaction_constraints=None, learning_rate=None,
max_delta_step=None, max_depth=None,
min_child_weight=None, missing=nan,
monotone_constraints=None, n_estimators=100,
n_jobs=None, num_parallel_tree=None,
random_state=None, reg_alpha=None,
reg_lambda=None, scale_pos_weight=None,
subsample=None, tree_method=None,
validate_parameters=None, verbosity=None))]). Consulte la lista de parámetros disponibles con `estimator.get_params (). Keys ()`.
¿No entendí la documentación de scikit? También he intentado configurar los parámetros como el parámetro del estimador como tal vez esta sea la forma de acceder a los parámetros cuando se encuentran en el mimo_wrapper, pero esto ha resultado infructuoso. (Ejemplo a continuación):
parameters = {
'estimador__estimador__reg_alpha': [0.0001, 0.001, 0.01, 0.1, 1, 10, 100],
'estimador__estimador__max_depth': [10, 100, 1000]
}
random_grid = RandomizedSearchCV(estimador=pipeline_xgboost, distribuciones_paramétricas=parámetros, estado_aleatorio=0, n_iter=5,
n_jobs=-1, refit=True, cv=3, verbose=True,
pre_dispatch='2*n_jobs', error_score='raise',
return_train_score=True,
scoring='neg_mean_absolute_error')
ajuste_de_hiperparámetros = random_grid.fit(df.drop(columns=TARGETS+UMAPS),
df[TARGETS])
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
/tmp/ipykernel_11898/2539017483.py in
----> 1 ajuste_de_hiperparámetros = random_grid.fit(final_file_df_with_aggregates.drop(columns=TARGETS+UMAPS),
2 final_file_df_with_aggregates[TARGETS])
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/sklearn/model_selection/_search.py in fit(self, X, y, groups, **fit_params)
889 return results
890
--> 891 self._run_search(evaluate_candidates)
892
893 # multimetric is determined here because in the case of a callable
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/sklearn/model_selection/_search.py in _run_search(self, evaluate_candidates)
1764 def _run_search(self, evaluate_candidates):
1765 """Search n_iter candidates from param_distributions"""
-> 1766 evaluate_candidates(
1767 ParameterSampler(
1768 self.param_distributions, self.n_iter, random_state=self.random_state
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/sklearn/model_selection/_search.py in evaluate_candidates(candidate_params, cv, more_results)
836 )
837
--> 838 out = parallel(
839 delayed(_fit_and_score)(
840 clone(base_estimator),
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/joblib/parallel.py in __call__(self, iterable)
1054
1055 with self._backend.retrieval_context():
-> 1056 self.retrieve()
1057 # Make sure that we get a last message telling us we are done
1058 elapsed_time = time.time() - self._start_time
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/joblib/parallel.py in retrieve(self)
933 try:
934 if getattr(self._backend, 'supports_timeout', False):
--> 935 self._output.extend(job.get(timeout=self.timeout))
936 else:
937 self._output.extend(job.get())
/anaconda/envs/azureml_py38/lib/python3.8/site-packages/joblib/_parallel_backends.py in wrap_future_result(future, timeout)
540 AsyncResults.get from multiprocessing."""
541 try:
--> 542 return future.result(timeout=timeout)
543 except CfTimeoutError as e:
544 raise TimeoutError from e
/anaconda/envs/azureml_py38/lib/python3.8/concurrent/futures/_base.py in result(self, timeout)
437 raise CancelledError()
438 elif self._state == FINISHED:
--> 439 return self.__get_result()
440 else:
441 raise TimeoutError()
/anaconda/envs/azureml_py38/lib/python3.8/concurrent/futures/_base.py in __get_result(self)
davy.ai
Parece que estás enfrentando problemas al establecer los parámetros para el envoltorio MultiOutputRegressor utilizando scikit-learn. Has seguido correctamente la documentación definiendo el pipeline para XGBoost con StandardScaler y VarianceThreshold como pasos de preprocesamiento y usando MultiOutputRegressor como envoltorio para habilitar la regresión de múltiples entradas y salidas. Sin embargo, no estás seguro de cómo establecer los parámetros para el estimador XGBoost dentro del envoltorio.
En tus fragmentos de código, has intentado establecer los parámetros usando
estimator__param
, pero esto no ha sido exitoso. También has notado que establecer el parámetro fuera de la función de búsqueda aleatoria funciona bien.Una posible razón por la cual esto está sucediendo podría ser la convención de nomenclatura de parámetros de objeto anidado de scikit-learn. Cuando usamos un envoltorio para un estimador, el pipeline de scikit-learn necesita saber el nombre del estimador real dentro del envoltorio, y este se llama
estimator
por defecto. Por lo tanto, para establecer un parámetro para el estimador dentro del envoltorio, necesitamos usarestimator__<param_name>
.En tu caso, puedes intentar establecer el parámetro para XGBoost como
estimator__estimator__<param_name>
, donde elestimator
interno se refiere al estimador XGBoost real dentro del pipeline y elestimator
externo se refiere al nombre del estimador XGBoost establecido dentro del envoltorio MultiOutputRegressor.Aquí tienes un ejemplo de cómo puedes establecer el parámetro XGBoost
max_depth
utilizando esta convención:De manera similar, puedes establecer otros parámetros como
reg_alpha
utilizando la misma convención de nomenclatura.Espero que esto te ayude a resolver los problemas y comparar diferentes estrategias de regresión para el problema de pronóstico.