From: Jérôme Benoit Date: Thu, 25 Dec 2025 18:04:33 +0000 (+0100) Subject: refactor(quickadapter): improve optuna integration X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=cc913276a075adc048d1f269ac8d8fd1701aa2a2;p=freqai-strategies.git refactor(quickadapter): improve optuna integration Signed-off-by: Jérôme Benoit --- diff --git a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py index 59b76f3..5f5383e 100644 --- a/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py +++ b/quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py @@ -100,10 +100,16 @@ class QuickAdapterRegressorV3(BaseRegressionModel): *_SKIMAGE_THRESHOLD_METHODS, *_CUSTOM_THRESHOLD_METHODS, ) + _OPTUNA_STORAGE_BACKENDS: Final[tuple[str, ...]] = ("file", "sqlite") _OPTUNA_SAMPLERS: Final[tuple[str, ...]] = ("tpe", "auto") _OPTUNA_NAMESPACES: Final[tuple[OptunaNamespace, ...]] = ("hp", "train", "label") + _OPTUNA_LABEL_N_OBJECTIVES: Final[int] = 7 + _OPTUNA_LABEL_DIRECTIONS: Final[tuple[optuna.study.StudyDirection, ...]] = ( + optuna.study.StudyDirection.MAXIMIZE, + ) * _OPTUNA_LABEL_N_OBJECTIVES + _SCIPY_METRICS: Final[tuple[str, ...]] = ( # "braycurtis", # "canberra", @@ -417,7 +423,9 @@ class QuickAdapterRegressorV3(BaseRegressionModel): for pair in self.pairs: self._optuna_hp_value[pair] = -1 self._optuna_train_value[pair] = -1 - self._optuna_label_values[pair] = [-1, -1, -1, -1, -1, -1] + self._optuna_label_values[pair] = [ + -1 + ] * QuickAdapterRegressorV3._OPTUNA_LABEL_N_OBJECTIVES self._optuna_hp_params[pair] = ( self.optuna_load_best_params( pair, QuickAdapterRegressorV3._OPTUNA_NAMESPACES[0] @@ -1090,15 +1098,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): QuickAdapterRegressorV3.MAX_LABEL_NATR_RATIO_DEFAULT, ), ), - directions=[ - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - optuna.study.StudyDirection.MAXIMIZE, - ], + directions=list(QuickAdapterRegressorV3._OPTUNA_LABEL_DIRECTIONS), ), ) @@ -2106,8 +2106,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): isinstance(trial.values, list) and len(trial.values) == n_objectives and all( - isinstance(value, (int, float)) - and (np.isfinite(value) or np.isinf(value)) + isinstance(value, (int, float)) and np.isfinite(value) for value in trial.values ) ) @@ -2162,10 +2161,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel): if self._optuna_config.get("warm_start"): self.optuna_enqueue_previous_best_params(pair, namespace, study) - if is_study_single_objective is True: - objective_type = "single" - else: - objective_type = "multi" + objective_type = "single" if is_study_single_objective else "multi" logger.info( f"Optuna {pair} {namespace} {objective_type} objective hyperopt started" ) @@ -2379,13 +2375,22 @@ class QuickAdapterRegressorV3(BaseRegressionModel): def optuna_enqueue_previous_best_params( self, pair: str, namespace: str, study: Optional[optuna.study.Study] ) -> None: + if not study: + return + best_params = self.get_optuna_params(pair, namespace) - if ( - study - and best_params - and self.optuna_validate_params(pair, namespace, study) - ): + if not best_params: + return + + try: study.enqueue_trial(best_params) + except Exception as e: + logger.warning( + "Failed to enqueue previous best params for %s %s: %r", + pair, + namespace, + e, + ) def optuna_save_best_params(self, pair: str, namespace: str) -> None: best_params_path = Path( diff --git a/quickadapter/user_data/strategies/Utils.py b/quickadapter/user_data/strategies/Utils.py index a5e393f..70eed70 100644 --- a/quickadapter/user_data/strategies/Utils.py +++ b/quickadapter/user_data/strategies/Utils.py @@ -1932,7 +1932,9 @@ def get_optuna_callbacks( optuna.integration.XGBoostPruningCallback(trial, "validation_0-rmse") ] elif regressor == REGRESSORS[1]: # "lightgbm" - callbacks = [optuna.integration.LightGBMPruningCallback(trial, "rmse")] + callbacks = [ + optuna.integration.LightGBMPruningCallback(trial, "rmse", valid_name="valid_0") + ] else: raise ValueError( f"Unsupported regressor model: {regressor} (supported: {', '.join(REGRESSORS)})"