This package provides a transparent and easy-to-use framework for solving parameter estimation problems (i.e., inverse problems) primarily via sampling methods in a characteristic two-step approach:
In the first step, the problem at hand is defined in a solver-independent fashion, i.e., without specifying which computational means are supposed to be utilized for finding a solution.
In the second step, the problem definition is handed over to a user-selected solver, that finds a solution to the problem. The currently supported solvers focus on Bayesian methods for posterior sampling.
Some of the features include:
Multiple prior types accepted
Measurement data bookkeeping
Various methods supported
Postprocessing functionalities
You can install it by running pip from the command line:
pip install probeye
More information can be found the Probeye documentation page
Optional 💽
🖱️Right-click and select “Save link as” to download the exercise HERE 👈 so you can work on it locally on your computer
Hint
Steps to follow:
Define ForwardModelBase child class
Define InverseProblem
Add Latent parameters
Add Fixed parameters
Add Experiment
Add Forward model
Add Likelihood model
Solve with emcee
Import necessary libraries¶
# Problem definition
from probeye.definition.inverse_problem import InverseProblem
from probeye.definition.forward_model import ForwardModelBase
from probeye.definition.distribution import Normal
from probeye.definition.sensor import Sensor
from probeye.definition.likelihood_model import GaussianLikelihoodModel
# Inference
from probeye.inference.emcee.solver import EmceeSolver
# Postprocessing
from probeye.postprocessing.sampling_plots import create_posterior_plot
Problem setup¶
# Fixed parameters
I = 1e9 # mm^4
L = 10_000 # mm
Q = 100 # kN
# Measurements
x_meas = 5000 # mm
d_meas = 50 # mm
sigma_meas = 10 # mm
# Prior
E_mean = 60 # GPa
E_std = 20 # GPa
Define forward model¶
## Write your code where the three dots are
def midspan_deflection(E):
return Q * L ** 3 / (48 * E * I)
class BeamModel(ForwardModelBase):
def interface(self):
self.parameters = ...
self.input_sensors = ...
self.output_sensors = ...
def response(self, inp: dict) -> dict:
E = ...
return {...}
Define inverse problem¶
## Write your code where the three dots are
# Instantiate the inverse problem
problem = ...
# Add latent parameters
problem.add_parameter(...)
# Add fixed parameters
problem.add_parameter(...)
# Add measurement data
problem.add_experiment(...)
# Add forward model
problem.add_forward_model(...)
# Add likelihood model
problem.add_likelihood_model(...)
Solve with MCMC¶
## Write your code where the three dots are
emcee_solver = EmceeSolver(...)
inference_data = emcee_solver.run(...)
Plot¶
post_plot_array = create_posterior_plot(
inference_data,
emcee_solver.problem,
kind="kde",
title="Kernel density estimate of the posterior distribution",
)
Complete Code! 📃💻
Here’s the complete code that you would run in your PC:
# Problem definition
from probeye.definition.inverse_problem import InverseProblem
from probeye.definition.forward_model import ForwardModelBase
from probeye.definition.distribution import Normal
from probeye.definition.sensor import Sensor
from probeye.definition.likelihood_model import GaussianLikelihoodModel
# Inference
from probeye.inference.emcee.solver import EmceeSolver
# Postprocessing
from probeye.postprocessing.sampling_plots import create_posterior_plot
# Fixed parameters
I = 1e9 # mm^4
L = 10_000 # mm
Q = 100 # kN
# Measurements
x_meas = 5000 # mm
d_meas = 50 # mm
sigma_meas = 10 # mm
# Prior
E_mean = 60 # GPa
E_std = 20 # GPa
#Define the forward model
def midspan_deflection(E):
return Q * L ** 3 / (48 * E * I)
class BeamModel(ForwardModelBase):
def interface(self):
self.parameters = ["E"]
self.input_sensors = Sensor("x")
self.output_sensors = Sensor("y", std_model="sigma")
def response(self, inp: dict) -> dict:
E = inp["E"]
return {"y": midspan_deflection(E)}
#Define the inverse problem
# Instantiate the inverse problem
problem = InverseProblem("Beam model with one sensor", print_header=False)
# Add latent parameters
problem.add_parameter(
"E",
tex="$E$",
info="Elastic modulus of the beam (GPa)",
prior=Normal(mean=E_mean, std=E_std),
)
# Add fixed parameters
problem.add_parameter(
"sigma",
tex="$\sigma$",
info="Standard deviation of the measurement error (mm)",
value=sigma_meas,
)
# Add measurement data
problem.add_experiment(
name="TestSeries_1",
sensor_data={"x": x_meas, "y": d_meas}
)
# Add forward model
problem.add_forward_model(BeamModel("BeamModel"), experiments="TestSeries_1")
# Add likelihood model
problem.add_likelihood_model(
GaussianLikelihoodModel(experiment_name="TestSeries_1", model_error="additive")
)
#solve with mcmc
emcee_solver = EmceeSolver(problem, show_progress=True)
inference_data = emcee_solver.run(n_steps=2000, n_initial_steps=2000)
#plot
post_plot_array = create_posterior_plot(
inference_data,
emcee_solver.problem,
kind="kde",
title="Kernel density estimate of the posterior distribution",
)