-
Notifications
You must be signed in to change notification settings - Fork 260
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
Prior support for "consumed" dims #841
Comments
This should make some sense. In the core case (without batch dims), you may have a vector of 100 probs that are consumed to generate a single scalar (a number between 0-99). You could ask to draw a batch of length 100 (dim probs) of these numbers, but that in general would be strange. |
Yes, totally. Makes sense. Let me change up the scenarios then in the initial description. EDIT: The first message has been modified |
Some scenarios that should work: # Broadcasting support
p = Prior("Dirichlet", a=np.ones((2, 5)), dims=("geo", "prob"))
y = Prior("Categorical", p=p, dims=("geo", "trial")) The information from # Can provide a user warning
p = Prior("Dirichlet", a=[1, 1, 1]) |
Is that example with the dims "geo", "trial" in that order in purpose? You would need to transpose them for it to work since it must broadcast to the left. To be clear when defining a Categorical distribution with p with dims (geo, probs), you could have dims (geo,), that is a single vector, or (trial, geo), which would be a matrix of observations, or anything with batch dims to the left of geo such as (year, .. , trial, geo) |
Yup, the order is on purpose in order to support the broadcasting even under scenario of "consumed" dims. Have code below to get distributions that might need some additional investigation from pytensor.tensor.random.basic import RandomVariable
import pymc as pm
from pymc.distributions.distribution import DistributionMeta
lookup = {}
for name in dir(pm):
obj = getattr(pm, name)
if isinstance(obj, DistributionMeta):
lookup[name] = obj
def needs_investigation(
rv_op,
) -> bool:
"""Non scalar to scalar"""
return any(ndims != 0 for ndims in rv_op.ndims_params) or rv_op.ndim_supp != 0
rv_op_lookup = {}
for name, value in lookup.items():
rv_op = value.rv_op
# Another case to investigate
if not isinstance(rv_op, RandomVariable):
continue
if not needs_investigation(rv_op):
continue
rv_op_lookup[name] = rv_op Results in:
Currently implementation does support many Distributions already (any supported for PyMC-Marketing previously). |
Yup, sounds like you're on it. Yeah the rightmost dims are the "core" ones. One day when we implement dims in PyTensor we'll probably need extra kwargs for the user to tell us what dims should be used to core case. Like a Categorical may need to ve written like Because with named dims order loses any meaning and so we can't rely on it to disambiguate what's core from what is batch. In this case we could probably introspect the dims of p and find out which one is there that is not "geo" or "trial". But like we don't require size to always be provided we may not want to require "dims" to be provided in which case we infer it from the dims of the parameters. This is all about future PyTensor API, not about the work here in pymc-marketing. Just using this as an excuse to think about it. I don't know if you want to go that route here of asking which ones are the core dims or rely on the missing dims in the output to find out which one is the "probs". I'm wondering about matrix core inputs, like cov. In some cases order may matter, so even if you can reason about which dims are the core you may still need to know which one goes first. cov is not a problem because it has to be symmetric but that need not always be the case with matrix inputs. The other tricky thing are multiple parametrizations. Like user may define MvNormal with the cholesky which is not an (m, m) matrix. Under the hood PyMC will convert it to a covariance and the Op signature is always correct. But here you're acting before PyMC does that conversion when you're trying to Dimshuffle the dims for then user. Those edge cases is when we start desiring PyTensor to natively handle dims |
Some things to note:
As for the problem of consumed dims under the |
Duplicate dims are not allowed anywhere. Even if it's square they must have different names |
Right but that will fail when they are specified and/or are not aligned according to the non-dim semantics of PyMC, right? |
For your pragmatic question, I don't know. I suggest trying what feels better and see how it goes. |
Some distributions will likely not work because of the check for parent dims being a superset of the child. For instance,
This could be relaxed based on some logic from the rv_op. i.e.
pm.Categorical.rv_op
hasndim_supp=0
andndims_params=(1,)
or by parsing the numpy-like signaturePrevious (incorrect) examples
EDIT: The following are wrong because categorical has signature of (p)->()
The transpose doesn't work as well
Ref: pymc-devs/pymc#7416 (reply in thread)
The text was updated successfully, but these errors were encountered: