Interventions
Given a bn_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.
Apply Modifications
Assume that model
represents a additive structural equation
model with DAG \(G\) and equations
Generally, modifications are changes of the transformations \(f_i\) and the additive noise \(\epsilon_i\).
Assume we have given a model
having a node Assume a node
\(X_3\) with parents \(X_1\) and \(X_2\) and \(f_3(x_1,
x_2)=x_1^2\cdot x_2+x_1\) and \(\epsilon_3\sim\mathcal{N}(0, 1)\).
That means,
Randomized modification
One way to change the construction of \(X_3\) from its parents is
by randomly generating a new Term
and additive noise object using the 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
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!
Controlled modification
Inner nodes
Instead of randomly generating a new term for \(X_3\) 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
Conditional
given when
instantiating the model.
Source nodes
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),
)
Computing causal effects
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 \(X_i\) having value \(k\) onto another variable, like \(X_j\) should be determined. This is
In our example above, setting \(X_1=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 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
.