生成非二进制贝叶斯网络时出错

2024-10-05 13:19:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个类来生成贝叶斯网络,BayesNode为网络生成节点,BayesNet在名为probabilityPlus.py的文件中生成网络

class BayesNode:
   """A conditional probability distribution, P(X | parents). Part of a BayesNet."""

    def __init__(self, X, parents, cpt):
        """X is a variable name, and parents a sequence of variable
        names or a space-separated string. cpt, the conditional
        probability table, takes one of these forms:

        * A number, the unconditional probability P(X=true). You can
          use this form when there are no parents.

        * A dict {v: p, ...}, the conditional probability distribution
          P(X=true | parent=v) = p. When there's just one parent.

        * A dict {(v1, v2, ...): p, ...}, the distribution P(X=true |
          parent1=v1, parent2=v2, ...) = p. Each key must have as many
          values as there are parents. You can use this form always;
          the first two are just conveniences.

        In all cases the probability of X being false is left implicit,
        since it follows from P(X=true).
        """
        if isinstance(parents, str):
            parents = parents.split()

        # We store the table always in the third form above.
        if isinstance(cpt, (float, int)):  # no parents, 0-tuple
            cpt = {(): cpt}
        elif isinstance(cpt, dict):
            # one parent, 1-tuple
            if cpt and isinstance(list(cpt.keys())[0], bool):
                cpt = {(v,): p for v, p in cpt.items()}

        assert isinstance(cpt, dict)
        for vs, p in cpt.items():
            assert isinstance(vs, tuple) and len(vs) == len(parents)      #line 163 »for ERROR MESSAGE
            assert all(isinstance(v, bool) for v in vs)
            assert 0 <= p <= 1

        self.variable = X
        self.parents = parents
        self.cpt = cpt
        self.children = []

    def p(self, value, event):
        """Return the conditional probability
        P(X=value | parents=parent_values), where parent_values
        are the values of parents in event. (event must assign each
        parent a value.)"""
        assert isinstance(value, bool)
        ptrue = self.cpt[event_values(event, self.parents)]
        return ptrue if value else 1 - ptrue

    def sample(self, event):
        """Sample from the distribution for this variable conditioned
        on event's values for parent_variables. That is, return True/False
        at random according with the conditional probability given the
        parents."""
        return probability(self.p(True, event))

    def __repr__(self):
        return repr((self.variable, ' '.join(self.parents)))

class BayesNet:
    """Bayesian network"""

    def __init__(self, node_specs=None):
        """Nodes must be ordered with parents before children."""
        self.nodes = []
        self.variables = []
        node_specs = node_specs or []
        for node_spec in node_specs:
            self.add(node_spec)           #line 207 »for ERROR MESSAGE

    def add(self, node_spec):
        """Add a node to the net. Its parents must already be in the
        net, and its variable must not."""
        node = BayesNode(*node_spec)           #line 212 »for ERROR MESSAGE
        assert node.variable not in self.variables
        assert all((parent in self.variables) for parent in node.parents)
        self.nodes.append(node)
        self.variables.append(node.variable)
        for parent in node.parents:
            self.variable_node(parent).children.append(node.variable)

    def variable_node(self, var):
        """Return the node for the variable named var.
        """
        for n in self.nodes:
            if n.variable == var:
                return n
        raise Exception("No such variable: {}".format(var))

    def variable_values(self, var):
        """Return the domain of var."""   
        return [True, False]

    def __repr__(self):
        return 'BayesNet({0!r})'.format(self.nodes)

当我这样做时,它运行没有问题:

T, F = True, False

burglary = BayesNet([
    ('Burglary', '', 0.001),
    ('Earthquake', '', 0.002),
    ('Alarm', 'Burglary Earthquake',
     {(T, T): 0.95, (T, F): 0.94, (F, T): 0.29, (F, F): 0.001}),
    ('JohnCalls', 'Alarm', {T: 0.90, F: 0.05}),
    ('MaryCalls', 'Alarm', {T: 0.70, F: 0.01})
])

burglary

返回:

BayesNet([('Burglary', ''), ('Earthquake', ''), ('Alarm', 'Burglary Earthquake'), ('JohnCalls', 'Alarm'), ('MaryCalls', 'Alarm')])

很好,然后我做burglary.variables,它就会回来

['Burglary', 'Earthquake', 'Alarm', 'JohnCalls', 'MaryCalls']

就像它应该但是当我尝试时:

T, F = True, False

burglary2 = BayesNet([
    ('Burglary', '', 0.001),
    ('Earthquake', '', {"strong":1,"light":10,"none":89 }),
    ('Alarm', 'Burglary Earthquake',
     {(T, 'strong'): 0.95, (T, 'light'): 0.80, (T, 'none'): 0.76, (F, 'strong'): 0.8, (F, 'light'): 0.3, (F, 'none'): 0.001}),
    ('JohnCalls', 'Alarm', {T: 0.90, F: 0.05}),
    ('MaryCalls', 'Alarm', {T: 0.70, F: 0.01})
])

burglary2

结果发现这个错误

ERROR MESSAGE

而且(逻辑上)不允许我对最后一个网络做任何事情;但我不明白为什么以及如何修复它。有人知道出了什么问题以及如何解决吗


Tags: theinselfeventnodefordefvariable

热门问题