-
-
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
Make MvStudentT distribution v4 compatible #4731
Conversation
Looking at the failed pipeline, it seems like it uses cached I am using |
Why not use the newer scipy version? |
I think it may lead to changing the requirements file and our pipeline cache. If I already had If using newer scipy versions is feasible with other dependencies' requirements, I am happy to make the required changes :) |
>>> import numpy as np
>>> import scipy
>>> scipy.__version__
'1.6.3'
>>> from scipy.stats import multivariate_normal, multivariate_t
>>> mean, cov = np.zeros(2), np.eye(2)
>>> multivariate_normal.rvs(mean=mean, cov=cov, size=None).shape
(2,)
>>> multivariate_t.rvs(loc=mean, shape=cov, size=None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 4148, in rvs
samples = loc + z / np.sqrt(x)[:, None]
IndexError: invalid index to scalar variable.
>>> multivariate_normal.rvs(mean=mean, cov=cov, size=(10, 3)).shape
(10, 3, 2)
>>> multivariate_t.rvs(loc=mean, shape=cov, size=(10, 3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 4148, in rvs
samples = loc + z / np.sqrt(x)[:, None]
ValueError: operands could not be broadcast together with shapes (10,3,2) (10,1,3)
>>> multivariate_t.rvs(loc=mean, shape=cov, size=(3))
array([[ 1.54502738, -0.23866557],
[-0.79040924, -1.72035808],
[-0.28060545, -0.69889876]]) This is the reason why many pipelines failed. Now, I want to try out implementing |
I am on latest main branch@ 4de95c3 and trying to understand how new API for shapes work. A small snippet - >>> import pymc3 as pm
You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3
>>> import numpy as np
>>> dist = pm.MvNormal.dist(mu=np.zeros(1), cov=np.eye(3), shape=3)
>>> dist.shape.eval()
array([1]) I am finding it hard to understand why the shape is [1] And some fancy errors during Traceback>>> dist.eval()
Traceback (most recent call last):
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/compile/function/types.py", line 977, in __call__
if output_subset is None
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/graph/op.py", line 495, in rval
r = p(n, [x[0] for x in i], o)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/op.py", line 413, in perform
smpl_val = self.rng_fn(rng, *(args + [size]))
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/basic.py", line 288, in rng_fn
return safe_multivariate_normal(mean, cov, size=size, rng=rng)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/basic.py", line 239, in safe_multivariate_normal
stats.multivariate_normal(mean=mean, cov=cov, allow_singular=True).rvs(
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 369, in __call__
seed=seed)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 744, in __init__
None, mean, cov)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 409, in _process_parameters
cov.shape = (1, 1)
ValueError: cannot reshape array of size 9 into shape (1,1)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/graph/basic.py", line 555, in eval
rval = self._fn_cache[inputs](*args)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/compile/function/types.py", line 993, in __call__
storage_map=getattr(self.fn, "storage_map", None),
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/link/utils.py", line 521, in raise_with_op
raise exc_value.with_traceback(exc_trace)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/compile/function/types.py", line 977, in __call__
if output_subset is None
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/graph/op.py", line 495, in rval
r = p(n, [x[0] for x in i], o)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/op.py", line 413, in perform
smpl_val = self.rng_fn(rng, *(args + [size]))
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/basic.py", line 288, in rng_fn
return safe_multivariate_normal(mean, cov, size=size, rng=rng)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/random/basic.py", line 239, in safe_multivariate_normal
stats.multivariate_normal(mean=mean, cov=cov, allow_singular=True).rvs(
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 369, in __call__
seed=seed)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 744, in __init__
None, mean, cov)
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/scipy/stats/_multivariate.py", line 409, in _process_parameters
cov.shape = (1, 1)
ValueError: cannot reshape array of size 9 into shape (1,1)
Apply node that caused the error: multivariate_normal_rv(RandomStateSharedVariable(<RandomState(MT19937) at 0x7FB57E736380>), TensorConstant{[]}, TensorConstant{11}, TensorConstant{(1,) of 0.0}, TensorConstant{[[1. 0. 0...0. 0. 1.]]})
Toposort index: 0
Inputs types: [RandomStateType, TensorType(int64, vector), TensorType(int64, scalar), TensorType(float64, (True,)), TensorType(float64, matrix)]
Inputs shapes: ['No shapes', (0,), (), (1,), (3, 3)]
Inputs strides: ['No strides', (8,), (), (8,), (24, 8)]
Inputs values: [RandomState(MT19937) at 0x7FB57E736380, array([], dtype=int64), array(11), array([0.]), 'not shown']
Outputs clients: [[], ['output']]
Backtrace when the node is created (use Aesara flag traceback__limit=N to make it longer):
File "<stdin>", line 1, in <module>
File "/Users/sayam/Desktop/pymc/pymc3/pymc3/distributions/multivariate.py", line 226, in dist
return super().dist([mu, cov], **kwargs)
File "/Users/sayam/Desktop/pymc/pymc3/pymc3/distributions/distribution.py", line 285, in dist
rv_out = cls.rv_op(*dist_params, size=create_size, **kwargs)
HINT: Use the Aesara flag `exception_verbosity=high` for a debug print-out and storage map footprint of this Apply node. |
This parametrization is incoherent. However, this is a scenario that motivates automatically adding a Your >>> import aesara
>>> aesara.__version__
'2.0.8'
>>> import aesara.tensor as at
>>> import aesara.tensor.random.basic as ar
>>> import numpy as np
>>> ar.multivariate_normal(mean=np.zeros(1), cov=np.eye(3)).shape.eval()
array([1], dtype=int64) The >>> ar.multivariate_normal(mean=[0,0,0], cov=np.eye(3)).shape.eval()
array([3], dtype=int64) One could argue that the Aesara implementation shouldn't have downcasted |
I guess this is due to rep_param_idx parameter used to infer distribution shape in aesara.
How hard would it be to loop over all distribution parameters to infer distribution shape, instead of relying on one parameter? |
This has nothing to do with "including the support dimensions"; the actual issue is that the parameters specify conflicting lengths/sizes across the relevant dimensions. Your follow-up example isn't including anything extra, it's only fixing the conflicting dimensions by making the length of the mean match the lengths of the covariance dimensions. Consider what I think a lot of confusion regarding
What "downcasting"? The dtype looks correct. The result itself appears to be due to a missing check in the shape inference. That's all. If you want to understand why, start by computing the result itself, and not just its shape. You'll see the underlying error that the shape inference logic missed: >>> ar.multivariate_normal(mean=np.zeros(1), cov=np.eye(3)).eval()
...
ValueError: cannot reshape array of size 9 into shape (1,1) This is the same error that appears in the original problem. In other words, the As usual, it's always good to see what the underlying NumPy function would do, since these >>> np.random.multivariate_normal(mean=np.zeros(1), cov=np.eye(3))
ValueError: mean and cov must have same length As expected, NumPy fails as well; however, it gives a much better error message. @Sayam753, feel free to open an issue in Aesara to add that missing check to the shape inference steps; otherwise, your example specifies a mathematically invalid distribution, because the mean and covariance are incompatible. Use |
IIRC I once had a version where
Sorry, I mean down_sizing_. (The bug in the shape inference.)
Please excuse that my language wasn't exactly on point. The phrase "including the support dimensions" is more from the perspective of wanting to imply more dimensions from the RV parameters, which wasn't the intention in the first place. Anyways. @Sayam753 let us know if you need assistance with the remaining ToDo for this PR. |
Thanks @michaelosthege and @brandonwillard for clearing the doubts above. A little interesting behaviour of >>> import numpy as np
>>> import pymc3 as pm
You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3
>>> mu, cov = np.ones(1), np.eye(3)
>>> pm.MvNormal.logp(value=np.random.randn(20, 3), mu=mu, cov=cov).eval()
array([ -3.67340545, -7.19130309, -3.23923742, -5.15713797,
-17.29246223, -10.32441825, -4.2939353 , -5.66928884,
-4.05121295, -4.58167586, -5.50445437, -4.20362596,
-6.12579132, -8.63937152, -4.656641 , -9.63474273,
-4.35076017, -3.33788195, -3.50893476, -4.77016247]) |
Calling the |
I am trying to understand how My question is - why cannot I use >>> import numpy as np
>>> import aesara.tensor as at
>>> import pymc3 as pm
You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3
>>> mu, cov = np.ones(3), np.eye(3)
>>> dist = pm.MvNormal.dist(mu=mu, cov=cov)
>>> X = np.random.normal(size=(20, 3))
>>> X = at.as_tensor(X)
>>> dist.type, dist.dtype, dist.ndim, dist.shape.eval()
(TensorType(float64, vector), 'float64', 1, array([3]))
>>> X.type, X.dtype, X.ndim, X.shape.eval()
(TensorType(float64, matrix), 'float64', 2, array([20, 3]))
>>> dist.type.filter_variable(X)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/sayam/miniconda3/envs/pymc_dev/lib/python3.7/site-packages/aesara/tensor/type.py", line 261, in filter_variable
f"Cannot convert Type {other.type} "
TypeError: Cannot convert Type TensorType(float64, matrix) (of Variable TensorConstant{[[ 0.30673..15832267]]}) into Type TensorType(float64, vector). You can try to manually convert TensorConstant{[[ 0.30673..15832267]]} into a TensorType(float64, vector). |
The pipelines are green. So, the PR is ready for another round of review. |
In the meantime, were there no other tests marked as xfail because they relied on this distribution? |
I think all the MvStudentT related tests in Thinking more about the test cases, |
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.
I left some minor suggestions. Otherwise it looks good to me. Great work :)
Co-authored-by: Ricardo <[email protected]>
Co-authored-by: Ricardo <[email protected]>
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.
LGTM!
Thanks @Sayam753, great work. |
Thanks @ricardoV94 for a thorough review. I do want to follow up for a better fix for pymc3/tests/test_distributions.py::TestBugfixes::test_issue_3051 and will open a related issue :) |
Thank your for opening a PR!
Depending on what your PR does, here are a few things you might want to address in the description:
Making MvStudentT distribution v4 compatible as per Port remaining distributions to v4 #4686
Follows the instructions as per this Port remaining distributions to v4 #4686 (comment)
rng_fn
code to use a similar implementation as in master.