3 votes

Comment corriger l'erreur "'_BaseUniformDistribution' object has no attribute 'to_internal_repr'" - comportement étrange dans optuna

J'essaie d'utiliser la librairie optuna en Python pour optimiser les paramètres des modèles de systèmes de recommandation. Ces modèles sont personnalisés et ressemblent à des modèles sklearn standard fit-predict (avec les méthodes get/set params).

Ce que je fais : une simple fonction objective qui sélectionne deux paramètres à partir d'une distribution uniforme, définit ces paramètres pour le modèle, prédit le modèle (il n'y a pas d'étape d'ajustement car il s'agit d'un modèle simple qui utilise les paramètres uniquement dans l'étape de prédiction) et calcule une certaine métrique.

Ce que j'obtiens : le premier essai se déroule normalement, il échantillonne les paramètres et imprime les résultats dans le journal. Mais lors du deuxième essai et de l'essai suivant, j'ai des erreurs étranges (voir le code ci-dessous) que je n'arrive pas à résoudre ou à googler. Lorsque je lance l'étude sur un seul essai, tout va bien.

J'ai essayé de réorganiser les parties de la fonction objective, de placer la phase d'ajustement à l'intérieur, d'essayer de calculer des paramètres plus simples, mais rien n'y fait.

Voici ma fonction objective :

# getting train, test
# fitting model
self.model = SomeRecommender()
self.model.fit(train, some_other_params)

def objective(trial: optuna.Trial):
    # save study
    if path is not None:
        joblib.dump(study, some_path)

    # sampling params
    alpha = trial.suggest_uniform('alpha', 0, 100)
    beta = trial.suggest_uniform('beta', 0, 100)

    # setting params to model
    params = {'alpha': alpha,
              'beta': beta}
    self.model.set_params(**params)

    # getting predict
    recs = self.model.predict(some_other_params)

    # metric computing
    metric_result = Metrics.hit_rate_at_k(recs, test, k=k)

    return metric_result

# starting study
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=3, n_jobs=1)

C'est ce que j'obtiens en trois essais :

[I 2019-10-01 12:53:59,019] Finished trial#0 resulted in value: 0.1. Current best value is 0.1 with parameters: {'alpha': 59.6135986324444, 'beta': 40.714559720597585}.
[W 2019-10-01 13:39:58,140] Setting status of trial#1 as TrialState.FAIL because of the following error: AttributeError("'_BaseUniformDistribution' object has no attribute 'to_internal_repr'")
Traceback (most recent call last):
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/study.py", line 448, in _run_trial
    result = func(trial)
  File "/Users/roseaysina/code/project/model.py", line 100, in objective
    'alpha', 0, 100)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/trial.py", line 180, in suggest_uniform
    return self._suggest(name, distribution)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/trial.py", line 453, in _suggest
    self.study, trial, name, distribution)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/samplers/tpe/sampler.py", line 127, in sample_independent
    values, scores = _get_observation_pairs(study, param_name)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/samplers/tpe/sampler.py", line 558, in _get_observation_pairs
    param_value = distribution.to_internal_repr(trial.params[param_name])
AttributeError: '_BaseUniformDistribution' object has no attribute 'to_internal_repr'
[W 2019-10-01 13:39:58,206] Setting status of trial#2 as TrialState.FAIL because of the following error: AttributeError("'_BaseUniformDistribution' object has no attribute 'to_internal_repr'")
Traceback (most recent call last):
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/study.py", line 448, in _run_trial
    result = func(trial)
  File "/Users/roseaysina/code/project/model.py", line 100, in objective
    'alpha', 0, 100)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/trial.py", line 180, in suggest_uniform
    return self._suggest(name, distribution)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/trial.py", line 453, in _suggest
    self.study, trial, name, distribution)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/samplers/tpe/sampler.py", line 127, in sample_independent
    values, scores = _get_observation_pairs(study, param_name)
  File "/Users/roseaysina/anaconda3/envs/sauvage/lib/python3.7/site-packages/optuna/samplers/tpe/sampler.py", line 558, in _get_observation_pairs
    param_value = distribution.to_internal_repr(trial.params[param_name])
AttributeError: '_BaseUniformDistribution' object has no attribute 'to_internal_repr'

Je n'arrive pas à comprendre où est le problème et pourquoi le premier essai fonctionne. Merci de m'aider.

Merci de votre attention !

5voto

sile Points 141

Votre code ne semble pas poser de problème.

J'ai exécuté une version simplifiée de votre code (voir ci-dessous), qui a bien fonctionné dans mon environnement :

import optuna

def objective(trial: optuna.Trial):
    # sampling params
    alpha = trial.suggest_uniform('alpha', 0, 100)
    beta = trial.suggest_uniform('beta', 0, 100)

    # evaluating params
    return alpha + beta

# starting study
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=3, n_jobs=1)

Pourriez-vous me donner des informations sur votre environnement afin que nous puissions étudier le problème ? (par exemple, système d'exploitation, version de Python, interpréteur Python (CPython, PyPy, IronPython ou Jython), version d'Optuna)

pourquoi le premier essai fonctionne.

Cette erreur est soulevée par optuna/samplers/tpe/sampler.py#558 et cette ligne n'est exécutée que lorsque le nombre d'essais terminés dans l'étude est supérieur à zéro.

BTW, vous pouvez peut-être éviter ce problème en utilisant RandomSampler comme suit :

sampler = optuna.samplers.RandomSampler()
study = optuna.create_study(direction='maximize', sampler=sampler)

Il est à noter que les performances d'optimisation de RandomSampler a tendance à être pire que TPESampler qui est l'échantillonneur par défaut d'Optuna.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X