Skip to content

Commit 6788e3c

Browse files
authored
fix LinAlgError in HSGP-Basic.ipynb, drop find_constrained_prior (#801)
* fix LinAlgError, drop find_constrained_prior + remove matplotlib commands which raise warnings * fix: rename cov_mat_jitted to cov_mat_stabilize
1 parent 730a60d commit 6788e3c

File tree

2 files changed

+299
-388
lines changed

2 files changed

+299
-388
lines changed

examples/gaussian_processes/HSGP-Basic.ipynb

Lines changed: 288 additions & 375 deletions
Large diffs are not rendered by default.

examples/gaussian_processes/HSGP-Basic.myst.md

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jupytext:
55
format_name: myst
66
format_version: 0.13
77
kernelspec:
8-
display_name: preliz
8+
display_name: Python 3 (ipykernel)
99
language: python
1010
name: python3
1111
---
@@ -87,7 +87,8 @@ def simulate_1d(x, ell_true, eta_true, sigma_true):
8787
# Draw one sample from the underlying GP.
8888
n = len(x)
8989
cov_func = eta_true**2 * pm.gp.cov.Matern52(1, ell_true)
90-
gp_true = pm.MvNormal.dist(mu=np.zeros(n), cov=cov_func(x[:, None]))
90+
cov_mat_stabilized = pm.gp.util.stabilize(cov_func(x[:, None]))
91+
gp_true = pm.MvNormal.dist(mu=np.zeros(n), cov=cov_mat_stabilized)
9192
f_true = pm.draw(gp_true, draws=1, random_seed=rng)
9293
9394
# The observed data is the latent function plus a small amount
@@ -153,7 +154,7 @@ with pm.Model(coords={"basis_coeffs": np.arange(200), "obs_id": np.arange(len(y_
153154
sigma = pm.Exponential("sigma", scale=1.0)
154155
pm.Normal("y_obs", mu=f, sigma=sigma, observed=y_obs, dims="obs_id")
155156
156-
idata = pm.sample()
157+
idata = pm.sample(chains=4)
157158
idata.extend(pm.sample_posterior_predictive(idata, random_seed=rng))
158159
```
159160

@@ -188,7 +189,7 @@ ax.scatter(x, y_obs, marker="o", color="grey", s=15, label="Observed data")
188189
ax.plot(x, f_true, color="#FBE64D", lw=2, label="True underlying GP 'f'")
189190
190191
ax.set(title="The HSGP Fit", xlabel="x", ylabel="y")
191-
ax.legend(frameon=True, fontsize=11, ncol=2);
192+
ax.legend(frameon=True, fontsize=11, ncol=2, loc="lower left");
192193
```
193194

194195
The inferred underlying GP (in bordeaux) accurately matches the true underlying GP (in yellow). We also see that the posterior predictive samples (in light blue) fit the observed data really well.
@@ -360,7 +361,7 @@ def calculate_Kapprox(Xs, L, m):
360361
```
361362
362363
```{code-cell} ipython3
363-
fig, axs = plt.subplots(2, 4, figsize=(14, 7), sharey=True)
364+
fig, axs = plt.subplots(2, 4, figsize=(14, 7), sharey=True, layout="tight")
364365
365366
axs[0, 0].imshow(K, cmap="inferno", vmin=0, vmax=1)
366367
axs[0, 0].set(xlabel="x1", ylabel="x2", title=f"True Gram matrix\nTrue $\\ell$ = {chosen_ell}")
@@ -413,7 +414,6 @@ axs[1, 3].set_title(f"m = {m}, c = {c}")
413414
414415
for ax in axs.flatten():
415416
ax.grid(False)
416-
plt.tight_layout();
417417
```
418418
419419
The plots above compare the approximate Gram matrices to the unapproximated Gram matrix in the top left panel. The goal is to compare the approximated Gram matrices to the true one (upper left). Qualitatively, **the more similar they look the better the approximation**. Also, these results are **only relevant to the context of the particular domain defined by `X` and the chosen lengthscale**, $\ell = 3$ -- just because it looks good for $\ell = 3$ doesn't mean it will look good for, for instance, $\ell = 10$.
@@ -499,7 +499,6 @@ y_tr, y_te = y_obs[ix_tr], y_obs[ix_te]
499499
500500
```{code-cell} ipython3
501501
fig = plt.figure(figsize=(13, 4))
502-
plt.subplots_adjust(wspace=0.02)
503502
504503
ax1 = plt.subplot(131)
505504
ax1.scatter(X_tr[:, 0], X_tr[:, 1], c=mu[ix_tr] - f_true[ix_tr])
@@ -539,10 +538,9 @@ with pm.Model() as model:
539538
540539
# Prior on the HSGP
541540
eta = pm.Exponential("eta", scale=2.0)
542-
ell_params = pm.find_constrained_prior(
543-
pm.Lognormal, lower=0.5, upper=5.0, mass=0.9, init_guess={"mu": 1.0, "sigma": 1.0}
544-
)
545-
ell = pm.Lognormal("ell", **ell_params)
541+
ell_dist = pz.maxent(pz.LogNormal(), lower=0.5, upper=5.0, mass=0.9, plot=False)
542+
ell = ell_dist.to_pymc("ell")
543+
546544
cov_func = eta**2 * pm.gp.cov.Matern52(input_dim=2, ls=ell)
547545
548546
# m and c control the fidelity of the approximation
@@ -608,7 +606,7 @@ Now, let's sample the model and quickly check the results:
608606
609607
```{code-cell} ipython3
610608
with model:
611-
idata.extend(pm.sample(nuts_sampler="numpyro", random_seed=rng))
609+
idata.extend(pm.sample(chains=4, nuts_sampler="numpyro", random_seed=rng))
612610
```
613611
614612
```{code-cell} ipython3
@@ -654,7 +652,6 @@ pm.model_to_graphviz(model)
654652
655653
```{code-cell} ipython3
656654
fig = plt.figure(figsize=(13, 4))
657-
plt.subplots_adjust(wspace=0.02)
658655
659656
ax1 = plt.subplot(131)
660657
ax1.scatter(X[:, 0], X[:, 1], c=f_true)
@@ -687,6 +684,7 @@ Sampling diagnostics all look good, and we can see that the underlying GP was in
687684
688685
* Created by [Bill Engels](https://github.com/bwengals) and [Alexandre Andorra](https://github.com/AlexAndorra) in 2024 ([pymc-examples#647](https://github.com/pymc-devs/pymc-examples/pull/647))
689686
* Use `pz.maxent` instead of `pm.find_constrained_prior`, and add random seed. [Osvaldo Martin](https://aloctavodia.github.io/). August 2024
687+
* Use `pm.gp.util.stabilize` in `simulate_1d`. Use `pz.maxent` rather than `pm.find_constrained_prior` in linearized HSGP model. [Alexander Armstrong](https://github.com/Armatron44), July 2025.
690688
691689
+++
692690

0 commit comments

Comments
 (0)