Parameter Learning
Parameter learning fills in the conditional probability tables of a Bayesian network from data, given its structure [2]. You supply the graph — which nodes exist and how they depend on one another — and a dataset of observations; the learned network is a fully-specified BayesianNetwork, ready for inference once ordered.
The structure is described by a DirectAcyclicGraph: nodes and edges, plus optional declared states, but no probabilities. It is a lightweight input type, not a network — it supports add_node!, parents, children, and gplot, but none of the operations that need CPTs (order!, infer, sample).
Declaring the structure
Build the DAG top-down with add_node!, listing each node's parents (which must already be present — add parents before children). Edges are wired for you as you declare the parents.
dag = DirectAcyclicGraph()
add_node!(dag, :W) # root
add_node!(dag, :R; parents = [:W]) # edge :W -> :R wired here
add_node!(dag, :P; parents = [:W])
add_node!(dag, :G; parents = [:R, :P])Each node's domain is taken from the data at learn time. Any states passed to add_node! are added to that domain — states you want to keep even if they never occur in the dataset. They end up in the learned CPT with probability 0 (or an alpha-smoothed mass):
add_node!(dag, :W, [:foggy]) # :sunny/:cloudy come from data; :foggy guaranteedLearning the parameters
learn estimates the CPTs and chooses the algorithm from the data: complete data uses maximum likelihood, data with any missing entries uses Expectation-Maximization. It returns a BayesianNetwork; call order! on it before inference or sampling.
using DataFrames
df = DataFrame(W = [:sunny, :sunny, :cloudy, :cloudy],
S = [:on, :off, :on, :off])
dag = DirectAcyclicGraph()
add_node!(dag, :W)
add_node!(dag, :S; parents = [:W])
learned = learn(dag, df) # complete data -> MLE
order!(learned)alpha is a Laplace/Dirichlet pseudo-count applied by both algorithms; max_iter and tol control EM's convergence:
learn(dag, df; alpha = 1) # add-one smoothing
learn(dag, df_with_missing; tol = 1e-6, max_iter = 500)To force a specific algorithm, call it directly.
Maximum likelihood
learn_parameters_mle is the closed-form estimator for complete data. For every node
where alpha the pseudo-count (alpha = 0 is pure maximum likelihood; alpha > 0 smooths, keeping never-observed states off exactly 0). A parent configuration that never appears in the data falls back to a uniform distribution.
learned = learn_parameters_mle(dag, df; alpha = 1)
order!(learned)Expectation-Maximization
When some entries are missing, learn_parameters_em estimates the CPTs iteratively by Expectation-Maximization [12]. Starting from uniform tables, each iteration performs:
an E-step — every row with missing values is expanded into all completions of its missing variables, each weighted by
under the current network; fully-observed rows keep weight 1;an M-step — the CPTs are re-estimated by the same counting as maximum likelihood, summing these fractional weights instead of counting whole rows.
Iteration stops when no CPT entry moves by more than tol, or after max_iter steps. Because EM converges only to a local optimum, the (uniform) initialization matters. With no missing values it reduces exactly to learn_parameters_mle.
learned = learn_parameters_em(dag, df_with_missing; alpha = 1, tol = 1e-6)
order!(learned)Both estimators leave the input dag untouched, so the same structure can be relearned on different datasets or with different smoothing.