Skip to content
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

Do not consider dims without coords volatile if length has not changed #7381

Merged

Conversation

JasonTam
Copy link
Contributor

@JasonTam JasonTam commented Jun 21, 2024

Description

Allow coords defined by length only (no values) to be considered constant_coords if the new length matches.

Related Issue

Checklist

Type of change

  • New feature / enhancement
  • Bug fix
  • Documentation
  • Maintenance
  • Other (please specify):

📚 Documentation preview 📚: https://pymc--7381.org.readthedocs.build/en/7381/

@JasonTam
Copy link
Contributor Author

The main part I feel uneasy about is having to call current_length.eval() since the length stored in model.dim_lengths is a pt shared variable

Comment on lines 799 to 800
if hasattr(current_length, 'eval'):
current_length = current_length.eval()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can only be a shared variable in which case you can retrieve with get_value(), or a Constant in which case you can retrieve with .data That should be much more efficient than eval unless eval does something clever under the hood

@ricardoV94
Copy link
Member

Also we need a test @JasonTam

@ricardoV94 ricardoV94 added the bug label Jun 26, 2024
@ricardoV94 ricardoV94 changed the title Compare coord length if no associated values (for constant_coords) Do not consider dims without coords volatile if length has not changed Jun 26, 2024
@JasonTam
Copy link
Contributor Author

@ricardoV94
I've pulled out the constant coord check logic into its own method in order to test in isolation. As I wasn't sure how to test this against the full sample_posterior_predictive method (or if that's even practical). Also, that method seems to have grown quite large.

Copy link

codecov bot commented Jun 26, 2024

Codecov Report

Attention: Patch coverage is 93.33333% with 1 line in your changes missing coverage. Please review.

Project coverage is 92.18%. Comparing base (f719796) to head (b76087d).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7381      +/-   ##
==========================================
- Coverage   92.18%   92.18%   -0.01%     
==========================================
  Files         103      103              
  Lines       17249    17258       +9     
==========================================
+ Hits        15901    15909       +8     
- Misses       1348     1349       +1     
Files Coverage Δ
pymc/sampling/forward.py 95.72% <93.33%> (-0.28%) ⬇️

@ricardoV94
Copy link
Member

ricardoV94 commented Jun 27, 2024

@JasonTam here is where we test this volatility logic:

class TestCompileForwardSampler:

Can you add something there instead. No need to do actual sampling, just make a scenario where a variable depends on a dim without coords (and then change it's length or not)

@JasonTam
Copy link
Contributor Author

@ricardoV94 I'm not sure how to write the test without actually sampling. In the similar tests under TestCompileForwardSampler, volatile vars are checked from the output of compile_forward_sampling_function. But that function already takes in constant_coords as a parameter.

The new logic of determining constant_coords can either be tested via the new low level function get_constant_coords (as currently written in the PR), or in the method which calls it, sample_posterior_predictive.

Maybe I'm misunderstanding what you mean.

@ricardoV94
Copy link
Member

You're right @JasonTam, I was confused by the fact that the changes in constant data are checked inside the compile_forward_function but the coords are not. I guess this is the case because coords are not part of the graph while SharedVariables are.

ricardoV94
ricardoV94 previously approved these changes Jun 30, 2024
@@ -1669,6 +1670,20 @@ def test_Triangular(
assert prior["target"].shape == (prior_samples, *shape)


def test_get_constant_coords():
with pm.Model() as model:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a more integration-like test like?

Spit-balling, perhaps something like:

with pm.Model() as m:
  m.add_coord("trial", length=3)
  x = pm.Normal("x", shape="trial")
  y = pm.Deterministic("y", x.mean())

# pass dims as well  
idata = az.from_dict("x": [[np.pi, np.pi, np.pi]])

with m:
  pp1 = pm.sample_posterior_predictive(idata, var_names=["y"]).posterior_predictive

assert pp1["y"] == np.pi

with m:
  # change coord length 
  pp2 = pm.sample_posterior_predictive(idata, var_names=["y"]).posterior_predictive

assert pp2["y"] != np.pi

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this look ok? d40fffe

@ricardoV94 ricardoV94 dismissed their stale review June 30, 2024 20:29

requested extra test

).posterior_predictive
assert pp_same_len["y"] == np.pi

# Coord length changed -- `x` is volatile
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to change the dim length in the pymc model and pass exactly the same idata to sample_posterior_predictive as was done in the first call.

Copy link
Member

@ricardoV94 ricardoV94 Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way to update an existing dim is with Model.set_dim()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just got to this now. Implemented in 49bbf8c -- hope I understood you correctly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup you got it!

Co-authored-by: Ricardo Vieira <28983449+ricardoV94@users.noreply.github.com>
@ricardoV94 ricardoV94 merged commit 1c532f8 into pymc-devs:main Jul 7, 2024
22 checks passed
@ricardoV94
Copy link
Member

Thanks @JasonTam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: Using a length-only coord causes it to be volatile
2 participants