-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Fix ordering Transformation for batched dimensions #6255
Fix ordering Transformation for batched dimensions #6255
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #6255 +/- ##
==========================================
- Coverage 94.17% 90.44% -3.73%
==========================================
Files 111 111
Lines 23908 23985 +77
==========================================
- Hits 22515 21693 -822
- Misses 1393 2292 +899
|
Hey. The instantiations' Regarding the |
I know, tests are still missing here. I hesistate here, because, if my changes are the way to go here, then I think |
@TimOliverMaier I think we can remove the old ordered one. Question: should we raise |
@ricardoV94 thank you for your response! Alright, I will alter the relevant tests then. But we keep the Yes, good point. I will implement in the |
Just some edge cases: MatrixNormal and RandomWalk with multivariate innovations (RandomWalk.ndim_supp = innovation.ndim_supp + 1) |
I am not sure that's better actually... |
311bf9d
to
9d279db
Compare
80c7dcc
to
7515c73
Compare
1. updated variable `__all__` to contain `univariate_ordered`,`multivariate_ordered` and analogous `sum_to_1` instantiations.
I updated the tests now to use the new instantiations and implemented the pymc/pymc/tests/distributions/test_transform.py Lines 620 to 645 in 7442474
These were added earlier in this PR. I think the shape of the transforms is now properly tested in pymc/pymc/tests/distributions/test_transform.py Lines 247 to 255 in 7442474
|
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.
@TimOliverMaier we forgot to include this PR in our major release of 4.4.0 last night. As such I would agree with your initial suggestion of keeping the original transforms around for a bit longer so we can merge these fixes and release them with 4.1, without breaking backwards compatibility. I hope that's not too annoying :)
Besides that I have some small suggestions for the new tests. I wrote about the first but it applies to both. Let me know what you think
@@ -598,3 +615,31 @@ def test_discrete_trafo(): | |||
with pytest.raises(ValueError) as err: | |||
pm.Binomial("a", n=5, p=0.5, transform="log") | |||
err.match("Transformations for discrete distributions") | |||
|
|||
|
|||
def test_transforms_ordered(): |
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.
Perhaps a more direct name?
def test_transforms_ordered(): | |
def test_2d_univariate_ordered_(): |
transform=tr.univariate_ordered, | ||
) | ||
|
||
log_prob = model.point_logps() |
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.
To make this test a bit more readable I would suggest including an equivalent x_1d = pm.Normal(..., shape=(4,))
in the model and comparing the elemwise logp of that is the same as each copy of the 2D (10, 4)
one that exists now.
You can do that via m.compile_logp(sum=False)({"x_1d_ordered__": np.zeros((4,)), x_2d_ordered__": np.zeros(10, 4)})
and then asserting closeness across the last axis.
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.
For the sum_to_1
transform the logps are not the same. Is this expected? Even if the shape is the same like here:
def test_2d_univariate_sum_to_1():
with pm.Model() as model:
x_1d = pm.Normal(
"x_1d",
mu=[-3,-1,1,2],
sigma=1,
size=(10,4),
transform=tr.univariate_sum_to_1,
)
x_2d = pm.Normal(
"x_2d",
mu=[-3, -1, 1, 2],
sigma=1,
size=(10, 4),
transform=tr.univariate_sum_to_1,
)
log_p = model.compile_logp(sum=False)({"x_1d_sumto1__":np.ones((10,3))*0.25,"x_2d_sumto1__":np.zeros((10,3))*0.25})
np.testing.assert_allclose(log_p[0],log_p[1])
Fails with:
./pymc/tests/distributions/test_transform.py::test_2d_univariate_sum_to_1 Failed: [undefined]AssertionError:
Not equal to tolerance rtol=1e-07, atol=0
Mismatched elements: 40 / 40 (100%)
Max absolute difference: 1.03125
Max relative difference: 0.72677567
x: array([[-6.200189, -1.700189, -1.200189, -2.450189],
[-6.200189, -1.700189, -1.200189, -2.450189],
[-6.200189, -1.700189, -1.200189, -2.450189],...
y: array([[-5.418939, -1.418939, -1.418939, -1.418939],
[-5.418939, -1.418939, -1.418939, -1.418939],
[-5.418939, -1.418939, -1.418939, -1.418939],...
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.
Ok funny. This is not the case if I use np.zeros
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.
PR looks good otherwise, should we investigate the SumTo1
?
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.
Was this when comparing np.zeros()
, vs np.ones()
? I don't expect those to be equivalent...
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.
Oh boy 😆 . Maybe it was just that. I thought I was comparing np.ones()
to np.ones()
. will check again.
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.
Yes. This was my mistake, sorry! Checked it properly with np.ones()
and it passes.
1. Old `transforms.ordered` and `transforms.sum_to_1` instantiations were added again for backwards compatibility. 2. Tests for multivariate and univariate usage of `SumTo1` and `Ordered` transformations were added.
@TimOliverMaier thanks so much for the fix (and the going back and forth). Is this ready to merge on your end, or did you want to do anything else? |
@ricardoV94 my pleasure :) . Yes, I am finished here. |
Co-authored-by: Purna Chandra Mansingh <purnachandramansingh135@gmail.com>
This PR is the continuation of @purna135 's PR #5660 addressing issue #5659 (ordering transformation fails for dim>1).
Short summary:
The initial change of the dimensionality of the jacobian determinant:
This led to issues with multivariate distributions (as pointed out by @Sayam753 here).
Based on the suggestions of @ricardoV94, I added a simple case inside the
log_jac_det
method ofordered
andsumto1
transform like this:While fixing the mentioned problem with multivariate distributions, two problems remain:
TestElementWiseLogP
intest_transform.py
failsdue to the inconsistent dimensionality of the jacobian determinant among the possible transformations.
I also ran all other the tests in the
distribution
subfolder locally. Here many tests are also failing in the main branch for me.I am unsure here if any of the failing tests are caused by this PR's additions.
While experimenting with the multivariate distributions I realized that ordering of a
MvNormal
fails in main and still fails inthis PR. In both branches it fails with an
ValueError
:"array must not contain infs or NaNs\nApply node that caused the error: SolveTriangular{lower=True, trans=0, unit_diagonal=False, check_finite=True}(TensorConstant{[[1. 0. 0...0. 0. 1.]]}, SpecifyShape.0)\nToposort index: 12\nInputs types: [TensorType(float64, (4, 4)), TensorType(float64, (4, 1))]\nInputs shapes: [(4, 4), (4, 1)]\nInputs strides: [(8, 32), (8, 8)]\nInputs values: ['not shown', array([[0.80230155],\n [ nan],\n [ nan],\n [ nan]])]\nOutputs clients: [[InplaceDimShuffle{1,0}(SolveTriangular{lower=True, trans=0, unit_diagonal=False, check_finite=True}.0)]]\n\nBacktrace when the node is created (use Aesara flag traceback__limit=N to make it longer):\n File "/home/tim/miniconda3/envs/pymc_dev/lib/python3.10/site-packages/aeppl/joint_logprob.py", line 151, in factorized_joint_logprob\n q_logprob_vars = _logprob(\n File "/home/tim/miniconda3/envs/pymc_dev/lib/python3.10/functools.py", line 889, in wrapper\n return dispatch(args[0].class)(*args, **kw)\n File "/home/tim/miniconda3/envs/pymc_dev/lib/python3.10/site-packages/aeppl/transforms.py", line 611, in transformed_logprob\n logprob = _logprob(rv_op, values, *inputs, **kwargs)\n File "/home/tim/miniconda3/envs/pymc_dev/lib/python3.10/functools.py", line 889, in wrapper\n return dispatch(args[0].class)(*args, **kw)\n File "/home/tim/Workspaces/pymc/pymc/distributions/distribution.py", line 123, in logp\n return class_logp(value, *dist_params)\n File "/home/tim/Workspaces/pymc/pymc/distributions/multivariate.py", line 288, in logp\n quaddist, logdet, ok = quaddist_parse(value, mu, cov)\n File "/home/tim/Workspaces/pymc/pymc/distributions/multivariate.py", line 156, in quaddist_parse\n dist, logdet, ok = quaddist_chol(delta, chol_cov)\n File "/home/tim/Workspaces/pymc/pymc/distributions/multivariate.py", line 173, in quaddist_chol\n delta_trans = solve_lower(chol_cov, delta.T).T\n\nHINT: Use the Aesara flag
exception_verbosity=high
for a debug print-out and storage map footprint of this Apply node."For reproduction, see code below.
I want to share my progress here as draft to make collaboration possible ;) .
Cheers!
Checklist
Bugfixes / New features