-
Notifications
You must be signed in to change notification settings - Fork 1
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
Review feedback #82
Comments
This is awesome work, I'm excited for this to be released and grow. After a high-level pass, here are my initial thoughts. DocumentationSome thoughts for improvement:
Return structs
Here, are some of my thoughts on syntax to accomplish this. I prefer options 2 or 3. 1. Using the approach proposed in #80I don't have any major issues with this approach, except that I think One side question would be why is 2. Tweaking #80 to return only one objectInstead of returning struct SimpleFormulation{P<:AbstractPredictor} <: AbstractFormulation
predictor::P
outputs::Array{Any} # new field for `y`
variables::Vector{Any}
constraints::Vector{Any}
end Then the user can just extract the outputs y from the formulation object as wanted. Going one step further, one could even overload Base.getindex(f::SimpleFormulation, inds...) = getindex(f.outputs, inds...) 3. Store the formulation info in the model and use referencesAdding a little more complexity, we could store the formulation objects in predictor = add_predictor(model, nn, x)
y = outputs(predictor)
cons = transformation_constraints(predictor)
vars = transformation_variables(predictor)
predictor_obj = predictor_object(predictor)
set_transformation(predictor, TransformType()) # change the transformation used in-place
delete(model, predictor) # removes the predictor and anything it added to the model
See #67 Comparison to existing projects
The comparison seems fair, but it could use some improvements.
MathOptAI.jl/docs/src/developers/design_principles.md Lines 108 to 114 in e1e4f47
MathOptAI.jl/docs/src/developers/design_principles.md Lines 126 to 129 in e1e4f47
MathOptAI.jl/docs/src/developers/design_principles.md Lines 137 to 138 in e1e4f47
Some additional points that might be worth mentioning:
Also, there is a recent review article that goes over a lot of the current software tools for embedding surrogate predictors in optimization models that is worth a look: https://doi.org/10.1021/acs.iecr.4c00632 Other thoughtsFinally, here are some other ideas/thoughts that came to mind. Reduced-space formulations
MathOptAI.jl/ext/MathOptAIPythonCallExt.jl Lines 45 to 50 in e1e4f47
reduced_space = true to work on NNs and simply ignore this option for layers where it is not applicable, perhaps throwing a warning instead of an error. Scaling
See #87 Black-box transformations
See #90 Other modelsAdding support for the following would be useful:
|
Fixed by #83 |
Niiiice @pulsipher. This is super helpful. How common are: set_transformation(predictor, TransformType())
delete(model, predictor) Delete seems easy. |
On scaling: I really didn't see the point of adding this to MathOptAI. Isn't it just a transformation you can trivially do in user-code? |
This is a pretty nice overview article. I think we're in a good position to play to JuMP's strengths with the wide variety of base AML features and multiple dispatch to provide a really great library. |
Deletion is a capability provided by alternative tools and seems easy to implement in MathOptAI. Admittedly, this is not a feature I really use, but I also don't tend use delete variables or constraints in JuMP models either. One possible scenario, might be wanting to replace a predictor with one that has updated weights. Setting the transformation is not a critical feature, but we have used such workflows when comparing the performance of different transformation approaches without having to rebuild the model each time. It has been helpful on large models where the build time is considerable. In terms of performance, simply deleting the old constraints and replacing these with the new transformation would be sufficient. I would think this is straightforward with full-space formulations since you can just reuse the previous output variables, but reduced-space formulations would definitely be more tricky. Perhaps such a feature would be limited to full-space if it were to be added. Alternatively, the user could just manually delete the predictor (assuming this capability is added) along with the constraints/objective it was used in and then add it again using the new transformation method. |
This isn't an argument that we should also implement it 😄 I'd much prefer we went for simplicity over a bag-of-features that are not used. |
For black-box outputs, we could automate wrapping It seems like a reasonable request. I'll open a separate issue. |
Thanks for the review @pulsipher. I think we've made a bunch of nice changes, and there are some more in the pipeline. |
Happy to help, this will integrate quite nicely into my research group. Thanks for all your hard work and the quick turnaround on making changes. |
With Flux, attempting to add a
Fixed by #95 |
Also, this function: Lines 93 to 96 in 36c9739
seems to assume that predictors will always take a vector of inputs, but I can envision wanting to support predictors later on that take in array inputs (e.g., CNNs, neural operators). |
Most definitely. Will be easier to catch and improve all these once we have CI and coverage up and running, etc.
Yes!!! I should discuss this as a design principle. I think Julia libraries too quickly lean to "anything goes". I want to keep inputs as a
Otherwise, it would need evaluate_df.enroll = map(eachrow(evaluate_df)) do row
return only(MathOptAI.add_predictor(model, model_glm, row))
end Although, on reflection, perhaps that's not too bad. |
This philosophy makes sense, thanks for adding the clarification to the docs. In near future however I would very much like to add support for CNNs which are not readily compatible with vector inputs. To deal with this, I see two main options:
My intuition is that option 1 would be simpler to implement and simpler for the user. |
So one thing that would be super helpful for this are example/tutorials. I tend to lean towards (2), provided that the reshaping is exactly
I don't disagree. But if they're using PyTorch/(F)lux, then they don't care how the layer is implemented internally. It would only be if they manually are using the MathOptAI layers directly. I'm a little concerned about scope explosion for this library. There are just so many things we could do, and it isn't obvious which ones are must-haves and which ones are niche features that a single user needs. As one example, I used to have a Before we did anything like this, we need many more examples. |
Closing this issue because I think it has run its course. We can open more focused issues to discuss input types etc if/when we decide to start supporting CNNs etc. |
The purpose of this issue is to collate and discuss user feedback.
Layout
Predictors all live in
https://github.com/lanl-ansi/MathOptAI.jl/tree/main/src/predictors
Extensions live in
https://github.com/lanl-ansi/MathOptAI.jl/tree/main/ext
Documentation
The docs can be difficult to build, because it requires a PyTorch installation via CONDA.
You might need to uncomment:
MathOptAI.jl/docs/src/tutorials/pytorch.jl
Line 22 in e1e4f47
Otherwise, you'll need to make do with reading the source until I can set up CI (we need the repo to be public first).
Here's a good tutorial intro:
https://github.com/lanl-ansi/MathOptAI.jl/blob/main/docs/src/tutorials/mnist.jl
The predictors all have doctrings and examples
MathOptAI.jl/src/predictors/Affine.jl
Lines 7 to 43 in e1e4f47
Return structs
Read #67 and #80. Thoughts, comments, and ideas?
Comparison to existing projects
Read https://github.com/lanl-ansi/MathOptAI.jl/blob/main/docs/src/developers/design_principles.md. Have I misrepresented anything, or left anything out?
The text was updated successfully, but these errors were encountered: