Skip to content

Commit 9284333

Browse files
move example simulators to own submodule
1 parent e59b2b2 commit 9284333

File tree

8 files changed

+242
-208
lines changed

8 files changed

+242
-208
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from .graphical_simulator import GraphicalSimulator
2+
from . import example_simulators

bayesflow/experimental/graphical_simulator/example_simulators.py

Lines changed: 0 additions & 207 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .single_level import single_level
2+
from .two_level import two_level
3+
from .two_level_repeated_roots import two_level_repeated_roots
4+
from .irt import irt
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import numpy as np
2+
3+
from ..graphical_simulator import GraphicalSimulator
4+
5+
6+
def irt():
7+
r"""
8+
Item Response Theory (IRT) model implemented as a graphical simultor.
9+
10+
schools
11+
/ \
12+
exams students
13+
| |
14+
questions |
15+
\ /
16+
observations
17+
"""
18+
19+
# schools have different exam difficulties
20+
def sample_school():
21+
mu_exam_mean = np.random.normal(loc=1.1, scale=0.2)
22+
sigma_exam_mean = abs(np.random.normal(loc=0, scale=1))
23+
24+
# hierarchical mu/sigma for the exam difficulty standard deviation (logscale)
25+
mu_exam_std = np.random.normal(loc=0.5, scale=0.3)
26+
sigma_exam_std = abs(np.random.normal(loc=0, scale=0.5))
27+
28+
return dict(
29+
mu_exam_mean=mu_exam_mean,
30+
sigma_exam_mean=sigma_exam_mean,
31+
mu_exam_std=mu_exam_std,
32+
sigma_exam_std=sigma_exam_std,
33+
)
34+
35+
# exams have different question difficulties
36+
def sample_exam(mu_exam_mean, sigma_exam_mean, mu_exam_std, sigma_exam_std):
37+
# mean question difficulty for an exam
38+
exam_mean = np.random.normal(loc=mu_exam_mean, scale=sigma_exam_mean)
39+
40+
# standard deviation of question difficulty
41+
log_exam_std = np.random.normal(loc=mu_exam_std, scale=sigma_exam_std)
42+
exam_std = float(np.exp(log_exam_std))
43+
44+
return dict(exam_mean=exam_mean, exam_std=exam_std)
45+
46+
# realizations of individual question difficulties
47+
def sample_question(exam_mean, exam_std):
48+
question_difficulty = np.random.normal(loc=exam_mean, scale=exam_std)
49+
50+
return dict(question_difficulty=question_difficulty)
51+
52+
# realizations of individual student abilities
53+
def sample_student():
54+
student_ability = np.random.normal(loc=0, scale=1)
55+
56+
return dict(student_ability=student_ability)
57+
58+
# realizations of individual observations
59+
def sample_observation(question_difficulty, student_ability):
60+
theta = np.exp(question_difficulty + student_ability) / (1 + np.exp(question_difficulty + student_ability))
61+
62+
obs = np.random.binomial(n=1, p=theta)
63+
64+
return dict(obs=obs)
65+
66+
def meta_fn():
67+
return {
68+
"num_exams": np.random.randint(2, 4),
69+
"num_questions": np.random.randint(10, 21),
70+
"num_students": np.random.randint(100, 201),
71+
}
72+
73+
simulator = GraphicalSimulator(meta_fn=meta_fn)
74+
75+
simulator.add_node("schools", sample_fn=sample_school)
76+
simulator.add_node("exams", sample_fn=sample_exam, reps="num_exams")
77+
simulator.add_node("questions", sample_fn=sample_question, reps="num_questions")
78+
simulator.add_node("students", sample_fn=sample_student, reps="num_students")
79+
simulator.add_node("observations", sample_fn=sample_observation)
80+
81+
simulator.add_edge("schools", "exams")
82+
simulator.add_edge("schools", "students")
83+
simulator.add_edge("exams", "questions")
84+
simulator.add_edge("questions", "observations")
85+
simulator.add_edge("students", "observations")
86+
87+
return simulator
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import numpy as np
2+
3+
from ..graphical_simulator import GraphicalSimulator
4+
5+
6+
def single_level():
7+
"""
8+
Simple single-level simulator that implements the same model as in
9+
https://bayesflow.org/main/_examples/Linear_Regression_Starter.html
10+
"""
11+
12+
def prior():
13+
beta = np.random.normal([2, 0], [3, 1])
14+
sigma = np.random.gamma(1, 1)
15+
16+
return {"beta": beta, "sigma": sigma}
17+
18+
def likelihood(beta, sigma, N):
19+
x = np.random.normal(0, 1, size=N)
20+
y = np.random.normal(beta[0] + beta[1] * x, sigma, size=N)
21+
22+
return {"x": x, "y": y}
23+
24+
def meta():
25+
N = np.random.randint(5, 15)
26+
27+
return {"N": N}
28+
29+
simulator = GraphicalSimulator(meta_fn=meta)
30+
31+
simulator.add_node("prior", sample_fn=prior)
32+
simulator.add_node("likelihood", sample_fn=likelihood)
33+
34+
simulator.add_edge("prior", "likelihood")
35+
36+
return simulator
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import numpy as np
2+
3+
from ..graphical_simulator import GraphicalSimulator
4+
5+
6+
def two_level():
7+
r"""
8+
Simple hierarchical model with two levels of parameters: hyperparameters
9+
and local parameters, along with a shared parameter:
10+
11+
hypers
12+
|
13+
locals shared
14+
\ /
15+
\ /
16+
y
17+
18+
"""
19+
20+
def sample_hypers():
21+
hyper_mean = np.random.normal()
22+
hyper_std = np.abs(np.random.normal())
23+
24+
return {"hyper_mean": hyper_mean, "hyper_std": hyper_std}
25+
26+
def sample_locals(hyper_mean, hyper_std):
27+
local_mean = np.random.normal(hyper_mean, hyper_std)
28+
29+
return {"local_mean": local_mean}
30+
31+
def sample_shared():
32+
shared_std = np.abs(np.random.normal())
33+
34+
return {"shared_std": shared_std}
35+
36+
def sample_y(local_mean, shared_std):
37+
y = np.random.normal(local_mean, shared_std)
38+
39+
return {"y": y}
40+
41+
simulator = GraphicalSimulator()
42+
simulator.add_node("hypers", sample_fn=sample_hypers)
43+
44+
simulator.add_node(
45+
"locals",
46+
sample_fn=sample_locals,
47+
reps=6,
48+
)
49+
50+
simulator.add_node("shared", sample_fn=sample_shared)
51+
simulator.add_node("y", sample_fn=sample_y, reps=10)
52+
53+
simulator.add_edge("hypers", "locals")
54+
simulator.add_edge("locals", "y")
55+
simulator.add_edge("shared", "y")
56+
57+
return simulator

0 commit comments

Comments
 (0)