libpgm使用经验

这里的libpgm是用于概率图模型的python库,其文档地址为http://pythonhosted.org/libpgm/
这里主要用libpgm进行贝叶斯网络(bayesian network)的学习和推理。当前libpgm的最新版本为1.3。

相关的库

如果你需要寻找支持贝叶斯网络的库,可以参考stackoverflow上的这个问题:Create Bayesian Network and learn parameters with Python3.x

我的项目中需要进行贝叶斯网络的结构学习和参数学习,在使用libpgm之前也找了不少的库:

  1. Weka是一个很强大的数据分析工具,它提供了Java接口,可以进行贝叶斯网络的学习。但是它需要指定一个属性作为类属性,我的项目里类属性有多个,无法进行这样的指定。在Weka的GUI界面中,它直接将贝叶斯网络作为一种分类方法,这与我的需求不太符合。也有人提到可以不指定类属性,这里没有再进一步调研。如果想要利用Weka进行贝叶斯网络相关的计算,这里有两个链接可以参考

    create bayesian network with random cpt values by java code
    How to learn a Bayesian Network (structure+parameters) with the WEKA API?

  2. matlab中有一个Bayesian Network Toolbox,可以进行贝叶斯网络的学习和推理。matlab本身是一个收费软件,而且过于庞大。

  3. Jayes是一个Java库,它被eclipse用于代码推荐。但是目前不支持网络的学习。进一步了解可以参考An Introduction to Bayesian Networks with Jayes
  4. pgmpy是一个python库,目前更新还很频繁。但是还没有支持网络结构的学习。
  5. libpgm支持结构学习、参数学习,文档也比较简单。

遇到的问题

在libpgm实际使用中遇到了一些问题:

  1. 训练速度慢
    我的数据集中,共有13000条记录,每条记录共有200多个属性,每个属性都是二值的。训练一次,大约需要30多个小时。由于没有试过别的库,不清楚是库的问题还是什么问题。
    这样的速度是不能接受的。最后的解决办法是,用scikit learn库,先进行一遍特征选择,挑选出一些比较相关的特征做进一步的贝叶斯网络学习。

  2. 调用libpgm的函数进行结构学习出错
    调用discrete_constraint_estimatestruct函数进行贝叶斯网络的学习,有时候会返回图中存在环(Graph contains a cycle)的错误:

    Traceback (most recent call last):
    File “fs.py”, line 77, in
    result = learner.discrete_constraint_estimatestruct(bn_data)
    File “/Users/zhuting/Projects/PyWorkspace/BayesianNet/venv/lib/python2.7/site-packages/libpgm/pgmlearner.py”, line 590, in discrete_constraint_estimatestruct
    pdag.toporder()
    File “/Users/zhuting/Projects/PyWorkspace/BayesianNet/venv/lib/python2.7/site-packages/libpgm/graphskeleton.py”, line 146, in toporder
    assert (not Ecopy), (“Graph contains a cycle”, Ecopy)
    AssertionError: (‘Graph contains a cycle’, [[164, 21], [21, 58], [21, 16], [16, 11], [58, 164], [11, 67], [16, 2], [164, 2]])

    这是不太能理解的,提供数据进行学习,竟然会学习失败,学出一个有环的图。
    查看libpgm的库源码发现,iscrete_constraint_estimatestruct实际就是先调用 discrete_constraint_estimatestruct再调用discrete_mle_estimateparams,即先结构学习,再参数学习。在结构学习的最后,会进行toporder拓扑排序,从而发现图中的环。这里感觉上是不合理的,在结构学习的过程中就应该保证不会出现环,结构学习完成后发现有环,已经没有办法处理了。

    最后想了一个取巧的办法,在拓扑排序前加入一段代码,保证图中不会有环。

    newE = []
    for e in self.E:
        if e[0] > e[1]:
            e.reverse()
        newE.append(e)
    self.E = newE

    代码很容易理解,人为地给节点一个大小顺序,只允许小的节点指向大的节点。如果某条边不符合,则交换边的出点和入点。很显然这样是能够保证图中不会出现环的。实际测试发现,这样修改之后,不会再出现图中存在环的错误。

你可能感兴趣的:(libpgm使用经验)