-
Notifications
You must be signed in to change notification settings - Fork 37
Rework of how transformations are handled #575
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
Conversation
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
|
Aight, so it seems we weren't really testing cases such as product_distribution(fill(Dirichlet(ones(4)), 2, 3))(which might be because we didn't have support for this in Bijectors.jl until recently), and so I just added a test for this and now things are failiing 🙃 It turns out there's a bug in |
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Markus Hauru <[email protected]>
|
Thanks @mhauru |
|
Looks like everything is passing nicely:) |
mhauru
left a comment
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.
My only two unresolved comments are very minor, so I'm happy to approve. Likewise @yebai has a few unresolved comments, but he approved as well, so I assume he considers them non-blocking. @torfjelde, good to merge on your side?
| return ConstructionBase.constructorof(D)(iter) | ||
| end | ||
|
|
||
| function values_from_metadata(md::Metadata) |
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.
Having read the code more carefully, I think I agree with from_internal_transform being the right thing. Could still have a docstring, but optional.
|
I will open another PR for converting diagrams images to Mermaid! |
|
The API docs index.html had grown to exceed the threshold size allowed by Documenter by a few kilobytes. I doubled the threshold to 400 KiB. There doesn't seem to be anything wrong with the API page, it's just plain long. |
|
Does this count the images? Or is it just the HTML? |
|
I'm not sure if it would count the images, but they are small, and not on the page that exceeds the threshold. |
|
Hurray! Great stuff @torfjelde! |
While working on #555, I ran into the pain that is our current way of handling transformations.
This is partially because we've been slowly adding support for things that wasn't support back in the day, while trying to preserve functionality.
I think it's now time rip out quite a bit of the historical artifacts and rework this.
In DynamicPPL.jl we effectively have a very annoying problem where we can have three different "representation" of a realization:
AbstractVarInfostores the realization internally.AbstractVarInfostores a "linked" realization internally (this might differ from (1) in dimensionality, e.g.VarInfo, but also type, e.g.SimpleVarInfo).Distributionfrom which the variable is sampled.Back in the day when everything was easier, we could define the map
from_linked_internal(needed ingetindex,assume, etc.) as a simple composition offrom_internal(akareconstruct) andinvlink, and similarly forto_linked_internal(needed insetindex!,push!, etc.). But this resulting in multiple bugs once we started working with less convenient distributions, e.g.LKJCholeskywhere the linked representation is aVectorbut the model representation is aCholesky.So these days we can't really think about
from_linked_internalas a simple composition, but instead has to think about it as an "independent" mapping that can sometimes be represented in the old way not always.To handle this, we made
reconstruct, a function which was meant to take us from "internal representation" to "model representation", also accept the linking transformation, and attempts to construct whatever representation is needed for the pair(invlink_transform(dist), dist). This is okay, but because we have different implementations ofAbstractVarInfo, e.g.VarInfoandSimpleVarInfo, each of which have different internal representations, thereconstructhas this behavior where it sometimes does what you expect and sometimes doesn't do anything, and it's difficult to determine exactly when what happens.This PR removes
reconstructcompletely, in addition to other related methods, and effectively boils the entire transformation handling down to two mappings:from_internal_transform(varinfo, vn, dist): construct a transformation that takes us from the internal representation to the model representation.from_internal_transformation(varinfo, vn, dist): construct a transformation that takes us from the internal representation to the model representation.from_linked_internal_transform(varinfo, vn, dist): construct a transformation that takes us from the linked internal representation to the model representation. (correction by @yebai)Notice that these methods construct a transformation, and we want these transformations to also define
InverseFunctions.inverseandChangesOfVariables.with_logabsdet_jacobianso that we can easily define theto_*mappings and obtain the log-abs-det-jacobian corrections for the transformations easily.But that's really all we need + now everything is very explicit and clear.
There is a longer exposition on the topic in the docs accompanying this PR (see the docs preview under the "internals" tab) where I discuss why we need certain methods that might at a first glance now seem necessary.
Note that there is one drawback with this approach: we might run into type-instabilities since we're constructing a transform. One would hope that union splitting saves us; indeed that seems to work nicely for our test-suite on more recent Julia versions but not on 1.6. I'm not sure how much we should care about this though because once we move away from all the
Selectorstuff + old Gibbs sampler #573 , there's really no reason why anyone would every link only a subset of avarinfo, at which point we should always use the immutablelinkmethod and make whether or not avarinfois linked available at compile-time, not runtime.@devmotion @yebai