You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The gradient optimizers (gntr, lbfgs, trf, ms) and the local searches (powell, sim) run several searches at the same time, each from a different starting point, and keep the best result. The number of concurrent searches comes from population_size for the gradient methods and from n_starts for powell and sim. The orchestration is in pybnf/algorithms/optimizers/concurrent_multistart.py.
Every one of those searches runs until it meets its own stopping rule. Nothing ever stops a search early because other searches are doing better.
Why this wastes a cluster
Fitting a model with many parameters usually means most starting points land in a poor region and stay there. On a laptop with eight concurrent searches that is tolerable. On a cluster with two hundred, it is not. Most of those two hundred searches are clearly going nowhere within the first handful of iterations, and they then spend the rest of their iteration budget confirming it. Each of those iterations costs a full simulation with sensitivities, which is the most expensive thing PyBNF does.
So a large allocation is spent mostly on proving that bad starting points are bad.
Suggested approach
Run all the starts for a short budget of iterations. Rank them by the objective value they have reached. Keep the better half and give the survivors a longer budget. Repeat until one or a few remain.
The total cost stays about the same, but far more of it is spent on the searches that are actually improving. It also means a user can afford many more starting points for the same money, which is the thing that most improves the chance of finding the best fit.
This idea is standard practice in hyperparameter tuning, where it is usually called successive halving, and it transfers directly.
Why this fits what we already have
The orchestrator already routes each finished simulation to the search that owns it, tracks each search's iteration count, and knows how to retire one. ConcurrentMultiStartOptimizer.got_result already handles a search finishing and decrementing the active count. Stopping a search early is a policy decision on top of machinery that exists.
Every search's current objective value is already available on its runner object as runner.fval.
A search that looks bad early is not always bad. A starting point in a long shallow valley can trail the field for many iterations and then overtake everything. Cutting too aggressively will throw those away.
Some ways to keep that in check:
Use a gentle schedule and give the first round enough iterations that a slow start has a fair chance.
What happens now
The gradient optimizers (
gntr,lbfgs,trf,ms) and the local searches (powell,sim) run several searches at the same time, each from a different starting point, and keep the best result. The number of concurrent searches comes frompopulation_sizefor the gradient methods and fromn_startsforpowellandsim. The orchestration is inpybnf/algorithms/optimizers/concurrent_multistart.py.Every one of those searches runs until it meets its own stopping rule. Nothing ever stops a search early because other searches are doing better.
Why this wastes a cluster
Fitting a model with many parameters usually means most starting points land in a poor region and stay there. On a laptop with eight concurrent searches that is tolerable. On a cluster with two hundred, it is not. Most of those two hundred searches are clearly going nowhere within the first handful of iterations, and they then spend the rest of their iteration budget confirming it. Each of those iterations costs a full simulation with sensitivities, which is the most expensive thing PyBNF does.
So a large allocation is spent mostly on proving that bad starting points are bad.
Suggested approach
Run all the starts for a short budget of iterations. Rank them by the objective value they have reached. Keep the better half and give the survivors a longer budget. Repeat until one or a few remain.
The total cost stays about the same, but far more of it is spent on the searches that are actually improving. It also means a user can afford many more starting points for the same money, which is the thing that most improves the chance of finding the best fit.
This idea is standard practice in hyperparameter tuning, where it is usually called successive halving, and it transfers directly.
Why this fits what we already have
ConcurrentMultiStartOptimizer.got_resultalready handles a search finishing and decrementing the active count. Stopping a search early is a policy decision on top of machinery that exists.runner.fval.Care needed
A search that looks bad early is not always bad. A starting point in a long shallow valley can trail the field for many iterations and then overtake everything. Cutting too aggressively will throw those away.
Some ways to keep that in check:
Some measurement of how often a pruned search would have won, on real models, would be worth having before this is turned on by default.
Not in scope
This is about which searches keep running. It does not change how any individual search takes its steps.