Implement novelty_threshold decay in ProximityArchive#709
Conversation
…ting new solutions in ProximityArchive
|
Hi @amarrerod, thanks for the PR! I have some minor edits that I can make later, but since you seem quite familiar with Novelty Search, I wanted to check with you if this is a known way to decay the novelty threshold? When I wrote the issue in #540, the idea I proposed was off the top of my head; I am not sure if it is grounded in any paper. |
|
Hi @btjanaka, basically, I took the idea from parameter/restriction reduction, which is used in many optimisation algorithms. Apparently, someone has already tried something similar: https://ala2018.cs.universityofgalway.ie/papers/ALA_2018_paper_7.pdf (Eq. 3), but they decrease the threshold in every iteration, whether there are new novel solutions or not. |
novelty_threshold decay in ProximityArchive
btjanaka
left a comment
There was a problem hiding this comment.
HI @amarrerod, thanks again for sending in the PR! I made some tiny changes and also left some comments below. Let me know if you have any questions!
Sounds good! Let's proceed with this implementation, then. |
- Renames iterations_without_imp to threshold_decay_itrs - Renames threshold_decay to threshold_decay_rate - Includes threshold_decay_min with default value to 0.0 - Ensures threshold_decay_rate is in the range [0.0, 1.0] - Implements two new test cases to check 1. The novelty_threshold remains constant when novel a constant flow of solutions are included. 2. That novelty_threshold remains constant when there is a mix of additions and failed insertions.
Moved threshold_decay_rate first so that we can set a default for threshold_decay_itrs. This way, somebody can just set threshold_decay_rate without having to set other parameters, and threshold decay already works.
btjanaka
left a comment
There was a problem hiding this comment.
Hi @amarrerod, thanks again! I made some changes and submitted the PR. These were my changes:
- Moved
threshold_decay_ratebeforethreshold_decay_itrsandthreshold_decay_min, and I gavethreshold_decay_itrsa default of 1. This way, a user can just pass in thethreshold_decay_rate, and threshold decay will be turned on. - Moved the check for
threshold_decay_rate is Noneto_maybe_update_threshold. - Rearranged comments for
_maybe_update_threshold. - Ran 5 trials on the sphere benchmark to check for any performance regressions; after 5 trials I got:
Which is close to the current results; hence I see no regression.
| Algorithm | QD Score | Coverage | Trials | |------------:|----------------------:|--------------:|---------:| | ns_cma | 155,384.75 ± 7,831.25 | 19.08 ± 1.05% | 5 | - Made minor edits to the tests and also added another test.
Description
Implements issue #540:
novelty_thresholddecay inProximityArchiveafter X iterations without inserting any new novel solution.TODO
ProximityArchiveto consider two new optional arguments:iterations_without_impandthreshold_decay.iterations_without_impit is either None or a positive integer. When None,ProximityArchiveworks as expected with a fixednovelty_thresholdvalue. Otherwise, it defines the maximum number of iterations without inserting novel solutions, before decreasing thenovelty_thresholdby a factor ofthreshold_decay. Note thatthreshold_decayis a float value in the range [0.0, 1.0], and the newnovelty_thresholdis calculated followingCreate
__maybe_update_thresholdinProximityArchive: A private method of theProximityArchivethat, if the decay strategy is enabled, is called every timen_novel_enoughtis zero inadd. When the number of iterations reaches the user-defined maximum, thenovelty_thresholdis decreased.Create
test_add_non_novel_solution_threshold_decay: Inside proximity_archive_test, a new test case is included to test the new functionality. The test tries to insert the same solution X iterations and, after that, checks that thenovelty_thresholdhas been updated to the new expected value.Questions
__maybe_update_thresholdis a function that receives no parameters and acts over the state of theProximityArchiveobject. I thought about including this logic directly in theaddmethod. However, I believe it is cleaner to have all the logic inside a private method and call it from every branch of theaddmethod when necessary.Status
CONTRIBUTING.md
ruffandpylintpytestHISTORY.md