-
-
Notifications
You must be signed in to change notification settings - Fork 971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optuna Suggests the Same Parameter Values in a lot of Trials (Duplicate Trials that Waste Time and Budget) #2021
Comments
Desirably, if the suggested parameters are the ones already suggested, the trial should be skipped for faster hyperparameter optimization, right? Reproduced output: https://gist.github.com/crcrpar/aba308a1350bb4986276a6c87cf256cb |
Exactly. If the trial has already been suggested, it should be skipped for faster hyperparameter optimization. Or better yet, it shouldn't have been suggested in the first place. The sampler should check the history of suggested hyperparameter values first before suggesting new one. |
By its nature, TPESampler tends to sample similar values with the number of trials increasing since it narrows the search space based on Bayesian optimization with the number of trials increasing. So I think it's a bit hard to avoid the same values suggested. That being said, we can deal with this case by checking the suggested values in the def objective(trial):
some_param = trial.suggest_int("some_param", 0, 100)
if some_param in param_history["some_param"]:
raise optuna.exceptions.TrialPruned()
...
# define your evaluation
return value The full code with this hack and its result is available: https://gist.github.com/crcrpar/c6d6fdf8112280654884353d6e68f6bb. Note that this solution might not be general enough to apply to other cases. @HideakiImamura would have some better ideas. |
Yes, and pruned past trials are treated differently for different samplers so it might or might not work. You could also just fail the trials by raising other exceptions or return an invalid value such as Just based on the code snippet above, let me just clarify that in case you're working with a discrete search space and your trial budget ( However, to properly address this issue we probably have to work on a new sampler based on a different algorithm. |
This issue has not seen any recent activity. |
If anyone cares enough about this in the meantime, I made a class for this. If you really want to prune repeats of pruned trials (or https://gist.github.com/bfs15/24045ab5e8ad007b4a09f708adfe359f |
This issue has not seen any recent activity. |
This issue was closed automatically because it had not seen any recent activity. If you want to discuss it, you can reopen it freely. |
This should really be the default implementation out-of-the-box. Can this issue be reopened? |
Re-open is welcome. import optuna
def objective1(trial):
x = trial.suggest_int("x", 0, 0)
return x
def objective2(trial):
x = trial.suggest_int("x", 0, 0)
# Here, it looks the same parameters but should not be pruned.
y = trial.suggest_int("y", 0, 0)
# We should check after all parameters have been suggested.
return x + y
study = optuna.create_study()
study.optimize(objective1, n_trials=1)
study.optimize(objective2, n_trials=1) |
@not522 Maybe we could have a built-in pruner that rejects duplicates and rolls back the number of trials by one automatically. |
+1 vote to add this functionality |
Thinking about this further, is this really a problem? While it is quite possible that the same parameter value will get suggested multiple times it seems extremely unlikely that all parameter values will be equal. So long as at least one parameter is different, isn't it worth running the trial? |
IMO, yes this is a problem worth resolving. Here are my concerns:
I don't see any value in Optuna running the same trial multiple times. In my humble opinion, it just makes sense to handle within the lib. |
I think @jmrichardson is right. In my work, after training for many iterations I collect say 10 models with best performance and evaluate them further (do they cluster data? etc.). out of the 10 with best performance I select the final candidate. With a lot of trials I tend to get all 10 models with the same parameters. Obviously I implemented a workaround for this, but I believe it should be handled within the library. |
This one is a bit tricky to do with distributed optuna as we'll need to query from storage what the historical parameters are. I was using it for feature selection, and it's a very serious problem as it gets rather stuck in exploitation and wastes a crazy amount of cycles. I was very surprised to see this behavior and had assumed that the sampler naturally handled this use case. Considering the goal of optuna is to "Efficiently search large spaces" it seems like this should be a high priority bug. I think a good way to handle this might be by getting a stable hash of the parameters and putting it into the storage. |
Hi all, what's the current status of this? I'm very interested in a tighter integration of this feature into optuna. |
In the black-box optimization, we can suppose "noisy" functions, i.e., including randomness in the objective values (E.g., https://arxiv.org/abs/2105.08195). For these problems, re-evaluating the objective function may be informative. Please note samplers don't know whether the objective function is noisy or not. import optuna
from optuna.trial import TrialState
def objective(trial):
x = trial.suggest_int("x", 0, 1)
y = trial.suggest_int("y", 0, 1)
for previous_trial in trial.study.trials:
if previous_trial.state == TrialState.COMPLETE and trial.params == previous_trial.params:
print(f"Duplicated trial: {trial.params}, return {previous_trial.value}")
return previous_trial.value
return x + y
study = optuna.create_study()
study.optimize(objective, n_trials=10) |
This "bug" is the first thing I have noticed when I started using/testing Optuna. If you are optimizing just one or two parameters, it will surely select exactly the same one (or two) parameters multiple times in your trials. Imagine, you are training a huge neural network and each trial takes a lot of time. Now out of 100 trials, you have repeated e.g. 30% of them. That is such a waste of time and resources. Hopefully it gets implemented/fixed soon. |
Parameters Tunning makes much more sense when the I think at least there should be an option to control this behavior |
+1.. I am here because I was running a study to determine which initializer worked best. Each trial takes quite a while. When I saw that all 3 trials ran the same initializer I was very confused. My assumption was that optuna would use a separate categorical initializer each trial, especially considering it was the only parameter. @optuna is there a solution I could open a PR for that you would find acceptable? |
I think it is important for TPE algorithm to "see" the duplicate trials to converge to the desired solution. However, if you know that the objective function is deterministic, you could memoize it to save time. #4352 provides a helper function for it. |
@contramundum53 if I understand correctly, you are caching the output of the last input. I would expect caching of multiple values. Ideally, I'd want to cache the X most frequent inputs where X could be infinity. |
Sorry if the name |
Right, that's what confused me. Maybe it should be called |
In distributed environment, it is possible that multiple trials with the same parameters are sampled "at the same time" before the results are |
This is a huge issue for distributed optimization. I'm seeing 10 workers, each running identical params, and each getting the same result, then all 10 workers sample another set of identical params and run those with the same result, etc. |
It could be another problem than we have discussed. I guess you fixed the seed of samplers, and the samplers suggest exactly the same parameters. I recommend |
The situation I described was with I was able to resolve the issue by calling Here's the gist: https://gist.github.com/camall3n/4b0272e547b0e5df05777ebed446b69f |
It drives me crazy that same point in the hyper-parameter space is sampled multiple times (see runs 18, 20, 21 and 22)
I'm using (Note: ignore trials index relative to search space size: several trial failed before number 17) |
@gabriel-vanzandycke Which version of optuna are you using? This problem with GridSampler is supposed to be fixed in #2783 (released in v2.9), except for a few trials in the end. |
Hi! Great discussion! I would very much argue we need a solution for this problem, and ideally within Optuna. I totally see that there is no 'one-size-fits-all' solution, and users will have to make a choice about this (with sensible defaults ideally). Ax for example, has a flag that allows to specify whether the experiment should be regarded as deterministic. It is important to find a solution because the phenomenon of repeated experiment values is quite prevalent from what I can see, and it burns very real time and money. I am using Optuna through the plugin for hydra, hence do not have an overview of trials to fall back to recent results (the experiments themselves are not aware of the hyperparameter optimization process), so a configurable solution from within Optuna would be amazing to have! |
Use this pruner:
|
@classner In the case you cannot modify the code of the objective function and you cannot use Pruners, you can write a sampler wrapper that hooks |
+1 |
I agree with this, I use Optuna through Ray and find it hard to implement such changes as well. |
@tniveej I think you can write a sampler wrapper that removes duplicate parameters, which you can then plug in to the |
In RL you have stochastic policies and stochastic environments. |
Hello everyone, I understand that mathematically, Bayesian optimization can converge to a local optimum. Does this also occur in Optuna? |
TPE can converge to a local optimum, but it can and actually very often sample the same parameters multiple times long before convergence (if all parameters are discrete). |
A descent implementation of Gaussian process-based Bayesian optimization would do that much less likely (if the objective function is deterministic and the sampler correctly infers so). However, currently We are trying to implement Gaussian process ourselves right now. (#5185) |
…d their hyperparameters - update OptunaPruningSingleFitCallback `report_nb_steps` param - rename into `optuna_report_nb_steps` to identify it more simply in kwargs - give it a default value if user does not define it in optuna script - add a full example with - solvers_to_test: list of classes of solver to test - kwargs_fixed_by_solver: kwargs to pass to __ini__, init_model, and solve, except for hyperparameters - solvers_by_name: mapping string -> solver class (by default using solver_class.__name__ but should be overriden if same names for different solvers) - problem: defining the problem to solve - using default objectives by default, and deducing fromt it - direction ("minimize" or "maximize") - objective name to display in optuna dashboard - objective(trial) function: can be let as is - study_name: nmae given to the study - storage_path: path to the file used to log the study (can be the same for several studies). For easy parallelisation, can be a NFS path. A JournalFileStorage will be created at that path if none existing. - optuna_nb_trials: number of trials to be executed by optuna if relaunched, another batch of same number of trials will be added if parallelized, each node/process will launch this same number of trials - seed: fixed to get reproducible results. But should be None for parallelization to avoid having same trials for each node/process. - duplicate trials - failed trials: by default, they are ignored by optuna, so we explicitely prune following trials with exactlythe same hyperparameters - complete trials: TPESampler can (and will when converging on categorical hyperparameters) suggest duplicate trials. In that case we raise a warning and simply return the previously computed fit, as we are fully deterministic. See https://optuna.readthedocs.io/en/stable/faq.html#how-can-i-ignore-duplicated-samples and also optuna/optuna#2021 The optuna results can be monitored by optuna-dashboard optuna-journal.log (if storage_path let as is)
…d their hyperparameters - update OptunaPruningSingleFitCallback `report_nb_steps` param - rename into `optuna_report_nb_steps` to identify it more simply in kwargs - give it a default value if user does not define it in optuna script - add a full example with - solvers_to_test: list of classes of solver to test - kwargs_fixed_by_solver: kwargs to pass to __ini__, init_model, and solve, except for hyperparameters - solvers_by_name: mapping string -> solver class (by default using solver_class.__name__ but should be overriden if same names for different solvers) - problem: defining the problem to solve - using default objectives by default, and deducing fromt it - direction ("minimize" or "maximize") - objective name to display in optuna dashboard - objective(trial) function: can be let as is - study_name: nmae given to the study - storage_path: path to the file used to log the study (can be the same for several studies). For easy parallelisation, can be a NFS path. A JournalFileStorage will be created at that path if none existing. - optuna_nb_trials: number of trials to be executed by optuna if relaunched, another batch of same number of trials will be added if parallelized, each node/process will launch this same number of trials - seed: fixed to get reproducible results. But should be None for parallelization to avoid having same trials for each node/process. - duplicate trials - failed trials: by default, they are ignored by optuna, so we explicitely prune following trials with exactlythe same hyperparameters - complete trials: TPESampler can (and will when converging on categorical hyperparameters) suggest duplicate trials. In that case we raise a warning and simply return the previously computed fit, as we are fully deterministic. See https://optuna.readthedocs.io/en/stable/faq.html#how-can-i-ignore-duplicated-samples and also optuna/optuna#2021 The optuna results can be monitored by optuna-dashboard optuna-journal.log (if storage_path let as is)
In v3.6, (If it still suggests duplicate parameters, it is due to precision loss in GP. |
Recently opened issue again (didn't know about this one), and wanted to ask why the solution is still user-added boilerplate code from the FAQ? It would be much easier to implement this as another parameter for the sample, i.e. previously mentioned I want to mention that in machine learning there is a huge problem of copy-pasted boilerplate code for everything, and right now instead of simple parameter users have to remember to insert several rows into their objective function. I suggest to reconsider this decision, with many users asking for built-in solution in this issue. Thank you in advance! @contramundum53 @nzw0301 |
Thank you for your feedback. We see this issue as a high-demand problem with a lot of interest. However, how to resolve this issue needs a lot of discussion and we have yet to do anything other than put a work-around in the FAQ. #4352 is an option, but in exchange for easier implementation, it compromises the simplicity of the API. |
Optuna TPESampler and RandomSampler try the same suggested integer values (possible floats and loguniforms as well) for any parameter more than once for some reason. I couldn't find a way to stop it from suggesting same values over over again. Out of 100 trials quite a few of them are just duplicates. Unique suggested value count ends up around 80-90 out of 100 trials. If I include more parameters for tuning, say 3, I even see all 3 of them getting the same values a few times in 100 trials.
It's like this:
[I 2020-11-14 14:44:05,320] Trial 8 finished with value: 45910.54012028659 and parameters: {'min_data_in_leaf': 75}. Best is trial 4 with value: 45805.19030897498.
[I 2020-11-14 14:44:07,876] Trial 9 finished with value: 45910.54012028659 and parameters: {'min_data_in_leaf': 75}. Best is trial 4 with value: 45805.19030897498.
[I 2020-11-14 14:44:10,447] Trial 10 finished with value: 45831.75933279074 and parameters: {'min_data_in_leaf': 43}. Best is trial 4 with value: 45805.19030897498.
[I 2020-11-14 14:44:13,502] Trial 11 finished with value: 46125.39810101329 and parameters: {'min_data_in_leaf': 4}. Best is trial 4 with value: 45805.19030897498.
[I 2020-11-14 14:44:16,547] Trial 12 finished with value: 45910.54012028659 and parameters: {'min_data_in_leaf': 75}. Best is trial 4 with value: 45805.19030897498.
Example code below:
The text was updated successfully, but these errors were encountered: