在Python中学习和使用增强贝叶斯分类器

16 投票
5 回答
5525 浏览
提问于 2025-04-17 16:08

我想在 python 中使用一种叫做森林增强贝叶斯分类器的东西(或者说树状贝叶斯分类器),首先要学习它的结构和参数,然后用它来进行离散分类,并获取那些有缺失数据的特征的概率。(这就是为什么单纯的离散分类和一些简单的分类器对我来说不是很有用的原因。)

我的数据是以一种特定的方式输入的,我希望能从不完整的数据中进行增量学习,但我在文献中找不到同时满足这两个条件的东西,所以任何能进行结构和参数学习以及推断的东西对我来说都是好答案。

似乎有一些不太相关且没有维护的 python 包大致朝这个方向发展,但我没有看到任何比较新的东西(例如,我认为使用 pandas 来进行这些计算是合理的,但 OpenBayes 几乎不使用 numpy),而增强分类器在我看到的内容中似乎完全缺失。

那么,我应该去哪里寻找可以节省我实现森林增强贝叶斯分类器的工作呢?有没有好的实现 Pearl 消息传递算法的 python 类,或者说这对于增强贝叶斯分类器来说不合适?有没有其他语言中可读的面向对象的实现,能够用于学习和推断 TAN 贝叶斯分类器,并可以翻译成 python?


我知道的一些现有包,但觉得不合适的有:

  • milk,它支持分类,但不支持贝叶斯分类器(而且我确实需要分类和未指定特征的概率)
  • pebl,它只做结构学习
  • scikit-learn,它只学习简单的贝叶斯分类器
  • OpenBayes,自从有人把它从 numarray 移植到 numpy 后几乎没有变化,文档也很少。
  • libpgm,它声称支持一组不同的功能。根据主要文档,它可以进行推断、结构和参数学习,但似乎没有任何精确推断的方法。
  • Reverend 声称是一个“贝叶斯分类器”,文档几乎没有,从源代码来看,我得出的结论是它主要是一个垃圾邮件分类器,依据 Robinson 和类似的方法,而不是一个真正的贝叶斯分类器。
  • eBay 的 bayesian 信念网络 允许构建通用的贝叶斯网络,并在其上实现推断(包括精确和近似),这意味着可以用来构建 TAN,但里面没有学习算法,贝叶斯网络的构建方式使得实现参数学习比假设的其他实现要困难。

5 个回答

2

R语言的bnlearn包里有朴素贝叶斯和树增强朴素贝叶斯分类器的实现。你可以使用rpy2这个工具把它们移植到Python中。

http://cran.r-project.org/web/packages/bnlearn/bnlearn.pdf

3

我之前也对如何使用libpgm进行精确推断感到困惑。不过,结果发现这是可能的。比如说,在libpgm的文档中有相关的例子。

import json

from libpgm.graphskeleton import GraphSkeleton
from libpgm.nodedata import NodeData
from libpgm.discretebayesiannetwork import DiscreteBayesianNetwork
from libpgm.tablecpdfactorization import TableCPDFactorization

# load nodedata and graphskeleton
nd = NodeData()
skel = GraphSkeleton()
nd.load("../tests/unittestdict.txt")
skel.load("../tests/unittestdict.txt")

# toporder graph skeleton
skel.toporder()

# load evidence
evidence = dict(Letter='weak')
query = dict(Grade='A')

# load bayesian network
bn = DiscreteBayesianNetwork(skel, nd)

# load factorization
fn = TableCPDFactorization(bn)

# calculate probability distribution
result = fn.condprobve(query, evidence)

# output
print json.dumps(result.vals, indent=2)
print json.dumps(result.scope, indent=2)
print json.dumps(result.card, indent=2)
print json.dumps(result.stride, indent=2)

要让这个例子正常运行,这里有一个数据文件(我把None替换成了null,然后保存为.json格式)。

我知道我来得有点晚,但这是我在寻找用Python做贝叶斯网络的资源时找到的最好的一篇帖子。我想回答一下,以防其他人也在找这个。(抱歉,我本来想评论的,但我刚注册了SO来回答这个问题,声望还不够高。)

5

我觉得目前没有现成的 随机朴素贝叶斯 分类器的实现(至少我不知道有),因为这还是个学术问题。下面这篇论文介绍了如何将随机森林和朴素贝叶斯分类器结合起来(需要付费才能查看): http://link.springer.com/chapter/10.1007%2F978-3-540-74469-6_35

我建议你使用 scikit-learn,这是Python中最流行的统计模块之一(还有 NLTK),而且文档非常完善。

scikit-learn 有一个随机森林模块: http://scikit-learn.org/stable/modules/ensemble.html#forests-of-randomized-trees。里面有一个子模块,可能(我强调一下这个不确定性)可以用来连接到朴素贝叶斯分类器:

RandomTreesEmbedding 实现了一种无监督的数据转换。它使用一片完全随机的树来编码数据,通过数据点最终落在的叶子节点的索引来表示。这个索引以一种一对K的方式编码,形成高维稀疏的二进制编码。这个编码可以非常高效地计算出来,然后可以作为其他学习任务的基础。编码的大小和稀疏性可以通过选择树的数量和每棵树的最大深度来影响。对于每棵树,编码中有一个条目为1。编码的最大大小是 n_estimators * 2 ** max_depth,也就是森林中叶子的最大数量。

由于相邻的数据点更可能落在同一棵树的同一叶子中,这种转换实际上进行了一种隐式的、非参数的密度估计。

当然,还有一个可以增量使用的朴素贝叶斯分类器的外部实现: http://scikit-learn.org/stable/modules/naive_bayes.html

离散的朴素贝叶斯模型可以用来处理大规模的文本分类问题,这种情况下完整的训练集可能无法全部放入内存。为了解决这个问题,MultinomialNB 和 BernoulliNB 提供了一个 partial_fit 方法,可以像其他分类器一样增量使用,具体可以参考文本文件的外部分类。

撰写回答