Ejemplo n.º 1
0
    def query(self, **kwds):

        # Ensure the evidence variables are actually
        # present
        invalid_vars = [v for v in kwds.keys() if v not in self.nodes]
        if invalid_vars:
            raise VariableNotInGraphError(invalid_vars)

        mu, sigma = self.get_joint_parameters()

        # Iteratively apply the evidence...
        result = dict()
        result['evidence'] = kwds

        for k, v in kwds.items():
            x = MeansVector([[v]], names=[k])
            sigma_yy, sigma_yx, sigma_xy, sigma_xx = (sigma.split(k))
            mu_y, mu_x = mu.split(k)
            # See equations (6) and (7) of CK
            mu_y_given_x = MeansVector(
                (mu_y + sigma_yx * sigma_xx.I * (x - mu_x)).rows,
                names=mu_y.name_ordering)
            sigma_y_given_x = CovarianceMatrix(
                (sigma_yy - sigma_yx * sigma_xx.I * sigma_xy).rows,
                names=sigma_yy.name_ordering)
            sigma = sigma_y_given_x
            mu = mu_y_given_x

        result['joint'] = dict(mu=mu, sigma=sigma)
        return result
 def test_get_joint_parameters(self, river_graph):
     mu, sigma = river_graph.get_joint_parameters()
     assert mu == MeansVector([[3], [4], [9], [14]],
                              names=['a', 'b', 'c', 'd'])
     assert sigma == CovarianceMatrix(
         [[4, 4, 8, 12], [4, 5, 8, 13], [8, 8, 20, 28], [12, 13, 28, 42]],
         names=['a', 'b', 'c', 'd'])
    def test_query(self, river_graph):
        result = river_graph.query(a=7)
        mu = result['joint']['mu']
        sigma = result['joint']['sigma']
        assert mu == MeansVector([[8], [17], [26]], names=['b', 'c', 'd'])
        assert sigma == CovarianceMatrix([[1, 0, 1], [0, 4, 4], [1, 4, 6]],
                                         names=['b', 'c', 'd'])

        result = river_graph.query(a=7, c=17)
        mu = result['joint']['mu']
        sigma = result['joint']['sigma']
        assert mu == MeansVector([[8], [26]], names=['b', 'd'])
        assert sigma == CovarianceMatrix([[1, 1], [1, 2]], names=['b', 'd'])

        result = river_graph.query(a=7, c=17, b=8)
        mu = result['joint']['mu']
        sigma = result['joint']['sigma']
        assert mu == MeansVector([[26]], names=['d'])
        assert sigma == CovarianceMatrix([[1]], names=['d'])
Ejemplo n.º 4
0
def build_gbn(*args, **kwds):
    '''Builds a Gaussian Bayesian Graph from
    a list of functions'''
    variables = set()
    name = kwds.get('name')
    variable_nodes = dict()
    factor_nodes = dict()

    if isinstance(args[0], list):
        # Assume the functions were all
        # passed in a list in the first
        # argument. This makes it possible
        # to build very large graphs with
        # more than 255 functions, since
        # Python functions are limited to
        # 255 arguments.
        args = args[0]

    for factor in args:
        factor_args = get_args(factor)
        variables.update(factor_args)
        node = GBNNode(factor)
        factor_nodes[factor.__name__] = node

    # Now lets create the connections
    # To do this we need to find the
    # factor node representing the variables
    # in a child factors argument and connect
    # it to the child node.
    # Note that calling original_factors
    # here can break build_gbn if the
    # factors do not correctly represent
    # a valid network. This will be fixed
    # in next release
    original_factors = get_original_factors(factor_nodes.values())
    for var_name, factor in original_factors.items():
        factor.variable_name = var_name
    for factor_node in factor_nodes.values():
        factor_args = get_args(factor_node)
        parents = [
            original_factors[arg] for arg in factor_args
            if original_factors[arg] != factor_node
        ]
        for parent in parents:
            connect(parent, factor_node)
    # Now process the raw_betas to create a dict
    for factor_node in factor_nodes.values():
        # Now we want betas to always be a dict
        # but in the case that the node only
        # has one parent we will allow the user to specify
        # the single beta for that parent simply
        # as a number and not a dict.
        if hasattr(factor_node.func, 'raw_betas'):
            if isinstance(factor_node.func.raw_betas, Number):
                # Make sure that if they supply a number
                # there is only one parent
                assert len(get_args(factor_node)) == 2
                betas = dict()
                for arg in get_args(factor_node):
                    if arg != factor_node.variable_name:
                        betas[arg] = factor_node.func.raw_betas
                factor_node.func.betas = betas
            else:
                factor_node.func.betas = factor_node.func.raw_betas
    gbn = GaussianBayesianGraph(original_factors, name=name)
    # Now for any conditional gaussian nodes
    # we need to tell the node function what the
    # parent parameters are so that the pdf can
    # be computed.
    sorted = gbn.get_topological_sort()
    joint_mu, joint_sigma = gbn.get_joint_parameters()
    for node in sorted:
        if hasattr(node.func, 'betas'):
            # This means its multivariate gaussian
            names = [n.variable_name
                     for n in node.parents] + [node.variable_name]
            node.func.joint_mu = MeansVector.zeros((len(names), 1),
                                                   names=names)
            for name in names:
                node.func.joint_mu[name] = joint_mu[name][0, 0]
            node.func.covariance_matrix = CovarianceMatrix.zeros(
                (len(names), len(names)), names)
            for row, col in xproduct(names, names):
                node.func.covariance_matrix[row, col] = joint_sigma[row, col]
    return gbn
