# causalnex.network.BayesianNetwork¶

class causalnex.network.BayesianNetwork(structure)[source]

Bases: object

Base class for Bayesian Network (BN), a probabilistic weighted DAG where nodes represent variables, edges represent the causal relationships between variables.

BayesianNetwork stores nodes with their possible states, edges and conditional probability distributions (CPDs) of each node.

BayesianNetwork is built on top of the StructureModel, which is an extension of networkx.DiGraph (see causalnex.structure.structuremodel.StructureModel()).

In order to define the BayesianNetwork, users should provide a relevant StructureModel. Once BayesianNetwork is initialised, no changes to the StructureModel can be made and CPDs can be learned from the data.

The learned CPDs can be then used for likelihood estimation and predictions.

Example:

 # Create a Bayesian Network with a manually defined DAG.
from causalnex.structure import StructureModel
from causalnex.network import BayesianNetwork

sm = StructureModel()
('rush_hour', 'traffic'),
('weather', 'traffic')
])
bn = BayesianNetwork(sm)
# A created BayesianNetwork stores nodes and edges defined by the StructureModel
bn.nodes
['rush_hour', 'traffic', 'weather']

bn.edges
[('rush_hour', 'traffic'), ('weather', 'traffic')]
# A BayesianNetwork doesn't store any CPDs yet
bn.cpds
{}

# Learn the nodes' states from the data
import pandas as pd
data = pd.DataFrame({
'rush_hour': [True, False, False, False, True, False, True],
'traffic': ['heavy', 'light', 'heavy', 'light', 'heavy', 'heavy', 'heavy']
})
bn = bn.fit_node_states(data)
bn.node_states
{'rush_hour': {False, True}, 'weather': {'Bad', 'Good', 'Terrible'}, 'traffic': {'heavy', 'light'}}
# Learn the CPDs from the data
bn = bn.fit_cpds(data)
# Use the learned CPDs to make predictions on the unseen data
test_data = pd.DataFrame({
'rush_hour': [False, False, True, True],
})
bn.predict(test_data, "traffic").to_dict()
{'traffic_prediction': {0: 'light', 1: 'heavy', 2: 'heavy', 3: 'heavy'}}
bn.predict_probability(test_data, "traffic").to_dict()
{'traffic_prediction': {0: 'light', 1: 'heavy', 2: 'heavy', 3: 'heavy'}}
{'traffic_light': {0: 0.75, 1: 0.25, 2: 0.3333333333333333, 3: 0.3333333333333333},
'traffic_heavy': {0: 0.25, 1: 0.75, 2: 0.6666666666666666, 3: 0.6666666666666666}}


Attributes

 BayesianNetwork.cpds Conditional Probability Distributions of each node within the Bayesian Network. BayesianNetwork.edges List of all edges contained within the Bayesian Network, as a Tuple(from_node, to_node). BayesianNetwork.node_states Dictionary of all states that each node can take. BayesianNetwork.nodes List of all nodes contained within the Bayesian Network. BayesianNetwork.structure StructureModel defining the DAG of the Bayesian Network.

Methods

 BayesianNetwork.__delattr__(name, /) Implement delattr(self, name). BayesianNetwork.__dir__() default dir() implementation BayesianNetwork.__eq__(value, /) Return self==value. BayesianNetwork.__format__ default object formatter BayesianNetwork.__ge__(value, /) Return self>=value. BayesianNetwork.__getattribute__(name, /) Return getattr(self, name). BayesianNetwork.__gt__(value, /) Return self>value. BayesianNetwork.__hash__() Return hash(self). BayesianNetwork.__init__(structure) Create a BayesianNetwork with a DAG defined by StructureModel. BayesianNetwork.__init_subclass__ This method is called when a class is subclassed. BayesianNetwork.__le__(value, /) Return self<=value. BayesianNetwork.__lt__(value, /) Return self
__init__(structure)[source]

Create a BayesianNetwork with a DAG defined by StructureModel.

