Skip to content

Make metropolis elemwise updates independent of each other #6678

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

Merged
merged 1 commit into from
Apr 19, 2023

Conversation

ricardoV94
Copy link
Member

@ricardoV94 ricardoV94 commented Apr 17, 2023

Not updating q0 after each elemwise update rendered subsequent proposals dependent on the previous ones.

This issue was revealed when testing the GeneralizedPoisson introduced in pymc-devs/pymc-extras#143


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

@ricardoV94 ricardoV94 force-pushed the fix_batched_metropolis branch from c693453 to c785d01 Compare April 17, 2023 14:58
@ricardoV94 ricardoV94 changed the title Make metropolis elemwise update independent of other proposals in the same step Make metropolis elemwise updates independent of each other Apr 17, 2023
Not updating q0 after each elemwise update rendered subsequent proposals dependent on the previous ones.
@ricardoV94 ricardoV94 force-pushed the fix_batched_metropolis branch from c785d01 to 9a1014e Compare April 17, 2023 15:00
Comment on lines +130 to +131
np.testing.assert_allclose(trace["x"].mean(("draw", "chain")), mu, rtol=0.1)
np.testing.assert_allclose(trace["x"].var(("draw", "chain")), mu, rtol=0.2)
Copy link
Member Author

@ricardoV94 ricardoV94 Apr 17, 2023

Choose a reason for hiding this comment

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

The relative error was ~2x worse before the changes

@codecov
Copy link

codecov bot commented Apr 17, 2023

Codecov Report

Merging #6678 (9a1014e) into main (1ed4475) will decrease coverage by 11.71%.
The diff coverage is 100.00%.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #6678       +/-   ##
===========================================
- Coverage   91.99%   80.28%   -11.71%     
===========================================
  Files          94       94               
  Lines       15944    15945        +1     
===========================================
- Hits        14667    12801     -1866     
- Misses       1277     3144     +1867     
Impacted Files Coverage Δ
pymc/step_methods/metropolis.py 58.08% <100.00%> (-28.49%) ⬇️

... and 45 files with indirect coverage changes

@ricardoV94
Copy link
Member Author

ricardoV94 commented Apr 17, 2023

@bwengals you rejected the null in my PR! https://github.com/pymc-devs/pymc/actions/runs/4722680748/jobs/8377620494?pr=6678

Can I add a seed?

@bwengals
Copy link
Contributor

Maybe NHST works, I guess this should happen 1/100 times.

Yes absolutely, I should have done that.

q_temp = q0d.copy()
# Shuffle order of updates (probably we don't need to do this in every step)
np.random.shuffle(self.enum_dims)
for i in self.enum_dims:
q_temp[i] = q[i]
accept_rate_i = self.delta_logp(q_temp, q0d)
q_temp_, accepted_i = metrop_select(accept_rate_i, q_temp, q0d)
q_temp[i] = q_temp_[i]
q_temp[i] = q0d[i] = q_temp_[i]
Copy link
Member

Choose a reason for hiding this comment

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

If I understand correctly, this basically means that you are performing Gibbs updates at each batch dimension iteratively. So if you have a vector variable $\vec{v}$ and a proposal vector $\vec{u}$, you will first see if you accept or reject the vector $(u_{0}, v_{1}, ..., v_{n})$ versus $\vec{v}$. If you accept this proposal, the next proposal will be $(u_{0}, u_{1}, v_{2}, ..., v_{n})$ versus $(u_{0}, v_{1}, ..., v_{n})$, and so on. If I understand correctly, the past behavior was doing the iterative element wise updates but always compared against $\vec{v}$.
If I my understanding is correct, then this looks ok to me

Copy link
Member Author

@ricardoV94 ricardoV94 Apr 18, 2023

Choose a reason for hiding this comment

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

Yes that's exactly it!

Only thing is we don't distinguish between core and batched dimensions, everything is unrolled as one long vector.

We don't perform elemwise_update if there is any multivariate discrete variable in the sampler, as those are usually impossible to update one value at a time (e.g., Multinomial).

For multivariate continuous, we implicitly assume they have a transform that makes each core dim more or less independent (or it's naturally so without a transform).

@ricardoV94
Copy link
Member Author

ricardoV94 commented Apr 18, 2023

@bwengals I tried to seed the test, and the first seed I gave it also failed, so there could be something wrong going on. I'll push the seeded test in a separate PR so you can have a look.

@bwengals
Copy link
Contributor

Ah ok thanks @ricardoV94, I commented there before seeing this. I'll try running it locally and see

@ricardoV94 ricardoV94 merged commit f2bb88b into pymc-devs:main Apr 19, 2023
@ricardoV94 ricardoV94 deleted the fix_batched_metropolis branch June 5, 2023 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants