1 个不稳定版本
0.1.0 | 2019年7月10日 |
---|
#15 in #propagation
21KB
310 行
Loopy 贝叶斯网络
贝叶斯网络 Loopy 信念传播算法的实现
贝叶斯网络 & Loopy 信念传播
贝叶斯网络可以用来编码事件之间的一组因果或逻辑概率依赖关系。它们以有向无环图的形式出现,每个节点都与一个概率表相关联,该表定义了节点在其父节点值的情况下,取每个可能值的概率。有关详细信息,您可以查看 维基百科。
Loopy 信念传播算法是一种计算网络中每个节点边缘概率分布近似的算法,条件是选择的一组“观察”变量的值,这些值事先已设置。
这是一个近似值,其行为就好像每个节点的父节点在给定节点的情况下条件独立一样。只有在考虑的图实际上是一棵树(没有无向环)的情况下,这种近似才是准确的。
该算法的一个典型失败案例是当某些节点的父节点既高度相关又非常随机时(这在 simple_net
示例中特别明显 ;))。在这种情况下,即使算法收敛(并不总是如此),它也很可能收敛到一个错误值。
另一方面,对于观察值几乎肯定可以确定网络中其余部分值的网络(这在现实世界问题中通常是情况),Loopy 信念传播算法提供了一个非常好的近似(例如,请参见 arXiv:1301.6725 上的研究)。
如何使用此 crate
此 crate 允许您给定一个完全指定的贝叶斯网络和一组观察值,在网络上迭代运行 Loopy 信念传播算法。
use loopybayesnet::BayesNet;
use ndarray::{Array1, Array2};
let mut net = BayesNet::new();
// First insert your modes to create your network
let node1 = net.insert_node_from_probabilities(
&[], // This node does not have any parent,
Array1::from(vec![0.2, 0.3, 0.5]) // This node can take 3 values, and these are the
// associated prior probabilities
);
let node2 = net.insert_node_from_probabilities(
&[node1], // This node has node1 as a parent
Array2::from(vec![ // This node can take 2 values
[0.4, 0.3, 0.7], // these are the probabilities of value 0 depending on the value of node1
[0.6, 0.7, 0.3], // these are the probabilities of value 1 depending on the value of node1
])
);
// Now that the net is set, we can run the algorithm
// Reset the internal state which is kept, as the algorithm is iterative
net.reset_state();
// Set as evidence that node2 = 0
net.set_evidence(&[(node2, 0)]);
for _ in range 0..3 {
// Iterate over the steps of the algorithms until convergence.
// As a rule of thumb, the number of necessary iterations is often of the same order as the
// diameter of the graph, but it may be longer with graphs containing loops.
net.step();
// between each step we can observe the current state of the algorithm
let beliefs = net.beliefs();
// the algorithm works internally with log-probabilities for numerical stability
// the `.as_probabilities()` call converts them back to regular normalized probabilities.
println!("Marginals for node1: {:?", beliefs[node1].as_probabilities());
println!("Marginals for node2: {:?", beliefs[node2].as_probabilities());
}
实现质量
考虑到算法本身相当清晰易懂,并且 ndarray
处理了困难的部分,因此实现应该是基本上正确的。
但我没有尝试优化性能,所以它可能在具有许多值和每个节点的许多父节点的非常大的图上运行缓慢。
依赖项
~2MB
~33K SLoC