-
-
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
Improve support for dims
in LKJCholeskyCov
#6828
base: main
Are you sure you want to change the base?
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #6828 +/- ##
===========================================
- Coverage 92.02% 66.82% -25.20%
===========================================
Files 95 95
Lines 16262 16293 +31
===========================================
- Hits 14965 10888 -4077
- Misses 1297 5405 +4108
|
mod.coords[name] = value | ||
mod.dim_lengths[name] = pt.TensorConstant(pt.lscalar, np.array(len(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.
Should probably use model.add_coord/s
and check name doesn't clash with existing one
f_idx = np.triu_indices | ||
|
||
flat_tri_idx = np.arange(n**2, dtype=int).reshape(n, n)[f_idx(n, k=k)] | ||
coord_product = np.fromiter([f"{x}" for x in product(*chol_dims)], dtype="object") |
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'm a bit scared that this could break things when we serialize traces. Can we at least store those in netcdf and zarr?
I wouldn't mind if this just had integer coords either...
coord_product = np.fromiter([f"{x}" for x in product(*chol_dims)], dtype="object") | ||
tri_coords = coord_product[flat_tri_idx].tolist() | ||
|
||
packed_dim_name = f"{name_prefix}_{dims[0]}" |
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 would much prefer a postfix instead of a prefix, especially in this case, because we already use that for the deterministics.
7ecbfbd
to
270cceb
Compare
@classmethod | ||
def _register_new_coords_with_model(cls, name, value): | ||
mod = pm.modelcontext(None) | ||
mod.coords[name] = value | ||
mod.dim_lengths[name] = pt.TensorConstant(pt.lscalar, np.array(len(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.
This must be a method already in Model no?
@@ -1413,14 +1413,32 @@ class LKJCholeskyCov: | |||
""" | |||
|
|||
def __new__(cls, name, eta, n, sd_dist, *, compute_corr=True, store_in_trace=True, **kwargs): | |||
dims = kwargs.pop("dims", None) | |||
|
|||
if dims is not None: |
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.
Not sure this should be done by default. If users want to resize the model they will have to know there is a special dims they also need to update
What is this PR about?
There are currently several pain points when using labeled dims with
LKJCholeskyCov
:LKJCholeskyCov
are not propagated to internally generated deterministics,{name}_std
and{name}_corr
. If a user wants these to be labeled, he has to pass a long dictionary toidata_kwargs
{name}_corr
causes an error inarviz
when computing within-chain variance.This PR tries to correct all three of these. Here is an example model under this PR:
First, I pass two dimensions to
LKJCholeskyCov
-- one for the columns, and one for the rows. This corresponds to the expectation that I am drawing from a matrix-valued random variable.Internally, I take the Cartesian product between these two dims, and use the lower triangle of the resulting matrix to make and register a new coordinate:
packed_tril_{name}
. This is then set as the dims onpacked_chol
.Next, only the upper triangle (excluding the diagonal) of the correlation matrix is stored in a deterministic. Another new coordinate is registered:
corr_{name}
.Finally, the first dim is used to add a labeled dimension to
{name}_std
.This results in the following graph:
Here is the result plotted with
az.plot_trace
:This PR still needs a bit of work, including:
It's also possible that the problem (3) is a problem on the arviz side of things, and should be fixed there instead of here. But in that case, it would still be nice to propagate the matrix dims to the full square correlation matrix.
Because of these points, I'm marking this as a draft PR. But I would still like feedback on the idea of automatically generating coords, or at least on how dim handling can be improved in
LKJCholeskyCov
Checklist
Major / Breaking Changes
New features
LKJCholeskyCov
to generate and register new modelcoords
corresponding to the distributions it internally registersBugfixes
az.plot_trace
, but that might not be something that should be fixed on the PyMC side. See discussion above.Documentation
-None
Maintenance
-None
📚 Documentation preview 📚: https://pymc--6828.org.readthedocs.build/en/6828/