Parameters

structure (StructureModel) –

a graph representing a causal relationship between variables. In the structure

• cycles are not allowed;

• multiple (parallel) edges are not allowed;

• isolated nodes and multiple components are not allowed.

Raises

ValueError – If the structure is not a connected DAG.

add_node(node, edges_to_add, edges_to_remove)[source]

Adding a latent variable to the structure model, as well as its corresponding edges

Parameters
• node (str) – Name of the node

• edges_to_add (List[Tuple[str, str]]) – which edges to add to the structure

• edges_to_remove (List[Tuple[str, str]]) – which edges to remove from the structure

Return type

BayesianNetwork

Returns

self

Raises

ValueError – If lv_name exists in the network or if edges_to_add include edges NOT containing the latent variable or if edges_to_remove include edges containing the latent variable

property cpds

Conditional Probability Distributions of each node within the Bayesian Network.

The row-index of each dataframe is all possible states for the node. The col-index of each dataframe is a MultiIndex that describes all possible permutations of parent states.

For example, for a node $$P(A | B, D)$$, where .. math:

   - A \in \text{{"a", "b", "c", "d"}}
- B \in \text{{"x", "y", "z"}}
- C \in \text{{False, True}}

b         x                   y               z
d     False     True      False True      False     True
a
a  0.265306  0.214286  0.066667  0.25  0.444444  0.000000
b  0.183673  0.214286  0.200000  0.25  0.222222  0.666667
c  0.285714  0.285714  0.400000  0.25  0.333333  0.333333
d  0.265306  0.285714  0.333333  0.25  0.000000  0.000000

Return type

Dict[str, DataFrame]

Returns

Conditional Probability Distributions of each node within the Bayesian Network.

property edges

List of all edges contained within the Bayesian Network, as a Tuple(from_node, to_node).

Return type

List[Tuple[str, str]]

Returns

A list of all edges.

fit_cpds(data, method='MaximumLikelihoodEstimator', bayes_prior=None, equivalent_sample_size=None)[source]

Learn conditional probability distributions for all nodes in the Bayesian Network, conditioned on their incoming edges (parents).

Parameters
• data (DataFrame) – dataframe containing one column per node in the Bayesian Network.

• method (str) – how to fit probabilities. One of: - “MaximumLikelihoodEstimator”: fit probabilities using Maximum Likelihood Estimation; - “BayesianEstimator”: fit probabilities using Bayesian Parameter Estimation. Use bayes_prior.

• bayes_prior (Optional[str]) –

how to construct the Bayesian prior used by method=”BayesianEstimator”. One of: - “K2”: shorthand for dirichlet where all pseudo_counts are 1

regardless of variable cardinality;

• ”BDeu”: equivalent of using Dirichlet and using uniform ‘pseudo_counts’ of

equivalent_sample_size / (node_cardinality * np.prod(parents_cardinalities)) for each node. Use equivelant_sample_size.

• equivalent_sample_size (Optional[int]) – used by BDeu bayes_prior to compute pseudo_counts.

Return type

BayesianNetwork

Returns

self

Raises

ValueError – if an invalid method or bayes_prior is specified.

fit_latent_cpds(lv_name, lv_states, data, box_constraints=None, priors=None, initial_params='random', non_missing_data_factor=1, n_runs=20, stopping_delta=0.0)[source]

This runs the EM algorithm to estimate the CPDs of latent variables and their corresponding Markov blanket

Parameters
• lv_name (str) – Latent variable name

• lv_states (List) – the states the LV can assume

• data (DataFrame) – dataframe, must contain all variables in the Markov Blanket of the latent variable. Include one column with the latent variable name, filled with np.nan for missing info about LV. If some data is present about the LV, create complete columns.

• n_runs (int) – max number of EM alternations

• stopping_delta (float) – if max difference in current - last iteration CPDS < stopping_delta => convergence reached

