我在学习使用 bnlearn
时,在下面的代码最后一行总是遇到以下错误:
在 custom.fit(dag, cpt) 中的错误:条件概率分布数量错误
我做错了什么?
modelstring(dag)= "[s][r][nblw|r][nblg|nblw][mlw|s:r][f|s:r:mlw][mlg|mlw:f] [mlgr|mlg:nblg]" ###View DAG Specifics dag arcs(dag) nodes(dag) # Create Levels State <- c("State0", "State1") ##Create probability distributions given; these are all 2d b/c they have 1 or 2 nodes cptS <- matrix(c(0.6, 0.4), ncol=2, dimnames=list(NULL, State)) cptR <- matrix(c(0.7, 0.3), ncol=2, dimnames=list(NULL, State)) cptNBLW <- matrix(c(0.95, 0.05, 0.05, 0.95), ncol=2, dimnames=list(NULL, "r"= State)) cptNBLG <- matrix(c(0.9, 0.099999999999999998, 0.2, 0.8), ncol=2, dimnames=list(NULL, "nblw"=State)) cptMLG <- matrix(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),ncol=2,nrow = 2, dimnames=list("mlw"= State, "f"=State)) cptMLGR <- matrix(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45),ncol=2,nrow = 2, dimnames=list("mlg"= State, "nblg"=State)) cptMLW <-matrix(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), ncol=2,nrow = 2,byrow = TRUE, dimnames=list("r"= State, "s"=State)) # Build 3-d matrices( becuase you have 3 nodes, you can't use the matrix function; you have to build it from scratch) cptF <- c(0.05, 0.95, 0.4, 0.6, 0.9, 0.1, 0.99, 0.01, 0.9, 0.1, 0.95, 0.05, 0.95, 0.05, 0.99, 0.01) dim(cptF) <- c(2, 2, 2, 2) dimnames(cptF) <- list("s"=State, "r"=State, "mlw"=State) ###Create CPT Table cpt <- list(s = cptS, r = cptR, mlw = cptMLW,nblw= cptNBLW, mlg= cptMLG, nblg= cptNBLG, mlgr= cptMLGR) # Construct BN network with Conditional Probability Table S.net <- custom.fit(dag,cpt)
参考资料: https://rpubs.com/sarataheri/bnlearnCGM
回答:
你的条件概率表(CPT)定义中有几个错误。主要需要确保以下几点:
- 提供的概率数量等于子节点和父节点状态数量的乘积,
- 矩阵/数组的维度数量等于父节点数量加一,用于子节点,
- 当节点维度大于一时,子节点应在第一维度给出,
- 在
dimnames
参数中给出的名称(例如dimnames=list(ThisName = ...)
中的名称)应与在DAG中定义的名称匹配,在你的例子中是通过modelstring
定义的,而在我的回答中是通过model2network
定义的。(所以我之前建议使用dimnames=list(cptNBLW = ...)
应该改为dimnames=list(nblw = ...)
,以匹配模型字符串中节点nblw
的声明方式)
你还未将节点 f
添加到你的 cpt 列表中。
以下是你的代码,添加了注释说明修改的地方。(我已经注释掉了有问题的行,并在其后添加了正确的代码)
library(bnlearn)dag <- model2network("[s][r][nblw|r][nblg|nblw][mlw|s:r][mlg|mlw:f][mlgr|mlg:nblg][f|s:r:mlw]")State <- c("State0", "State1")cptS <- matrix(c(0.6, 0.4), ncol=2, dimnames=list(NULL, State))cptR <- matrix(c(0.7, 0.3), ncol=2, dimnames=list(NULL, State)) # 将子节点添加到 dimnames 的第一位置cptNBLW <- matrix(c(0.95, 0.05, 0.05, 0.95), ncol=2, dimnames=list(nblw=State, "r"= State))cptNBLG <- matrix(c(0.9, 0.099999999999999998, 0.2, 0.8), ncol=2, dimnames=list(nblg=State,"nblw"=State)) # 使用3维数组而不是矩阵,并将子节点添加到 dimnames 中# cptMLG <- matrix(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),ncol=2,nrow = 2, dimnames=list("mlw"= State, "f"=State))cptMLG <- array(c(0.95, 0.05, 0.4, 0.6, 0.2, 0.8, 0.05, 0.95),dim=c(2,2,2), dimnames=list(mlg = State, "mlw"= State, "f"=State))# cptMLGR <- matrix(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45),ncol=2,nrow = 2, dimnames=list("mlg"= State, "nblg"=State))cptMLGR <- array(c(0.6,0.4,0.95,0.05,0.2,0.8,0.55,0.45), dim=c(2,2,2), dimnames=list(mlgr=State, "mlg"= State, "nblg"=State))# cptMLW <-matrix(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), ncol=2,nrow = 2,byrow = TRUE, dimnames=list("r"= State, "s"=State))cptMLW <-array(c(0.95, 0.05, 0.1, 0.9, 0.2, 0.8, 0.01, 0.99), dim=c(2,2,2), dimnames=list(mlw=State, "r"= State, "s"=State))# 将子节点添加到 dimnames 的第一位置cptF <- c(0.05, 0.95, 0.4, 0.6, 0.9, 0.1, 0.99, 0.01, 0.9, 0.1, 0.95, 0.05, 0.95, 0.05, 0.99, 0.01)dim(cptF) <- c(2, 2, 2, 2)dimnames(cptF) <- list("f" = State, "s"=State, "r"=State, "mlw"=State)# 添加缺失的节点 f 到列表中cpt <- list(s = cptS, r = cptR, mlw = cptMLW,nblw= cptNBLW, mlg= cptMLG, nblg= cptNBLG, mlgr= cptMLGR, f=cptF) # 使用条件概率表构建贝叶斯网络S.net <- custom.fit(dag, dist=cpt)