-
-
Notifications
You must be signed in to change notification settings - Fork 52
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
Add DiscreteMarkovChain
distribution
#100
Conversation
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
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 looks amazing 🤩 Left some comments below that hopefully you find helpful.
For the sampler, I think there's a way to make it so your distribution goes with Categorical sampler by default. |
validate `P` in `logp` via `check_parameters` Create `test_discrete_markov_chain.py`
remove shape checks on x0 add `init_dist` argument add support for `dtype` kwarg
`dims` argument now works Add tests associated with `dims`
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.
Great progress. Some comments/requests below.
Would be so cool to implement logp marginalization of these variables in a future PR! Should be as simple as putting the right DiscreteMarginalizedRV inside Scan? Should come out the same as the forward algorithm.
Another future improvement would be multiple lag dependencies?
Anyway I am getting carried away, this is already very exciting!
pymc_experimental/tests/distributions/test_discrete_markov_chain.py
Outdated
Show resolved
Hide resolved
pymc_experimental/tests/distributions/test_discrete_markov_chain.py
Outdated
Show resolved
Hide resolved
Speaking of bad APIs... Here is a solution? Like the test added here you can override the default list of step methods: pymc-devs/pymc@2dd4c8c You could add a subclass of the categorical metropolis sampler that assigns ideal competence to this variable. We should definitely refactor that approach, perhaps with dispatching, but for now that is the step assignment API for external libraries... |
I was thinking if I could subclass from Categorical then it would be automatically assigned correctly, but I got some errors doing this. |
re: multiple lag dependencies, I think that would be nice as well and should be easy enough to add. |
Marginalizing HMMs usually sample much better in my experience. We would need to increase the marginalization to support it, though. Right now it only works for vanilla discrete variables, not scans or this specific wrapped scan op either. |
Remove unnecessary type handling on distributions.
Add `initval='prior'` as a default argument to `__new__`
One of the scan re-writes is throw an error now, but only if I compile the model outside of a model context (e.g. with ERROR (pytensor.graph.rewriting.basic): Rewrite failure due to: save_mem_new_scan
ERROR (pytensor.graph.rewriting.basic): node: for{cpu,scan_fn}(TensorConstant{(1,) of 9}, IncSubtensor{Set;:int64:}.0, RandomGeneratorSharedVariable(<Generator(PCG64) at 0x151E8EE40>), Softmax{axis=1}.0)
ERROR (pytensor.graph.rewriting.basic): TRACEBACK:
ERROR (pytensor.graph.rewriting.basic): Traceback (most recent call last):
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/graph/rewriting/basic.py", line 1933, in process_node
replacements = node_rewriter.transform(fgraph, node)
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/graph/rewriting/basic.py", line 1092, in transform
return self.fn(fgraph, node)
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/scan/rewriting.py", line 1628, in save_mem_new_scan
subtens = Subtensor(nw_slice)
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/tensor/subtensor.py", line 692, in __init__
self.idx_list = tuple(map(index_vars_to_types, idx_list))
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/tensor/subtensor.py", line 592, in index_vars_to_types
slice_a = index_vars_to_types(a, False)
File "/Users/jessegrabowski/mambaforge/envs/pymc_dev/lib/python3.9/site-packages/pytensor/tensor/subtensor.py", line 613, in index_vars_to_types
raise AdvancedIndexingError("Invalid index type or slice for Subtensor")
pytensor.tensor.exceptions.AdvancedIndexingError: Invalid index type or slice for Subtensor EDIT:: This was caused by |
Add test for random draws Re-run notebook
I marked it as ready for review, although the problem of sampler assignment still isn't solved. If it was OK'd for the main PyMC code base, I'd just add the distribution to the list of competencies for Another small issue is that Also still need to add support for multiple lags. |
That need not be a blocker unless you want it to |
I think I addressed pretty much everything. I changed an import in |
@jessegrabowski I am happy code and test-wise. Do you need help fixing the conflicts and rebasing or are you up to it? We can merge aftewards |
The title of the NB needs to be updated. |
The NB was a bit of an afterthought, just to show everyone the distribution works as intended. I could doll it up a bit and make a separate PR into |
@jessegrabowski I updated my comment after I saw that this was pymc-experimental, not pymc. So I think a NB here is a good idea, and you can later doll it up for pymc-examples. But the title needs to be fixed. |
The math from the docstrings doesn't seem to render correctly: https://pymcio--100.org.readthedocs.build/projects/experimental/en/100/generated/pymc_experimental.distributions.timeseries.DiscreteMarkovChain.html#pymc_experimental.distributions.timeseries.DiscreteMarkovChain |
…ults to statsmodels
Use short import name in `api_reference.rst` Co-authored-by: Ricardo Vieira <[email protected]>
DiscreteMarkovChain
distribution
Add a distribution for discrete-state Markov chains. Support for deterministic and random initial conditions. Motivated by two recent threads on the discourse asking about this type of model: here and here. This work is derivative of the work presented by @junpenglao and @ricardoV94 in those threads.
Still a lot of work to do so I'm marking this as a draft. In no particular order:
.eval()
methods in several places to validate inputs, this strikes me as bad but I didn't know what else to do.dims
currently breaks the modelsteps
argument, but it seems more natural if it were instead set by thesize
ordims
argument (this is related to why dims breaks the model i think)pm.sample
automatically assigns the markov chain RV topm.Metropolis
, don't know how to direct it to BinaryMetropolis or CategoricalMetropolis, depending on the size of the state space.steps
argument. I internally subtract 1 to account for the fact thatx0
will be appended to the scan -- otherwise the resulting chain is length steps + 1, which I don't think will match the user expectation. It gives the right answer but it doesn't feel very clean.