-
Notifications
You must be signed in to change notification settings - Fork 44
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
Redesigning Design Methods with Bayesian Optimisation #1762
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didnt get a ton of time to fully digest it today but we can discuss tomorrow. So far, it's looking good though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @m-bone just went through. Looks like it's getting pretty close. A few things:
- I think I still feel like it would make more sense to handle
fn_post
afterfn_mid
. In my mind, if we havefn_mid
return somethingdict-like
(ie either adict
or aBatchData
) then we can simply iterate through it and feed values tofn_post
, this would retain the memory saving ofBatchData.items()
, while I think simplifying the code. Let me know if you see any problem with that? - I think we still need to nail down some kind of well defined acceptable output type -> input type relationship for
fn_pre
andfn_post
. The current code implicitly seems to handle
fn_pre return type | fn_post arg type | notes |
---|---|---|
Simulation | SimulationData | line 170 |
dict[Any, Simulation] | dict[Any, SimulationData] | line 191 |
list[Simulation] | list[SimulationData] | line 213 |
Any | Any | line 217 |
I think we list need to consider a few things:
A: what if fn_pre
returns a mixed dict
or list
? say some Simulation
and some float
? for example, they want to pass some computed value to their fn post? Do we allow this? how do we handle it more generally?
B. should be able to trivially handle the fn_pre
returning Batch
or Job
directly I think.
C. I recall now that in the original design plugin, a dict output of fn_pre
actually gets input as kwargs
to fn_post
and a list
output gets passed as positional args
. see after cell [11]. https://docs.flexcompute.com/projects/tidy3d/en/latest/notebooks/Design.html
I think we just need to decide how to fill out this table once and for all.. Here's my proposal
in a general sense
fn_pre return type | fn_post arg type | notes |
---|---|---|
list | *args | |
dict | **kwargs | |
other | other |
and then within individual data, basically
fn_pre return type | fn_post arg type | notes |
---|---|---|
Simulation | SimulationData | |
Batch | BatchData | |
Job | SimulationData | |
anything else | itself |
Then we can say that if there's some special cases we handle to speed things along..
- if a
list
ordict
of stuff, anySimulation
-like data gets combined into one batch run, but then passed tofn_post
using the tables above.
That's pretty complex but I'll comment out some specifics to discuss
How does this sound? |
48b123b
to
0533e81
Compare
Noticed another change for optimisers compared to samplers: the user may want to return the raw output data from a simulation run whilst the optimiser will only take a single float value. I think it would be sensible to allow the user to output the raw data as a list/dict and we combine it within the results df, whilst the optimiser just gets passed the float. The two output cases would be:
We can include a MethodOptimise method that can deal with float or list output from the function and let the user know the requirement is that it must output a float or a list Is this too much pressure on the user? I feel this output is something people will want and it fits well within our existing API design. |
Hey Matt, I think this is a good thing to consider. The way that it’s handled in jax and autograd is to support a So yea what makes sense to me is to consider these two possible output possibilities to the |
With regards to the table I've implemented tests that validate all cases except
For Sim() I think the correct result is to run I'm also not convinced on allowing users to run their own batches using pre-post function inputs. Fn_mid doesn't currently support this so would need to be expanded. Creating a Batch feels like an unnecessary extra step because the user can just give us the dict they used if they wanted us to handle the batch. If we flatten the batch to take advantage of running sims in parallel, we'd likely lose whatever the user has specified as batch parameters. If the user really does want to manage their own batches it can be done with a single function. |
Just to respond to this officially / for reference (we kind of already discussed earlier):
This is true except for the memory advantage of
Yea this is true too.
Yes, but if the single function is used, then we can't take advantage of the parallelism over the arg_list (eg if each individual in the genetic algorithm population runs a batch, we'd have to run each batch sequentially). At some point, it might be worth building in some special cases to allow Batches of Batches.. with |
Hi @tylerflex, I think this is now ready for the first round of review. Sampler now ignores requirements for specific outputs and will take any object, whilst optimisers will now reliably throw an error for an unsupported outputs early on in the the execution. Testing has been expanded and is now covering >95% of the code. I believe I've implemented all the things we've discussed, as well as some extras so fire away if there's any questions! |
Thanks @m-bone ! I'm flying home today but will review as much as I can and maybe will have a review by tomorrow (my) morning or early afternoon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @m-bone . I added my initial comments. Overall the structure is looking pretty good! my comments are mainly details. Let's just discuss each of them and iterate a few times on it.
@tylerflex when you're ready I think this is good for your review. I've implemented all changes and added estimate_cost, logging and QoL features. The DesignSpace delete method will coming next but I want to review the existing design wrt. updating state and then go from there. I've removed the pre/2.8 commits that were included (again), so this is all just my design update |
Thanks @m-bone , enjoy your trip! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @m-bone , thanks for this. Looking pretty good! I had a lot of suggestions but I think it's getting there.
My main concern at a high level is that I have trouble following every detail as things have gotten pretty complicated. I think a lot of this can't be avoided because we're trying to do a lot of things with this package. But in general if we can be really clear and explicit in the docstrings, descriptions, and errors, that will go a long way. This especially pertains to when there are edge cases that we handle (eg behavior A if given type a, behavior B when given type b). We should be super clear otherwise I worry it will be confusing to users. But overall I think it is pretty good. Thanks!
d9a3e7c
to
b703a24
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @m-bone This is looking great. 80% of my comments were minor proofreading things. I think it's almost done. Only slight concerns right now are:
- Some of these methods are a bit complex. which is not necessarily bad, but could make them a bit hard to maintain them in long run. If you see any way to simplify them, please take the opportunity now while it's still fresh.
- I think docs will be very important here for usability, so please flesh out some of the docstrings for the main class with as much info, diagrams, links as you can, including links to the tutorial notebooks.
Other than that and some minor things, looks really good, think this will be a great addition!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, just not sure about the task_name default. Also just wondering if you checked how the docs look when compiled?
7a6f8eb
to
00adae8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good! just a few final things:
- Please add one or more items in the CHANGELOG.md. For example, I think: a sentence under "changed" summarizing the major changes to
design
. 1 or more bullet points under "added" discussing the new optimization methods. Basically this will be our mini advertisement that the tool has these new features - Could you squash all of these commits into 1 (or at most, a handful?) reason is to avoid an onslaught of new commits int he public branch. Just one or a few indicating the major changes should be easier. To squash, I usually rebase and "fixup" everything but the top commit, which I "reword" and call something general, eg ("design plugin overhaul and added optimization methods")
- After this we can merge the notebook PR
Nice work Matt! really excited to see this in production
415efd0
to
8e5af1f
Compare
@@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
- Added convenience functions `from_terminal_positions` and `from_circular_path` to simplify setup of `VoltageIntegralAxisAligned` and `CustomCurrentIntegral2D`, respectively. | |||
- Added `axial_ratio` to `DirectivityData.axial_ratio` for the `DirectivityMonitor`, defined as the ratio of the major axis to the minor axis of the polarization ellipse. | |||
`ComponentModeler.batch_data` convenience property to access the `BatchData` corresponding to the component modeler run. | |||
- Added optimization methods to the Design plugin. The plugin has been expanded to include Bayesian optimization, genetic algorithms and particle swarm optimization. Explanations of these methods are available in new and updated notebooks. | |||
- Added new support functions for the Design plugin: automated batching of `Simulation` objects, and summary functions with `DesignSpace.estimate_cost` and `DesignSpace.summarize`. | |||
|
|||
### Changed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually could you add a change item just to let users know of any API changes they might need?
Added Bayesian optimization, genetic algorithms, and particle swarm optimization methods Removed MethodRandom and MethodRandomCustom as had become redundant Expanded DesignSpace with new support methods estimate_cost and summarize Redesigned interface with plugin to make it easier for users to batch simulations for different design search methods Automated batching of simulations when user provides pre and post processing functions Expanded testing for all new features
8e5af1f
to
b280a6d
Compare
Redesigning method.py to allow for key usability improvements namely:
Included within this is the addition of Bayesian optimisation and the creation of a MethodOptimise subclass to enable rapid development of additional optimisation methods e.g. genetic algorithms.
This will require refactoring to reduce achieve this setup without significant compromising the current user experience. Principle change will be the requirement of pre_fn and post_fn functions for creating and processing simulated data.