from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import lapylace as lp
root = Path("../../ROS-Examples")
def coef_medians(fit):
return pd.Series(
[np.median(fit.alpha_draws()), *np.median(fit.beta_draws(), axis=0)],
index=["Intercept", *fit.columns],
)
def fit_glm(formula, data, family=None, seed=1, prior_scale=2.5, intercept_scale=5, aux_scale=10, **kwargs):
return lp.stan_glm(
formula,
data=data,
family=family or lp.gaussian(),
prior=lp.normal(0, prior_scale),
prior_intercept=lp.normal(0, intercept_scale),
prior_aux=lp.exponential(aux_scale),
chains=2,
parallel_chains=2,
iter_warmup=300,
iter_sampling=500,
seed=seed,
refresh=100,
**kwargs,
)Bayesian R-squared examples
Source: Rsquared/rsquared.Rmd
The calculations use posterior expected values from lapylace fits. For each model, \(R^2 = Var(\mu)/(Var(\mu) + Var(\epsilon))\) is computed draw by draw.
Setup
def bayes_r2_gaussian(fit, data):
mu = fit.posterior_epred(data)
return np.var(mu, axis=1) / (np.var(mu, axis=1) + fit.stan_variables()["sigma"]**2)
kidiq = pd.read_csv(root / "KidIQ/data/kidiq.csv")
earnings = pd.read_csv(root / "Earnings/data/earnings.csv").dropna(subset=["earn", "height", "male"])
earnings["log_earn"] = np.log(earnings.earn.clip(lower=1))fits = {
"KidIQ": (fit_glm("kid_score ~ mom_hs + mom_iq", kidiq, seed=19301, prior_scale=10, intercept_scale=30, aux_scale=30), kidiq),
"log earnings": (fit_glm("log_earn ~ height + male", earnings, seed=19302, prior_scale=2.5, intercept_scale=10, aux_scale=5), earnings),
}
rows = []
for label, (fit, data) in fits.items():
r2 = bayes_r2_gaussian(fit, data)
rows.append({"model": label, "median": np.median(r2), "lo80": np.quantile(r2,.1), "hi80": np.quantile(r2,.9)})
pd.DataFrame(rows)
| model | median | lo80 | hi80 | |
|---|---|---|---|---|
| 0 | KidIQ | 0.217660 | 0.181176 | 0.258708 |
| 1 | log earnings | 0.076843 | 0.063485 | 0.092963 |