Functional Bayesian Network¶
- class pgmpy.models.FunctionalBayesianNetwork.FunctionalBayesianNetwork(ebunch=None, latents={}, lavaan_str=None, dagitty_str=None)[source]¶
Class for representing Functional Bayesian Network.
Functional Bayesian Networks allow for representation of any probability distribution using CPDs in functional form (Functional CPD). Functional CPDs return a pyro.distribution object allowing for flexible representation of any distribution.
- add_cpds(*cpds)[source]¶
Adds FunctionalCPDs to the Bayesian Network.
- Parameters:
cpds (instances of FunctionalCPD) – List of FunctionalCPDs which will be associated with the model
Examples
>>> from pgmpy.factors.hybrid import FunctionalCPD >>> from pgmpy.models import FunctionalBayesianNetwork >>> import pyro.distributions as dist >>> import numpy as np
>>> model = FunctionalBayesianNetwork([("x1", "x2"), ("x2", "x3")]) >>> cpd1 = FunctionalCPD("x1", lambda _: dist.Normal(0, 1)) >>> cpd2 = FunctionalCPD("x2", lambda parent: dist.Normal(parent["x1"] + 2.0, 1), parents=["x1"]) >>> cpd3 = FunctionalCPD("x3", lambda parent: dist.Normal(parent["x2"] + 0.3, 2), parents=["x2"]) >>> model.add_cpds(cpd1, cpd2, cpd3)
- check_model()[source]¶
Checks the model for various errors. This method checks for the following error -
Checks if the CPDs associated with nodes are consistent with their parents.
- Returns:
check – True if all the checks pass.
- Return type:
boolean
- fit(data, method='SVI', optimizer=<pyro.optim.optim.PyroOptim object>, prior_fn=None, num_steps=1000, seed=None, nuts_kwargs=None, mcmc_kwargs=None)[source]¶
Fit the Bayesian network to data using Pyro’s stochastic variational inference.
- Parameters:
data (pandas.DataFrame) – DataFrame with observations of variables.
method (str (default: "SVI")) – Fitting method to use. Currently supports “SVI” and “MCMC”.
optimizer (Instance of pyro optimizer (default: pyro.optim.Adam({"lr": 1e-2}))) – Only used if method is “SVI”. The optimizer to use for optimization.
prior_fn (function) – Only used if method is “MCMC”. A function that returns a dictionary of pyro distributions for each parameter in the model.
num_steps (int (default: 100)) – Number of optimization steps. For SVI it is the num_steps argument for pyro.infer.SVI. For MCMC, it is the num_samples argument for pyro.infer.MCMC.
seed (int (default: None)) – Seed value for random number generator.
nuts_kwargs (dict (default: None)) – Only used if method is “MCMC”. Additional arguments to pass to pyro.infer.NUTS.
mcmc_kwargs (dict (default: None)) – Only used if method is “MCMC”. Additional arguments to pass to pyro.infer.MCMC.
- Returns:
dict – If method is “MCMC”, returns a dictionary of posterior samples for each parameter.
- Return type:
If method is “SVI”, returns a dictionary of parameter values.
Examples
>>> from pgmpy.factors.hybrid import FunctionalCPD >>> from pgmpy.models import FunctionalBayesianNetwork >>> import numpy as np >>> import pyro.distributions as dist
>>> model = FunctionalBayesianNetwork([("x1", "x2")]) >>> x1 = np.random.normal(0.2, 0.8, size=10000) >>> x2 = np.random.normal(0.6 + x1, 1) >>> data = pd.DataFrame({"x1": x1, "x2": x2})
>>> def x1_fn(parents): ... mu = pyro.param("x1_mu", torch.tensor(1.0)) ... sigma = pyro.param("x1_sigma", torch.tensor(1.0), constraint=constraints.positive) ... return dist.Normal(mu, sigma)
>>> def x2_fn(parents): ... intercept = pyro.param("x2_inter", torch.tensor(1.0)) ... sigma = pyro.param("x2_sigma", torch.tensor(1.0), constraint=constraints.positive) ... return dist.Normal(intercept + parents['x1'], sigma)
>>> cpd1 = FunctionalCPD("x1", fn=x1_prior) >>> cpd2 = FunctionalCPD('x2', fn=x2_prior, parents=['x1']) >>> model.add_cpds(cpd1, cpd2) >>> params = model.fit(data, method="SVI", num_steps=100) >>> print(params)
>>> def prior_fn(): ... return {"x1_mu": dist.Uniform(0, 1), "x1_sigma": dist.HalfNormal(5), ... "x2_inter": dist.Normal(1.0), "x2_sigma": dist.HalfNormal(1)}
>>> def x1_fn(priors, parents): ... return dist.Normal(priors["x1_mu"], priors["x1_sigma"])
>>> def x2_fn(priors, parents): ... return dist.Normal(priors["x2_inter"] + parent['x1'], priors["x2_sigma"])
>>> cpd1 = FunctionalCPD("x1", fn=x1_fn) >>> cpd2 = FunctionalCPD('x2', fn=x2_fn, parents=['x1']) >>> model.add_cpds(cpd1, cpd2)
>>> params = model.fit(data, method="MCMC", prior_fn=prior_fn, num_steps=100) >>> print(params["x1_mu"].mean(), params["x1_std"].mean())
- get_cpds(node=None)[source]¶
Returns the cpd of the node. If node is not specified returns all the CPDs that have been added till now to the graph
Parameter¶
- node: any hashable python object (optional)
The node whose CPD we want. If node not specified returns all the CPDs added to the model.
- rtype:
A list of Functional CPDs.
Examples
>>> from pgmpy.factors.hybrid import FunctionalCPD >>> from pgmpy.models import FunctionalBayesianNetwork >>> import numpy as np >>> import pyro.distributions as dist
>>> model = FunctionalBayesianNetwork([("x1", "x2"), ("x2", "x3")]) >>> cpd1 = FunctionalCPD("x1", lambda _: dist.Normal(0, 1)) >>> cpd2 = FunctionalCPD("x2", lambda parent: dist.Normal(parent["x1"] + 2.0, 1), parents=["x1"]) >>> cpd3 = FunctionalCPD("x3", lambda parent: dist.Normal(parent["x2"] + 0.3, 2), parents=["x2"]) >>> model.add_cpds(cpd1, cpd2, cpd3) >>> model.get_cpds()
- remove_cpds(*cpds)[source]¶
Removes the given cpds from the model.
- Parameters:
*cpds (FunctionalCPD objects) – A list of FunctionalCPD objects that need to be removed from the model.
Examples
>>> from pgmpy.factors.hybrid import FunctionalCPD >>> from pgmpy.models import FunctionalBayesianNetwork >>> import numpy as np >>> import pyro.distributions as dist
>>> model = FunctionalBayesianNetwork([("x1", "x2"), ("x2", "x3")]) >>> cpd1 = FunctionalCPD("x1", lambda _: dist.Normal(0, 1)) >>> cpd2 = FunctionalCPD("x2", lambda parent: dist.Normal(parent["x1"] + 2.0, 1), parents=["x1"]) >>> cpd3 = FunctionalCPD("x3", lambda parent: dist.Normal(parent["x2"] + 0.3, 2), parents=["x2"]) >>> model.add_cpds(cpd1, cpd2, cpd3) >>> for cpd in model.get_cpds(): ... print(cpd)
>>> model.remove_cpds(cpd2, cpd3) >>> for cpd in model.get_cpds(): ... print(cpd)
- simulate(n_samples=1000, seed=None)[source]¶
Simulate samples from the model.
- Parameters:
- Returns:
Simulated samples with columns corresponding to network variables
- Return type:
pandas.DataFrame
Examples
>>> from pgmpy.factors.hybrid import FunctionalCPD >>> from pgmpy.models import FunctionalBayesianNetwork >>> import numpy as np >>> import pyro.distributions as dist
>>> model = FunctionalBayesianNetwork([("x1", "x2"), ("x2", "x3")]) >>> cpd1 = FunctionalCPD("x1", lambda _: dist.Normal(0, 1)) >>> cpd2 = FunctionalCPD("x2", lambda parent: dist.Normal(parent["x1"] + 2.0, 1), parents=["x1"]) >>> cpd3 = FunctionalCPD("x3", lambda parent: dist.Normal(parent["x2"] + 0.3, 2), parents=["x2"]) >>> model.add_cpds(cpd1, cpd2, cpd3) >>> model.simulate(n_samples=1000)