-
Notifications
You must be signed in to change notification settings - Fork 31
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
Gama re-evaluates already evaluated pipelines #189
Comments
Thanks for the report, this is not intentional. |
Perhaps the following is of interest to estimate the impact of the issue. For my own purposes I ran GAMA multiple times, in total evaluating 25916 pipelines, of which 2322 (~9%) were previously-seen-pipeline evaluations. |
On a similar note, I have a better estimate on the severity of the issue. For my purposes I have a lot of GAMA runs, in total there were 1.277.162 individuals evaluated, across all of the 3 search methods currently faciliated (AsyncEA, RandomSearch and ASHA) on the datasets from OpenML-18CC. These evaluations do not include ASHA evaluations on a subset of a dataset, thus only when subsample = 1.0. Out of the 1.277.162 evaluations, a total of 188.550 seem to be duplicates, or about 14.7%. |
Hi @leightonvg - Note that I came around your issue by full hazard! Well spotted though. If you are interested in assisting the team of @PGijsbers with this issue, you could investigate the matter and submit a pull request, I reckon 🫡 I am involved in numerous other pull requests, but this one may be of tremendous interest to many in the future. Although I am not yet one of the primary developers for GAMA, I believe we could approach this issue from two distinct perspectives - If I am not mistaken. I would classify them as narrowed and broad. Say that broad should be performed outside of any search algorithm, thereby preventing any algorithm from having duplicates. However, I cannot recall a current population of evaluated individuals existing outside of an algorithm. I could be incorrect however. In a narrowed context, nonetheless, this duplicated avoidance design could be delegated to the search algorithm / the search algorithm designer. This is primarily due to the fact that the majority of the search algorithm should have an up-to-date status on the currently evaluated population, as this information should be returned at the conclusion of the search - in any event! Therefore, let us examine a simple example, random search. Random search does update a variable called I believe that with my proposed solution, we could gain:
I trust that these modifications serve as a solid foundation. It would be essential to conduct experiments to ensure that the modifications do not introduce unintended side effects and function as expected in a variety of situations. If @leightonvg or other contributors are willing to advance this, they can begin with this foundation and make any necessary modifications. Following this, the subsequent phase would be to repeat this process for every search method thus far. In case you do follow this way and my briefly proposed solution, I would be happy to have my name somewhere as contributor of the pull request 😛 that could be helpful to me if that makes sense. Code: def random_search(
operations: OperatorSet,
output: List[Individual],
start_candidates: List[Individual],
max_evaluations: Optional[int] = None,
max_attempts: int = 100000
) -> List[Individual]:
"""Perform random search over all possible pipelines without duplicates.
Parameters
----------
operations: OperatorSet
An operator set with `evaluate` and `individual` functions.
output: List[Individual]
A list which contains the found individuals during search.
start_candidates: List[Individual]
A list with candidate individuals to evaluate first.
max_evaluations: int, optional (default=None)
If specified, only a maximum of `max_evaluations` individuals are evaluated.
If None, the algorithm will be run indefinitely.
max_attempts: int, optional (default=100000)
Maximum number of attempts to generate a unique individual otherwise raise an error.
Returns
-------
List[Individual]
All evaluated individuals.
"""
_check_base_search_hyperparameters(operations, output, start_candidates)
# Using a set for constant-time lookups, i.e O(1).
already_evaluated_pipelines = {ind.pipeline for ind in output}
with AsyncEvaluator() as async_:
for individual in start_candidates:
async_.submit(operations.evaluate, individual)
while (max_evaluations is None) or (len(output) < max_evaluations):
future = operations.wait_next(async_)
if future.result is not None:
output.append(future.result.individual)
already_evaluated_pipelines.add(future.result.individual.pipeline)
attempts = 0
new_individual = operations.individual()
while new_individual.pipeline in already_evaluated_pipelines:
if attempts >= max_attempts:
raise ValueError("Maximum attempts reached while trying to generate a unique individual.")
new_individual = operations.individual()
attempts += 1
async_.submit(operations.evaluate, new_individual)
return output |
I do not know if you were aware already, but it seems as if GAMA re-creates individuals it has already evaluated before. This is also the case after the initial population, when the duplicate is created after another equivalent pipeline was already evaluated.
In the small test I ran, GAMA evaluated 131 individuals without errors. 10 of these were previously-seen.
The text was updated successfully, but these errors were encountered: