This page was generated from notebooks/0B-Simulator.ipynb.

Swyft Simulator

In this notebook, we will demonstrate how to generate training data using the swyft.Simulator class.

Setup

First some imports.

[1]:
import numpy as np
from scipy import stats
import pylab as plt
import torch
import swyft

Definition of a simulator

The simulator defines a forward model for generating samples. This happens in the forward method, where we populate the trace with sampling instructions for the relevant variables.

[3]:
class Simulator(swyft.Simulator):
    def __init__(self):
        super().__init__()
        self.transform_samples = swyft.to_numpy32

    def build(self, graph):
        z = graph.node('z', lambda: np.random.rand(1))
        x = graph.node('x', lambda z: z + np.random.randn(1)*0.1, z)

sim = Simulator()

Generating training data

It is now simple to generate training data.

[4]:
samples = sim.sample(10000)
100%|██████████| 10000/10000 [00:00<00:00, 67905.70it/s]

Notice that the generated samples are single-precision, which is caused by the optional transform_samples hook.

[5]:
samples[0:3]
[5]:
Samples({'z': array([[0.8564868 ],
       [0.23995215],
       [0.9284431 ]], dtype=float32), 'x': array([[0.9416641 ],
       [0.13781811],
       [0.85398877]], dtype=float32)})

Why a simulator class?

The simulator class defines the computational graph of the simulator model. Sample statements in the simulator are lazily evaluated. That means that only those components in the calculational graph are evaluated that are necessary for a given task.

As an example, we can use this to only generate samples for one of the variables.

[6]:
sim.sample(targets = ['z'])
[6]:
Sample({'z': array([0.72290325], dtype=float32)})

Or we can generate sample that are conditioned on certain variables.

[7]:
sim.sample(conditions = {'z': np.array([1.])})
[7]:
Sample({'z': array([1.], dtype=float32), 'x': array([0.9408247], dtype=float32)})
[ ]:

This page was generated from notebooks/0B-Simulator.ipynb.