如何使用 bnlearn 和 graphviz 绘制具有实例化节点的贝叶斯网络?

How do I graph a Bayesian Network with instantiated nodes using bnlearn and graphviz?

我正在尝试使用库 bnlearnRgraphviz 绘制具有实例化节点的贝叶斯网络 (BN)。我的工作流程如下:

用随机数据(我实际使用的数据显然不是随机的)创建数据框后,我将数据离散化,构造学习有向无环图(DAG),将数据拟合到DAG,然后绘制DAG。我还绘制了一个 DAG,它显示了每个节点的后验概率。

#rm(list = ls())
library(bnlearn)
library(Rgraphviz)

# Generating random dataframe
data_clean <- data.frame(a = runif(min = 0, max = 100, n = 1000),
                         b = runif(min = 0, max = 100, n = 1000),
                         c = runif(min = 0, max = 100, n = 1000),
                         d = runif(min = 0, max = 100, n = 1000),
                         e = runif(min = 0, max = 100, n = 1000))

# Discretising the data into 3 bins
bins <- 3
data_discrete <- discretize(data_clean, breaks = bins)

# Creating factors for each bin in the data
lv <- c("low", "med", "high")

for (i in names(data_discrete)){
  levels(data_discrete[, i]) = lv
}

# Structure learning the DAG from the training set
whitelist <- matrix(c("a", "b",
                      "b", "c",
                      "c", "e",
                      "a", "d",
                      "d", "e"),
                    ncol = 2, byrow = TRUE, dimnames = list(NULL, c("from", "to")))

bn.hc <- hc(data_discrete, whitelist = whitelist)

# Plotting the DAG
dag.hc <- graphviz.plot(bn.hc,
                        layout = "dot")

# Fitting the data to the structure
fitted <- bn.fit(bn.hc, data = data_discrete, method = "bayes")

# Plotting the DAG with posteriors
graphviz.chart(fitted, type = "barprob", layout = "dot")

接下来我要做的是手动更改 bn.fit 对象中的分布,分配给 fitted,然后绘制一个 DAG,显示实例化节点和更新后的后验概率响应变量 e.

# Manually instantiating
fitted_evidence <- fitted

cpt.a = matrix(c(1, 0, 0), ncol = 3, dimnames = list(NULL, lv))

cpt.c = c(1, 0, 0,
          0, 1, 0,
          0, 0, 1)
dim(cpt.c) <- c(3, 3)
dimnames(cpt.c) <-  list("c" = lv, "b" =  lv)

cpt.b = c(1, 0, 0,
          0, 1, 0,
          0, 0, 1)
dim(cpt.b) <- c(3, 3)
dimnames(cpt.b) <-  list("b" = lv, "a" =  lv)

cpt.d = c(0, 0, 1,
          0, 1, 0,
          1, 0, 0)
dim(cpt.d) <- c(3, 3)
dimnames(cpt.d) <-  list("d" = lv, "a" =  lv)

fitted_evidence$a <- cpt.a
fitted_evidence$b <- cpt.b
fitted_evidence$c <- cpt.c
fitted_evidence$d <- cpt.d

# Plotting the DAG with instantiation and posterior for response
graphviz.chart(fitted_evidence, type = "barprob", layout = "dot")

这是我得到的结果,但我的实际 BN 更大,弧更多,手动更改 bn.fit 对象是不切实际的。

我想知道是否有一种方法可以在不手动更改 bn.fit 对象的情况下通过实例化绘制 DAG?是否有我缺少的解决方法或功能?

我 think/hope 我已经通读了 bnlearn 的文档。感谢任何反馈,如果我没有足够清楚地表达我的想法,我很乐意更改问题中的任何内容。

谢谢。

如何使用 cpdist 根据证据从后验中抽取样本。然后,您可以使用 cpdist 个样本使用 bn.fit 估计更新后的参数。然后像以前一样绘制。

一个例子:

set.seed(69184390) # for sampling

# Your evidence vector
ev <- list(a = "low", b="low", c="low", d="high")

# draw samples
updated_dat <- cpdist(fitted, nodes=bnlearn::nodes(fitted), evidence=ev, method="lw", n=1e6)

# refit : you'll get warnings over missing levels
updated_fit <- bn.fit(bn.hc, data = updated_dat)

# plot
par(mar=rep(0,4))
graphviz.chart(updated_fit, type = "barprob", layout = "dot")

注意我使用了 bnlearn::nodes,因为 nodesRgraphviz 的依赖项掩盖了。我倾向于最后加载 bnlearn