Understanding 1D Tracking Tutorial

I am new to the pyro community, though have a lot of experience with multitarget tracking. I am trying to understand the basic pyro tutorial on 1D tracking using sinusoidal movement:

https://pyro.ai/examples/tracking_1d.html

Here are my questions:

  1. In the get_dynamics function, why is the time variable divided by 4?
    • Note- I thought this might be to keep the time values between [0,1], but when I tried running it with num_frames = 10, and change the 4 to 9 (num_frames - 1), I get an error at the following line saying the parameter loc has invalid values:

real_dist = dist.Normal(positions.unsqueeze(-2), args.emission_noise_scale)

  1. What does the following line in the model mean:

is_spurious = (assign == args.max_num_objects)

  1. So far when running the code as is I have been able to run with num_frames as 1-5 and 8-11 fine, but 6,7, and 12-48 (as high as I tested) seemed to return an error on the line:
        pyro.sample("is_real",
                    dist.Bernoulli(args.expected_num_objects / num_observed),
                    obs=is_real.float())


Is anyone familiar with the constraints that might cause this?

Note- I was able to work through debugging this with pdb, and figured I’d mention in case it helps anyone else. It seems that sometimes the value sent into the Bernoulli distribution can be > 1. This happens because that is being set by the expected number of objects/number of observed objects. They are computing the number of observed objects as the sum at any time of the number of objects that exist based on a Bernoulli distribution of whether they were detected or “emitted”, plus the number of “spurious” targets or sensor returns that are not actually targets. So, if the actual target was not “emitted” and there are no spurious targets, this number will be less than the expected number of objects. I’m not sure why it worked for some frames and didn’t for others other than it was just by chance.

  1. If I wanted to change the sinusoidal movement to linear movement, would I just change the get_dynamics function to something like this, and would I still use the “states” variable the same way with the matrix multiplication?:

def get_dynamics(num_frames):
x = torch.arange(float(num_frames))
y = torch.arange(float(num_frames))
transposed = torch.stack([x, y], -1)
return transposed

Thank you, I appreciate any help or insight to any of these questions!