es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

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)
   
Tags:  , ,

Answer

  1. Avatar for 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 usar estimator__<param_name>.

    En tu caso, puedes intentar establecer el parámetro para XGBoost como estimator__estimator__<param_name>, donde el estimator interno se refiere al estimador XGBoost real dentro del pipeline y el estimator 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:

    mimo_wrapper.set_params(estimator__estimator__max_depth=10)
    

    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.

Comments are closed.