-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Implement reversed and strictly positive ordered transform #7759
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
Implement reversed and strictly positive ordered transform #7759
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7759 +/- ##
=======================================
Coverage 92.83% 92.83%
=======================================
Files 107 107
Lines 18343 18354 +11
=======================================
+ Hits 17028 17039 +11
Misses 1315 1315
🚀 New features to boost your workflow:
|
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 great, I left some small comments and request for testing
pymc/distributions/transforms.py
Outdated
return pt.cumsum(x, axis=-1) | ||
if self.positive: | ||
x = pt.exp(value) | ||
else: # Everything except the first element is positive |
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.
Comment is a but imprecise. The deltas are positive but the values may still be negative after the cumsum
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.
Changed it to hopefully be more understandable
pymc/distributions/transforms.py
Outdated
if self.positive: | ||
x = pt.exp(value) | ||
else: # Everything except the first element is positive | ||
x = pt.zeros(value.shape) |
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.
We should use empty, also below
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.
Fixed. But just out of curiosity - how and why does it matter?
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.
It's not a fix just an optimization. Theres was another use in the other method.
It's faster because the allocated array doesn't have to be filled with zeros.
@@ -281,6 +281,18 @@ def test_ordered(): | |||
vals = get_values(tr.ordered, Vector(R, 3), pt.vector, floatX(np.zeros(3))) | |||
assert_array_equal(np.diff(vals) >= 0, True) | |||
|
|||
# Check that positive=True creates positive and still ordered values |
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.
Do we have a test that checks that forward/backward are inverses + jacobian that we could parametrize with the new parameters?
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.
Added them. Had to adjust the check_jacobian_det to take the absolute value and to have an absolute tolerance along a relative one, because ascending=False permutes values and this leads to a negative determinant and a slightly less clean logdet computation in general as it can't just multiply the main diagonal.
6f8be43
to
dc594eb
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, small typo
pymc/distributions/transforms.py
Outdated
x = pt.empty(value.shape) | ||
x = pt.set_subtensor(x[..., 0], value[..., 0]) | ||
x = pt.set_subtensor(x[..., 1:], pt.exp(value[..., 1:])) | ||
x = pt.cumsum(x, axis=-1) # Add deltas cumulativelyto initial value |
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.
typo
dc594eb
to
87fd3a0
Compare
87fd3a0
to
97cdf4e
Compare
Description
Generalize Ordered transform to take two optional parameters:
positive: (default: False) also ensure values are positive. This has better geometry than chaining order with log-transform as it avoids double-exponentiation
ascending: (default: True) allow for both ascending and descending orders. Latter is achieved simply by reversing the vector in both forward and backward transforms.
This is motivated by a draft PR into pymc-extras where I need a default transform for a positive and descending-ordered RV (NormalSingularValue)
Related Issue
NA
Checklist
Type of change