import osif"KERAS_BACKEND"notin os.environ:# set this to "torch", "tensorflow", or "jax" os.environ["KERAS_BACKEND"] ="jax"import matplotlib.pyplot as pltimport numpy as npimport bayesflow as bf
INFO:bayesflow:Using backend 'jax'
Here we will estimate the mean and standard deviation, assuming data following a Gaussian distribution. The model can be summarised as
Note that contrary to the JAGS/BUGS implementation, we can specify the model with whatever parametrization we want, and so we can use the standard deviation parameter (\(\sigma\)) directly in the model.
We want to produce a network that can handle data of various sample sizes \(n\). The inference net expects an input of the same size, and so we need a way how to summarise the raw data into a vector of a fixed length.
We could simply exploit the fact that Gaussian data \(\textbf{x} = (x_1, \dots, x_n)\) can be sufficiently described by its observed mean \(\bar{x} = \sum_i^n \frac{x_i}{n}\), standard deviation \(s = \sqrt{\frac{\sum_i^n (x_i - \bar{x})^2}{n-1}}\), and sample size \(n\). You may notice that this is also the approach that we used in the previous chapters where we summarised a vector of bernoulli trials \(\textbf{x}\) in terms of its sufficient statistics: number of successes \(k\) and the number of trials \(n\).
Simulator
Code
def context(batch_size): n = np.random.randint(10, 501, size=batch_size)returndict(n = n)def prior(): mu = np.random.normal() sigma = np.random.gamma(shape=2, scale=1)returndict(mu=mu, sigma=sigma)def summary(y): mean = np.mean(y) sd = np.std(y)returndict(mean=mean, sd=sd)def likelihood(n, mu, sigma): y = np.random.normal(loc=mu, scale=sigma, size=n)return summary(y)simulator = bf.simulators.make_simulator([prior, likelihood], meta_fn=context)df = simulator.sample(100)for key, value in df.items():print(key, "\tshape:", np.array(value).shape)
n shape: (100, 1)
mu shape: (100, 1)
sigma shape: (100, 1)
mean shape: (100, 1)
sd shape: (100, 1)