Implementation:Pyro ppl Pyro InclinedPlane
| Property | Value |
|---|---|
| Implementation Type | Pattern Doc |
| Source File | examples/inclined_plane.py
|
| Module | examples |
| Pyro Features | pyro.sample, Importance sampling, EmpiricalMarginal, simulator inversion, Uniform/Normal distributions
|
| Pattern | Bayesian inference to invert a physics simulator |
Overview
This file demonstrates a compelling use case of probabilistic programming: inverting a physics simulator using Bayesian inference. The scenario is a student (Samantha) who observes a box sliding down an inclined plane 20 times and wants to infer the coefficient of friction (mu) between the box and the plane.
The approach:
- A deterministic simulator computes descent time given friction coefficient via numerical integration of equations of motion
- The model places a Uniform(0, 1) prior on mu, runs the simulator, and adds Gaussian measurement noise
- Importance sampling is used to infer the posterior distribution of mu given the observed descent times
This example is notable because the simulator contains a while loop with variable iteration count, demonstrating Pyro's ability to handle complex, non-differentiable program structures.
Code Reference
def simulate(mu, length=2.0, phi=np.pi / 6.0, dt=0.005, noise_sigma=None):
T = torch.zeros(())
velocity = torch.zeros(())
displacement = torch.zeros(())
acceleration = torch.tensor(little_g * np.sin(phi)) - \
torch.tensor(little_g * np.cos(phi)) * mu
while displacement.numpy() < length:
displacement += velocity * dt
velocity += acceleration * dt
T += dt
if noise_sigma is None:
return T
else:
return T + noise_sigma * torch.randn(())
def model(observed_data):
mu_prior = Uniform(0.0, 1.0)
mu = pyro.sample("mu", mu_prior)
def observe_T(T_obs, obs_name):
T_simulated = simulate(mu)
T_obs_dist = Normal(T_simulated, torch.tensor(time_measurement_sigma))
pyro.sample(obs_name, T_obs_dist, obs=T_obs)
for i, T_obs in enumerate(observed_data):
observe_T(T_obs, "obs_%d" % i)
return mu
I/O Contract
| Parameter | Type | Description |
|---|---|---|
observed_data |
torch.Tensor |
Tensor of N observed descent times (seconds) |
-n / --num-samples |
int |
Number of importance samples (default: 500) |
Physical parameters:
- Plane length: 2 meters
- Incline angle: 30 degrees (pi/6)
- Measurement noise: 20 milliseconds
- True mu: 0.12
Output:
- Posterior mean and standard deviation of friction coefficient mu
- Comparison of observed, simulated, and analytic descent times
Usage Examples
from pyro.infer import Importance, EmpiricalMarginal
# Run importance sampling
importance = Importance(model, guide=None, num_samples=500)
emp_marginal = EmpiricalMarginal(importance.run(observed_data))
# Extract posterior statistics
posterior_mean = emp_marginal.mean
posterior_std = emp_marginal.variance.sqrt()
# Run from command line
# python inclined_plane.py -n 1000
Related Pages
- Pyro_ppl_Pyro_MiniPyro_Example - Simple inference example with MiniPyro