Quick-start walkthrough — fit your first covariance ellipse¶
The snippet below shows the minimal end-to-end workflow: simulate a handful of
oddity-task trials at a single reference point, fit the WPPM with MAP
optimization, and visualize the result. No GPU needed — runs in under 2 min
on CPU.
MC_SAMPLES=50# MC samples per trial in the likelihood (full example: 500)NUM_TRIALS=1000# total simulated trials (full example: 4000 × 25)NUM_STEPS=600# optimizer steps (full example: 2000)learning_rate=1e-4# full example: 5e-5. The smaller the lr, the more steps# are required.## These four are not free choices -- they were swept (across both the jax# version floor CI pins, jax==0.4.28, and a current jax, and across several# seeds each) for the cheapest setting that recovers the ground truth reliably:# fitted/true ellipse area ratio within roughly [0.6, 1.6] and no sign of# collapse or divergence, ~4-13 s CPU depending on jax version.## * NUM_TRIALS is the binding constraint. All trials sit at a *single*# reference point, so the likelihood is weak, and the outcome at low# trial counts is not a clean "collapses to zero" failure -- it is# chaotic: depending on the exact random draw (which differs across jax# versions for the same PRNGKey, not just across seeds) the same trial# count can collapse toward zero, overshoot by several times, or blow up# numerically. Below ~500 trials this instability shows up often enough# to make the fit unreliable; 1000 clears it with margin on every# jax/seed combination tested.# * NUM_STEPS below ~600 overshoots rather than under-fits.# * learning_rate above ~2e-3 diverges to a non-finite loss within 25 steps.## MAPOptimizer defaults to reduction="mean" (a per-trial objective), so this# learning rate does not need rescaling when you change NUM_TRIALS.
task=OddityTask(config=OddityTaskConfig(num_samples=int(MC_SAMPLES)))noise=GaussianNoise(sigma=0.1)# Set all Wishart process hyperparameters in Priortruth_prior=Prior()truth_model=WPPM(prior=truth_prior,likelihood=task,noise=noise,)# Sample ground-truth Wishart process weightstruth_params=truth_model.init_params(jax.random.PRNGKey(123))
# Simulate observed responses using the likelihood implied by the taskys,prob_params=task.simulate(truth_params,stimuli,truth_model,key=k_sim)p_correct=prob_params[0]# <- for Bernoulli tasks, p_correct is the only prob_param
inference=MAPOptimizer(steps=NUM_STEPS,learning_rate=learning_rate,track_history=True,log_every=1,)map_estimate=inference.fit(model,data,init_params=init_params,seed=4)# Protocol: ParameterPosterior, here point estimate# optional: for visualization:map_cov_field=WPPMCovarianceField(model,map_estimate.params)# OUTPUT: Covariance Matrices (N, 2, 2) for plotting