【问题标题】:Sample from a Bayesian network in pomegranate石榴中贝叶斯网络的样本
【发布时间】:2018-06-26 05:14:13
【问题描述】:

我在石榴中使用from_samples() 构建了一个贝叶斯网络。我可以使用model.predict() 从模型中获得最大可能的预测。我想知道是否有一种方法可以有条件地(或无条件地)从这个贝叶斯网络中采样?即是否有来自网络的随机样本而不是最大可能的预测?

我看了model.sample(),但它正在提高NotImplementedError

另外,如果使用 pomegranate 无法做到这一点,还有哪些其他库对 Python 中的贝叶斯网络非常有用?

【问题讨论】:

    标签: python machine-learning python-3.5 bayesian-networks pomegranate


    【解决方案1】:

    只是为了用一个具体的例子来阐明上述答案,以便对某人有所帮助,让我们从以下简单的数据集开始(包含 4 个变量和 5 个数据点):

    import pandas as pd
    df = pd.DataFrame({'A':[0,0,0,1,0], 'B':[0,0,1,0,0], 'C':[1,1,0,0,1], 'D':[0,1,0,1,1]})
    df.head()
    
    #   A   B   C   D
    #0  0   0   1   0
    #1  0   0   1   1
    #2  0   1   0   0
    #3  1   0   0   1
    #4  0   0   1   1 
    

    现在我们用'exact'算法和pomegranate从以上数据中学习贝叶斯网络结构(使用DP/A*学习最优BN结构),使用如下代码sn-p

    import numpy as np
    from pomegranate import *
    model = BayesianNetwork.from_samples(df.to_numpy(), state_names=df.columns.values, algorithm='exact')
    # model.plot()
    

    学习的 BN 结构和对应的 CPT 如下图所示

    从上图可以看出,准确的解释了数据。我们可以使用模型计算数据的对数似然如下:

    np.sum(model.log_probability(df.to_numpy()))
    # -7.253364813857112
    

    一旦学习了BN结构,我们就可以从BN中采样如下:

    model.sample()  
    # array([[0, 1, 0, 0]], dtype=int64)
    

    作为旁注,如果我们使用algorithm='chow-liu' 代替(它找到一个快速近似的树状结构),我们将获得以下BN:

    这次数据的对数似然是

    np.sum(model.log_probability(df.to_numpy()))
    # -8.386987635761297
    

    这表明算法exact找到了更好的估计。

    【讨论】:

    • 您是如何打印上图中的 CPT 的? model.plot() 仅显示没有 CPT 的节点/边。
    【解决方案2】:

    如果我正确查看提交历史记录,model.sample()should have been implemented 到此为止。

    您可以查看PyMC,它也支持分发混合。 但是,我不知道任何其他具有类似工厂方法的工具箱,例如 pomogranate 中的from_samples()

    【讨论】:

    【解决方案3】:

    从“烘焙”贝叶斯网络中采样的一种方法是使用 predict_proba 方法。 predict_proba 根据提供的信息返回与未提供信息的每个节点对应的分布列表。

    例如:

    bn = BayesianNetwork.from_samples(X)
    proba = bn.predict_proba({"1":1,"2":0}) # proba will be an array of dists
    samples = np.empty_like(proba)
    for i in np.arange(proba.shape[0]):
        for j in np.arange(proba.shape[1]):
            if hasattr(proba[i][j],'sample'):
                samples[i,j] = proba[i][j].sample(10000).mean() #sample and aggregate however you want
            else:
                samples[i,j] = proba[i][j]
    pd.Series(samples,index=X.columns) #convert samples to a pandas.Series with column labels as index
    

    【讨论】:

      猜你喜欢
      • 2013-04-08
      • 2011-01-09
      • 2012-07-14
      • 2013-05-11
      • 2013-07-19
      • 2019-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多