Source code for bayesflow.simulators.benchmark_simulators.bernoulli_glm_raw
import numpy as np
from scipy.special import expit
from .benchmark_simulator import BenchmarkSimulator
[docs]
class BernoulliGLMRaw(BenchmarkSimulator):
def __init__(self, T: int = 100, rng: np.random.Generator = None):
"""Bernoulli GLM raw simulated benchmark.
See: https://arxiv.org/pdf/2101.04653.pdf, Task T.6
Parameters
----------
T: int, optional, default: 100
The simulated duration of the task (eq. the number of Bernoulli draws).
rng: np.random.Generator or None, optional, default: None
An optional random number generator to use.
"""
self.T = T
self.rng = rng
if self.rng is None:
self.rng = np.random.default_rng()
# Covariance matrix computed once for efficiency
F = np.zeros((9, 9))
i = np.arange(9)
F[i, i] = 1 + np.sqrt(i / 9)
F[i[1:], i[:-1]] = -2
F[i[2:], i[:-2]] = 1
self.cov = np.linalg.inv(F.T @ F)
[docs]
def prior(self):
"""Generates a random draw from the custom prior over the 10
Bernoulli GLM parameters (1 intercept and 9 weights). Uses a
global covariance matrix `Cov` for the multivariate Gaussian prior
over the model weights, which is pre-computed for efficiency.
Returns
-------
params : np.ndarray of shape (10, )
A single draw from the prior.
"""
beta = self.rng.normal(0, 2)
f = self.rng.multivariate_normal(np.zeros(9), self.cov)
return np.append(beta, f)
[docs]
def observation_model(self, params: np.ndarray):
"""Simulates data from the custom Bernoulli GLM likelihood and
returns the raw Bernoulli data.
Parameters
----------
params : np.ndarray of shape (10, )
The vector of model parameters (`params[0]` is intercept, `params[i], i > 0` are weights)
Returns
-------
x : np.ndarray of shape (T, 10)
The full simulated set of Bernoulli draws and design matrix.
Should be configured with an additional trailing dimension if the data is (properly) to be treated as a set.
"""
# Unpack parameters
beta, f = params[0], params[1:]
# Generate design matrix
V = self.rng.normal(size=(9, self.T))
# Draw from Bernoulli GLM and return
z = self.rng.binomial(n=1, p=expit(V.T @ f + beta))
return np.c_[np.expand_dims(z, axis=-1), V.T]