• initial_params (Union[str, Dict[str, DataFrame]]) – way to initialise parameters. Can be: - “random”: random values (default) - “avg”: uniform distributions everywhere. Not advised, as it may be the a stationary point on itself - if provide a dictionary of dataframes, this will be used as the initialisation

• box_constraints (Optional[Dict[str, Tuple[DataFrame, DataFrame]]]) – minimum and maximum values for each model parameter. Specified with a dictionary mapping: - Node - two dataframes, in order: Min(P(Node|Par(Node))) and Max(P(Node|Par(Node)))

• priors (Optional[Dict[str, DataFrame]]) – priors, provided as a mapping Node -> dataframe with Dirichilet priors for P(Node|Par(Node))

• non_missing_data_factor (int) – This is a weight added to the non-missing data samples. The effect is as if the amount of data provided was bigger. Empirically, helps to set the factor to 10 if the non missing data is ~1% of the dataset

Return type

BayesianNetwork

Returns

self

Raises

ValueError – if the latent variable is not a string or if the latent variable cannot be found in the network or if the latent variable is present/observed in the data if the latent variable states are empty

fit_node_states(df)[source]

Fit all states of nodes that can appear in the data. The dataframe provided should contain every possible state (values that can be taken) for every column.

Parameters

df (DataFrame) – data to fit node states from. Each column indicates a node and each row an observed combination of states.

Return type

BayesianNetwork

Returns

self

Raises

ValueError – if dataframe contains any missing data.

fit_node_states_and_cpds(data, method='MaximumLikelihoodEstimator', bayes_prior=None, equivalent_sample_size=None)[source]

Call fit_node_states and then fit_cpds.

Parameters
• data (DataFrame) – dataframe containing one column per node in the Bayesian Network.

• method (str) – how to fit probabilities. One of: - “MaximumLikelihoodEstimator”: fit probabilities using Maximum Likelihood Estimation; - “BayesianEstimator”: fit probabilities using Bayesian Parameter Estimation. Use bayes_prior.

• bayes_prior (Optional[str]) –

how to construct the Bayesian prior used by method=”BayesianEstimator”. One of: - “K2”: shorthand for dirichlet where all pseudo_counts are 1

regardless of variable cardinality;

• ”BDeu”: equivalent of using dirichlet and using uniform ‘pseudo_counts’ of

equivalent_sample_size / (node_cardinality * np.prod(parents_cardinalities)) for each node. Use equivelant_sample_size.

• equivalent_sample_size (Optional[int]) – used by BDeu bayes_prior to compute pseudo_counts.

Return type

BayesianNetwork

Returns

self

property node_states

Dictionary of all states that each node can take.

Returns

{node: state}.

Return type

A dictionary of node and its possible states, in format of dict

property nodes

List of all nodes contained within the Bayesian Network.

Return type

List[str]

Returns

A list of node names.

predict(data, node)[source]

Predict the state of a node based on some input data, using the Bayesian Network.

Parameters
• data (DataFrame) – data to make prediction.

• node (str) – the node to predict.

Return type

DataFrame

Returns

A dataframe of predictions, containing a single column name {node}_prediction.

predict_probability(data, node)[source]

Predict the probability of each possible state of a node, based on some input data.

Parameters
• data (DataFrame) – data to make prediction.

• node (str) – the node to predict probabilities.

Return type

DataFrame

Returns

A dataframe of predicted probabilities, contained one column per possible state, named {node}_{state}.

set_cpd(node, df)[source]

Provide self-defined CPD to Bayesian Network

Parameters
• node (str) – the node to add self-defined cpd.

• df (DataFrame) – self-defined cpd in pandas DataFrame format.

Return type

BayesianNetwork

Returns

self

Raises
• IndexError – if the index names of the pandas DataFrame does not match the expected DataFrame.

• ValueError – if node does not exist in Bayesian Network or a bad cpd table is provided.

property structure

StructureModel defining the DAG of the Bayesian Network.

Return type

StructureModel

Returns

A StructureModel of the Bayesian Network.