Code
import os
if "KERAS_BACKEND" not in os.environ:
# set this to "torch", "tensorflow", or "jax"
"KERAS_BACKEND"] = "jax"
os.environ[
import matplotlib.pyplot as plt
import numpy as np
import bayesflow as bf
import keras
import os
if "KERAS_BACKEND" not in os.environ:
# set this to "torch", "tensorflow", or "jax"
"KERAS_BACKEND"] = "jax"
os.environ[
import matplotlib.pyplot as plt
import numpy as np
import bayesflow as bf
import keras
Here we will compare two models. The null model assumes that proportion is the same for two binomial data sets
\[\begin{equation} \begin{aligned} s_1 & \sim \text{Binomial}(\theta_1, n_1) \\ s_2 & \sim \text{Binomial}(\theta_1, n_2) \\ \theta_1 & \sim \text{Beta}(1, 1), \end{aligned} \end{equation}\] whereas the alternative model assumes that the two groups are associated with different binomial rates:
\[\begin{equation} \begin{aligned} s_1 & \sim \text{Binomial}(\theta_1, n_1) \\ s_2 & \sim \text{Binomial}(\theta_1, n_2) \\ \theta_1 & \sim \text{Beta}(1, 1) \\ \theta_2 & \sim \text{Beta}(1, 1). \end{aligned} \end{equation}\]
We will also amortize over different sample sizes for each group.
def context():
= np.random.randint(1000, 10_000, size=2)
n return dict(n = n)
def prior_null():
= np.random.beta(a=1, b=1)
theta return dict(theta = np.array([theta, theta]))
def prior_alternative():
= np.random.beta(a=1, b=1, size=2)
theta return dict(theta = theta)
def likelihood(theta, n):
= np.random.binomial(n=n, p=theta)
s return dict(s=s)
= bf.make_simulator([context, prior_null, likelihood])
simulator_null = bf.make_simulator([context, prior_alternative, likelihood])
simulator_alternative = bf.simulators.ModelComparisonSimulator(
simulator =[simulator_null, simulator_alternative],
simulators=True) use_mixed_batches
= (
adapter
bf.Adapter()'n', 's'], into="classifier_conditions")
.concatenate(['theta')
.drop( )
= keras.Sequential([
classifier_network 32, activation="gelu")
keras.layers.Dense(for _ in range(8)
])= bf.approximators.ModelComparisonApproximator(
approximator =2,
num_models=classifier_network,
classifier_network=adapter) adapter
= 30
epochs = 100
num_batches = 512
batch_size
= keras.optimizers.schedules.CosineDecay(5e-4, decay_steps=epochs*num_batches)
learning_rate = keras.optimizers.Adam(learning_rate=learning_rate, clipnorm=1.0)
optimizer compile(optimizer=optimizer) approximator.
= approximator.fit(
history =epochs,
epochs=num_batches,
num_batches=batch_size,
batch_size=simulator,
simulator=adapter
adapter )
=bf.diagnostics.plots.loss(history=history) f
=simulator.sample(5_000) test_data
=test_data["model_indices"]
true_models=approximator.predict(conditions=test_data) pred_models
=bf.diagnostics.plots.mc_calibration(
f=pred_models,
pred_models=true_models,
true_models=[r"$\mathcal{M}_0$",r"$\mathcal{M}_1$"],
model_names )
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
=bf.diagnostics.plots.mc_confusion_matrix(
f=pred_models,
pred_models=true_models,
true_models=[r"$\mathcal{M}_0$",r"$\mathcal{M}_1$"],
model_names="true"
normalize )
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
INFO:matplotlib.mathtext:Substituting symbol M from STIXNonUnicode
= dict(n = np.array([[5416, 9072]]), s = np.array([[424, 777]])) inference_data
= approximator.predict(conditions=inference_data)[0]
pred_models pred_models
array([0.9855641 , 0.01443596], dtype=float32)
1]/pred_models[0] pred_models[
0.014647411