def build_gbn(*args, **kwds):
    '''Builds a Gaussian Bayesian Graph from
    a list of functions'''
    variables = set()
    name = kwds.get('name')
    variable_nodes = dict()
    factor_nodes = dict()

    if isinstance(args[0], list):
        # Assume the functions were all
        # passed in a list in the first
        # argument. This makes it possible
        # to build very large graphs with
        # more than 255 functions, since
        # Python functions are limited to
        # 255 arguments.
        args = args[0]

    for factor in args:
        factor_args = get_args(factor)
        variables.update(factor_args)
        node = GBNNode(factor)
        factor_nodes[factor.__name__] = node

    # Now lets create the connections
    # To do this we need to find the
    # factor node representing the variables
    # in a child factors argument and connect
    # it to the child node.
    # Note that calling original_factors
    # here can break build_gbn if the
    # factors do not correctly represent
    # a valid network. This will be fixed
    # in next release
    original_factors = get_original_factors(list(factor_nodes.values()))
    for var_name, factor in list(original_factors.items()):
        factor.variable_name = var_name
    for factor_node in list(factor_nodes.values()):
        factor_args = get_args(factor_node)
        parents = [original_factors[arg] for arg in
                   factor_args if original_factors[arg] != factor_node]
        for parent in parents:
            connect(parent, factor_node)
    # Now process the raw_betas to create a dict
    for factor_node in list(factor_nodes.values()):
        # Now we want betas to always be a dict
        # but in the case that the node only
        # has one parent we will allow the user to specify
        # the single beta for that parent simply
        # as a number and not a dict.
        if hasattr(factor_node.func, 'raw_betas'):
            if isinstance(factor_node.func.raw_betas, Number):
                # Make sure that if they supply a number
                # there is only one parent
                assert len(get_args(factor_node)) == 2
                betas = dict()
                for arg in get_args(factor_node):
                    if arg != factor_node.variable_name:
                        betas[arg] = factor_node.func.raw_betas
                factor_node.func.betas = betas
            else:
                factor_node.func.betas = factor_node.func.raw_betas
    gbn = GaussianBayesianGraph(original_factors, name=name)
    # Now for any conditional gaussian nodes
    # we need to tell the node function what the
    # parent parameters are so that the pdf can
    # be computed.
    sorted = gbn.get_topological_sort()
    joint_mu, joint_sigma = gbn.get_joint_parameters()
    for node in sorted:
        if hasattr(node.func, 'betas'):
            # This means its multivariate gaussian
            names = [n.variable_name for n in node.parents] + [node.variable_name]
            node.func.joint_mu = MeansVector.zeros((len(names), 1), names=names)
            for name in names:
                node.func.joint_mu[name] = joint_mu[name][0, 0]
            node.func.covariance_matrix = CovarianceMatrix.zeros(
                (len(names), len(names)), names)
            for row, col in xproduct(names, names):
                node.func.covariance_matrix[row, col] = joint_sigma[row, col]
    return gbn
 def test_assignment_of_joint_parameters(self, river_graph):
     assert river_graph.nodes['b'].func.joint_mu == MeansVector(
         [[3], [4]], names=['a', 'b'])
     assert river_graph.nodes[
         'b'].func.covariance_matrix == CovarianceMatrix([[4, 4], [4, 5]],
                                                         names=['a', 'b'])