Given a :pybn_testing.models.Model
object, modifications, like interventions, of the terms and source distributions can be applied and data from the modified model can be sampled.
The goal of these modificiations may be:
- Generating interventional data.
- Simulation of changed behavior in the system under study.
Assume that model
represents a additive structural equation model with DAG G and equations
Xi = fi(Xj, j ∈ paG(i)) + ϵi
Generally, modifications are changes of the transformations fi and the additive noise ϵi.
Assume we have given a model
having a node Assume a node X3 with parents X1 and X2 and f3(x1, x2) = x12 ⋅ x2 + x1 and ϵ3 ∼ 𝒩(0, 1). That means,
X3 = X12 ⋅ X2 + X1 + ϵ3
One way to change the construction of X3 from its parents is by randomly generating a new :py~bn_testing.terms.Term
and additive noise object using the :py~bn_testing.conditionals.Conditional
used when instantiating the model. This can be done as folllows:
model.modify_node(node='X3')
The same works for source nodes, where a new source distribution is generated using the :py~bn_testing.conditionals.Conditional.make_source
method of the condidtional object.
Note
The model modification is done inplace, that means, an applied modification cannot be undone.
Alternatively, the new term can also be generated using another conditional:
from bn_testing.conditionals import LinearConditional
model.modify_node(node='X3', conditionals=LinearConditional())
Note
A modification not only changes the term, but also the additive noise!
Instead of randomly generating a new term for X3 is constructed, we can also directly set the new term:
from bn_testing.terms import Linear
import pymc as pm
model.modify_inner_node(
node='X3',
term=Linear(['X1', 'X2'], [0.5, -0.1],
noise=pm.Beta.normal(alpha=0.2, beta=0.1),
)
Note that if either the noise
or the term
are omitted, a respective object is generated using the :py~bn_testing.conditionals.Conditional
given when instantiating the model.
If X1 is a source node, its distribution can be replaced with another distribution as follows:
import pymc as pm
model.modify_source_node(
node='X3',
distribution=pm.Beta.dist(alpha=0.9, beta=0.1),
)
A special case of a modification is when a random variable is set to a constant value. Typically, this is done because the average causal effect of Xi having value k onto another variable, like Xj should be determined. This is
𝔼[Xj|Xi = k] − 𝔼[Xj]
In our example above, setting X1 = 2 permantently can be archived with:
from bn_testing.conditionals import ConstantConditional
import pymc as pm
model.modify_node(
node='X1',
conditionals=ConstantConditional(2)
)
The average causal effect for this setting can be computed using the shortcut :py~bn_testing.models.Model.compute_average_causal_effect
:
model.compute_average_causal_effect(
node_from='X1',
node_onto='X3',
value=2,
)
Note
The calculation of the expected values used in the formula of the average causal effect is done empirically by sampling from the model with and without modification. The number of samples used can be changed by setting the paramater n
.