axiom

Bringing your own problem · step 4 of 6

Fit it, and read what came back

Did the model find the response, and what did the spec cost you?

fit takes the spec and the panel and nothing else. The posterior comes back with one named parameter per thing the spec declared, so there is no positional unpacking and no guessing which column of an array is the amplitude.

Look at sigma before anything else. The stores really do differ by about 6 visits, and a shared intercept has nowhere to put that, so it lands in the residual. The fit is not wrong — it is answering the question the spec asked. Changing intercept is how you ask a different one.

step 4
from axiom.surface import fit

result = fit(spec, panel, backend="laplace", draws=800, seed=0)

print(f"{'parameter':16s}{'posterior mean':>16}")
for name in result.posterior.names():
    mean = float(result.posterior.flat(name).mean())
    print(f"{name:16s}{mean:>16.2f}")
print()
print("the world that produced the data used:")
print("  baseline  ~40      amplitude 9.0     half-way 250")
print("  within-store noise 2.0, between-store spread 6.0")
print()
print("beta and k came back close. sigma did not -- it is carrying the")
print("between-store spread the shared intercept could not.")
what it printed
parameter         posterior mean
alpha                      38.27
k_leaflets                244.79
s_leaflets                  2.74
sigma                       7.23
beta_leaflets               8.31

the world that produced the data used:
  baseline  ~40      amplitude 9.0     half-way 250
  within-store noise 2.0, between-store spread 6.0

beta and k came back close. sigma did not -- it is carrying the
between-store spread the shared intercept could not.

Every line above was captured by running this code at build time. The steps share one namespace, so the code on this page is the code you would type after the steps before it.