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

Add particle filter exercise notebook #33

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Conversation

lucianopaz
Copy link

@lucianopaz lucianopaz commented Feb 5, 2025

This tries to add a particle filter as per my comment from #24

I ran into a bunch of problems though.

  1. I can't seem to be able to use RandomStream objects inside of scan, so that makes it hard for me to use rng.some_method as I would like to have been able to do.
  2. I can't make scan behave as a while loop, which is what I really need to happen in the systematic_resample
  3. There are some times in which closure python variables would have been nicer to use than the pytensor counterparts, but I couldn't get those to work properly.
  4. The systematic_resample loop is a mess. I need to update some indices, but I'm clearly botching the indexing or the sharing or the updates. Any guidance there would be great.
  5. Since I haven't gotten the filter to work, I can't guarantee that the plotting code at the end is correct.

TODO:

  • Setup
  • emphasize that instead of normal_logpdf you could have an arbitrary probability model (including a PyMC model one!)
  • Convert into exercise
  • Start with simpler dumb multinomial resampling
  • Get rid of outer scan, and just call update function in a loop (make it interactive so we can see the robot moving over-time and the function updating online)

Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@lucianopaz
Copy link
Author

lucianopaz commented Feb 5, 2025

As a side note. The code copies a SIR particle filter from here, and the resampling algorithm is copied from here.

One last thing. I would really love for the particle filter to work on some kind of streaming data, but I have no idea how to get that to work in pytensor.

@lucianopaz
Copy link
Author

I got it work now!
image

The particle filter tracks the position of a robot that has noisy sensors and noisy controls. I think that it can still be greatly improved. One thing that I think can be better is to ditch the RandomStream and send a shared random generator that can be provided to the random variable creators. Another thing that would be nice, would be to get the particle replacement operation scan to not use what I feel are mostly patches around shared variables and python integers.

@@ -0,0 +1,391 @@
{
Copy link
Member

@ricardoV94 ricardoV94 Feb 6, 2025

Choose a reason for hiding this comment

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

Line #68.        i = pytensor.shared(np.array([0]))

why are you creating shared variables for i, j? Sounds like they should be recurrent outputs that get updated?

In general the only time you need shared variables is to handle RNGs in Scan (scan limitation) or to have implicit inputs / share inputs across functions


Reply via ReviewNB

@@ -0,0 +1,391 @@
{
Copy link
Member

@ricardoV94 ricardoV94 Feb 6, 2025

Choose a reason for hiding this comment

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

Line #142.        [particles, weights], _ = pytensor.scan(

if you have updates in the inner functions (which you will have with rng.foo(), plus your other use of updates for indices (which I don't think you want), you need to forward the updates to the outmost pytensor function, otherwise they won't work


Reply via ReviewNB

@ricardoV94
Copy link
Member

  • I can't seem to be able to use RandomStream objects inside of scan, so that makes it hard for me to use rng.some_method as I would like to have been able to do.

What do you mean, they should definitely work. Maybe you defining custom updates is messing PyTensor identification of the default randomstream updates. You do need to forward all updates from nested functions to the final compiled pytensor function.

  • I can't make scan behave as a while loop, which is what I really need to happen in the systematic_resample

Why can't you? Perhaps because of the odd use of shared variables?

  • There are some times in which closure python variables would have been nicer to use than the pytensor counterparts, but I couldn't get those to work properly.

What do you mean?

  • The systematic_resample loop is a mess. I need to update some indices, but I'm clearly botching the indexing or the sharing or the updates. Any guidance there would be great.

indices should be regular non shared variables that are recursed (so parts of outputs_info)

@ricardoV94
Copy link
Member

Bigger picture, how do you suggest we turn this into an exercise notebook? One concern is just to give enough intro content and break it in incremental parts, that should be a no biggie.

The other is the use of Scan which is a bit advanced, and I wasn't sure I wanted to touch in the workshop. We will need to give a bit of scaffolding for it. Specially with the use of rngs inside which requires explicitly handling updates.

@ricardoV94
Copy link
Member

One last thing. I would really love for the particle filter to work on some kind of streaming data, but I have no idea how to get that to work in pytensor.

You just update the data in subsequent calls to pytensor, or you mean something more fancy?

@@ -0,0 +1,391 @@
{
Copy link
Member

@ricardoV94 ricardoV94 Feb 6, 2025

Choose a reason for hiding this comment

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

Line #3.        particles = rng.normal(loc=mean, scale=std, size=(n_particles, 3))

normal will do the implicit broadcast of loc and scale


Reply via ReviewNB

@@ -0,0 +1,391 @@
{
Copy link
Member

@ricardoV94 ricardoV94 Feb 6, 2025

Choose a reason for hiding this comment

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

Line #16.        particles = pt.set_subtensor(particles[:, 2], particles[:, 2] % (2 * np.pi))

what is this line doing?


Reply via ReviewNB

@@ -0,0 +1,391 @@
{
Copy link
Member

@ricardoV94 ricardoV94 Feb 6, 2025

Choose a reason for hiding this comment

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

Line #3.    func = pytensor.function([], [estimate_mean, estimate_std, particles, log_weights])

this will need some updates=updates that are collected (for the RNGs in the scan). IIRC even with the default updates of RandomStreams you need them manually for the scan


Reply via ReviewNB

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

Successfully merging this pull request may close these issues.

2 participants