Skip to content

Commit 0fc9703

Browse files
add irt_simulator and threelevel_simulator
1 parent 3f91e7a commit 0fc9703

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed

bayesflow/experimental/graphical_simulator/example_simulators.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,93 @@
22
from .graphical_simulator import GraphicalSimulator
33

44

5+
def irt_simulator():
6+
# schools have different exam difficulties
7+
def sample_school():
8+
mu_exam_mean = np.random.normal(loc=1.1, scale=0.2)
9+
sigma_exam_mean = abs(np.random.normal(loc=0, scale=1))
10+
11+
# hierarchical mu/sigma for the exam difficulty standard deviation (logscale)
12+
mu_exam_std = np.random.normal(loc=0.5, scale=0.3)
13+
sigma_exam_std = abs(np.random.normal(loc=0, scale=1))
14+
15+
return dict(
16+
mu_exam_mean=mu_exam_mean,
17+
sigma_exam_mean=sigma_exam_mean,
18+
mu_exam_std=mu_exam_std,
19+
sigma_exam_std=sigma_exam_std,
20+
)
21+
22+
# exams have different question difficulties
23+
def sample_exam(mu_exam_mean, sigma_exam_mean, mu_exam_std, sigma_exam_std):
24+
# mean question difficulty for an exam
25+
exam_mean = np.random.normal(loc=mu_exam_mean, scale=sigma_exam_mean)
26+
27+
# standard deviation of question difficulty
28+
log_exam_std = np.random.normal(loc=mu_exam_std, scale=sigma_exam_std)
29+
exam_std = float(np.exp(log_exam_std))
30+
31+
return dict(exam_mean=exam_mean, exam_std=exam_std)
32+
33+
# realizations of individual question difficulties
34+
def sample_question(exam_mean, exam_std):
35+
question_difficulty = np.random.normal(loc=exam_mean, scale=exam_std)
36+
37+
return dict(question_difficulty=question_difficulty)
38+
39+
# realizations of individual student abilities
40+
def sample_student(**kwargs):
41+
student_ability = np.random.normal(loc=0, scale=1)
42+
43+
return dict(student_ability=student_ability)
44+
45+
# realizations of individual observations
46+
def sample_observation(question_difficulty, student_ability):
47+
theta = np.exp(question_difficulty + student_ability) / (1 + np.exp(question_difficulty + student_ability))
48+
49+
obs = np.random.binomial(n=1, p=theta)
50+
51+
return dict(obs=obs)
52+
53+
def meta_fn():
54+
return {
55+
"num_exams": np.random.randint(2, 4),
56+
"num_questions": np.random.randint(10, 21),
57+
"num_students": np.random.randint(100, 201),
58+
}
59+
60+
simulator = GraphicalSimulator(meta_fn=meta_fn)
61+
simulator.add_node(
62+
"schools",
63+
sampling_fn=sample_school,
64+
)
65+
simulator.add_node(
66+
"exams",
67+
sampling_fn=sample_exam,
68+
reps="num_exams",
69+
)
70+
simulator.add_node(
71+
"questions",
72+
sampling_fn=sample_question,
73+
reps="num_questions",
74+
)
75+
simulator.add_node(
76+
"students",
77+
sampling_fn=sample_student,
78+
reps="num_students",
79+
)
80+
81+
simulator.add_node("observations", sampling_fn=sample_observation)
82+
83+
simulator.add_edge("schools", "exams")
84+
simulator.add_edge("schools", "students")
85+
simulator.add_edge("exams", "questions")
86+
simulator.add_edge("questions", "observations")
87+
simulator.add_edge("students", "observations")
88+
89+
return simulator
90+
91+
592
def twolevel_simulator():
693
def sample_hypers():
794
hyper_mean = np.random.normal()
@@ -40,3 +127,52 @@ def sample_y(local_mean, shared_std):
40127
simulator.add_edge("shared", "y")
41128

42129
return simulator
130+
131+
132+
def threelevel_simulator():
133+
def sample_level_1():
134+
level_1_mean = np.random.normal()
135+
136+
return {"level_1_mean": float(level_1_mean)}
137+
138+
def sample_level_2(level_1_mean):
139+
level_2_mean = np.random.normal(level_1_mean, 1)
140+
141+
return {"level_2_mean": float(level_2_mean)}
142+
143+
def sample_level_3(level_2_mean):
144+
level_3_mean = np.random.normal(level_2_mean, 1)
145+
146+
return {"level_3_mean": float(level_3_mean)}
147+
148+
def sample_shared():
149+
shared_std = np.abs(np.random.normal())
150+
151+
return {"shared_std": shared_std}
152+
153+
def sample_y(level_3_mean, shared_std):
154+
y = np.random.normal(level_3_mean, shared_std, size=10)
155+
156+
return {"y": y}
157+
158+
simulator = GraphicalSimulator()
159+
simulator.add_node("level1", sampling_fn=sample_level_1)
160+
simulator.add_node(
161+
"level2",
162+
sampling_fn=sample_level_2,
163+
reps=10,
164+
)
165+
simulator.add_node(
166+
"level3",
167+
sampling_fn=sample_level_3,
168+
reps=20,
169+
)
170+
simulator.add_node("shared", sampling_fn=sample_shared)
171+
simulator.add_node("y", sampling_fn=sample_y, reps=10)
172+
173+
simulator.add_edge("level1", "level2")
174+
simulator.add_edge("level2", "level3")
175+
simulator.add_edge("level3", "y")
176+
simulator.add_edge("shared", "y")
177+
178+
return simulator

0 commit comments

Comments
 (0)