Session 7: experiments, sweeps and replications#
Zoo models: Deffuant, Hegselmann-Krause, Axelrod
Goals#
Design a parameter sweep with replications, each run with its own independent seed.
Run it in parallel with
modelly.batch.run_gridon Windows, macOS and Linux.Report a result with its spread across seeds, not one lucky run.
Before the session: the sociology tutorial.
Exercises#
7.1 Sweep the Deffuant confidence bound over 0.05, 0.1, 0.2 and 0.3 with ten replications
each using run_grid, and plot the mean and standard deviation of the cluster count.
Solution
Put the run function in an importable file, sweep.py, so that worker processes can import
it (Windows and macOS start workers with spawn):
# sweep.py
from modelly.batch import run_grid
from modelly.zoo.deffuant.model import Deffuant, DeffuantScenario
def run(task):
model = Deffuant(DeffuantScenario(rng=task["seed"], epsilon=task["epsilon"]))
model.run()
return {"clusters": model.n_clusters()}
if __name__ == "__main__":
frame = run_grid(run, {"epsilon": [0.05, 0.1, 0.2, 0.3]}, replicates=10, seed=1)
print(frame.groupby("epsilon")["clusters"].agg(["mean", "std"]))
Run it with python sweep.py (bash and PowerShell alike).
7.2 Are the seeds of run_grid the same when you run with one worker and with four?
Why does it matter?
Solution
Yes: grid_tasks derives every task’s seed from numpy.random.SeedSequence(seed).spawn,
before any work is distributed. The results therefore do not depend on the machine or the
number of processes, and anybody can rerun one task alone.
7.3 Do the same sweep for Hegselmann-Krause. Which model reaches consensus at a smaller confidence bound?
Solution
Replace the model and scenario in run with HegselmannKrause and HKScenario. Both
reach consensus between about 0.2 and 0.3 for uniform initial opinions; compare the means
at 0.2 with their standard deviations before calling one smaller.
7.4 For Axelrod, sweep traits over 2, 5, 10, 15 and 30 with five seeds each. Between
which values does the number of regions take off?
Solution
from modelly.zoo.axelrod.model import Axelrod, AxelrodScenario
def run(task):
model = Axelrod(AxelrodScenario(rng=task["seed"], traits=task["traits"]))
model.run()
return {"regions": model.n_regions()}
On a 10 x 10 grid with five features, one or a few regions up to about 10 traits, then a sharp rise: the finite-size trace of the order-disorder transition of Castellano, Marsili and Vespignani.