Uncertainty¶
A fit gives one estimate. Two functions say how much it would vary.
ps.ensemble |
ps.bootstrap |
|
|---|---|---|
| For | synthetic studies, where you have the clean signal | measured data |
| Repeats the fit on | the clean data plus fresh noise, one draw per run | the fitted signal plus the residuals, resampled |
| Answers | how the method performs at this noise level | how sure this particular estimate is |
| Starts each fit from | the original starting values | the original estimate |
Both return an Ensemble: the estimate of every run (thetas), their mean, standard
deviation (std) and coefficient of variation (cov, in percent), percentile intervals
(interval(0.95)), and a summary().
Ensemble¶
The procedure of the SNAPE papers' tables: fit noise-free data once, then refit noisy copies.
import numpy as np
import pysnape as ps
t = np.linspace(0.0, 10.0, 301)
clean = ps.Data(fields={"x": np.exp(-0.1 * t) * np.cos(2.0 * t)}, coords={"t": t})
eq = "x_tt + a*x_t + b*x = 0"
base = ps.fit(eq, clean, unknowns={"a": 1.0, "b": 1.0}, multistart=False)
ens = ps.ensemble(base, n=20, noise=5, jobs=2) # draws with seeds 0..19
print(ens.summary(truth={"a": 0.2, "b": 4.01}))
Draw i uses seed seed + i, so an ensemble is repeatable. ensemble warns if the fit's
data does not look noise-free, since it would add noise on top of noise.
Bootstrap¶
For measurements, where no clean signal exists. It keeps the fitted signal, resamples the residuals at the measured points with replacement, and refits:
noisy = clean.add_noise(percent=5, seed=7)
result = ps.fit(eq, noisy, unknowns={"a": 1.0, "b": 1.0}, multistart=False)
boot = ps.bootstrap(result, n=50, jobs=2)
print(boot.interval(0.95))
The residuals are treated as independent. If your noise is correlated in time or space, the spread comes out too small.
The bootstrap can understate the spread even for independent noise, because the residuals of
a fitted curve are a little smaller than the noise itself; in one of our tests its 95 %
interval missed the true value. For a synthetic check, compare it with ensemble, and treat
its intervals as a lower bound on the uncertainty.
Parallel runs¶
jobs= runs the fits in parallel processes. Set OMP_NUM_THREADS=1 in the environment
first, so that the sparse solvers in each process do not compete for cores.