Example #1
0
def stochastic_node_mean_symbolic(approx: pm.MeanField,
                                  node,
                                  size=100,
                                  more_replacements=None,
                                  shape=None,
                                  dtype=None):
    """Symbolic mean of a given PyMC3 stochastic node with respect to a given variational
    posterior approximation.

    Args:
        approx: an instance of PyMC3 approximation
        node: stochastic node
        size: the number of samples to use for calculating the mean
        more_replacements: (optional) an ordered dictionary of node replacements to be
            applied to the computational graph before sampling
        shape: (optional) shape of the node
        dtype: (optional) dtype of the node

    Raises:
        ValueError: If `node.tag.test_value` is not present and `shape` and `dtype` are
            not provided

    Returns:
        Symbolic approximate mean of the stochastic node
    """

    assert size > 0

    if shape is not None and dtype is not None:
        cum_sum = tt.zeros(shape, dtype)
    elif hasattr(node.tag, 'test_value') and node.tag.test_value is not None:
        cum_sum = tt.zeros(node.tag.test_value.shape,
                           node.tag.test_value.dtype)
    else:
        raise ValueError(
            "Can not determine the shape of the node to be sampled")

    if more_replacements is not None:
        node = th.clone(node, more_replacements, strict=False)
    posterior_samples = approx.random(size)
    node = approx.to_flat_input(node)

    def add_sample_to_cum_sum(posterior_sample, _cum_sum):
        new_sample = th.clone(node, {approx.input: posterior_sample},
                              strict=False)
        return _cum_sum + tt.patternbroadcast(new_sample,
                                              _cum_sum.broadcastable)

    outputs, _ = th.scan(add_sample_to_cum_sum,
                         sequences=[posterior_samples],
                         outputs_info=[cum_sum],
                         n_steps=size)

    return outputs[-1] / size
Example #2
0
def stochastic_node_mean_symbolic(approx: pm.MeanField, node, size=100,
                                  more_replacements=None, shape=None, dtype=None):
    """Symbolic mean of a given PyMC3 stochastic node with respect to a given variational
    posterior approximation.

    Args:
        approx: an instance of PyMC3 approximation
        node: stochastic node
        size: the number of samples to use for calculating the mean
        more_replacements: (optional) an ordered dictionary of node replacements to be
            applied to the computational graph before sampling
        shape: (optional) shape of the node
        dtype: (optional) dtype of the node

    Raises:
        ValueError: If `node.tag.test_value` is not present and `shape` and `dtype` are
            not provided

    Returns:
        Symbolic approximate mean of the stochastic node
    """

    assert size > 0

    if shape is not None and dtype is not None:
        cum_sum = tt.zeros(shape, dtype)
    elif hasattr(node.tag, 'test_value') and node.tag.test_value is not None:
        cum_sum = tt.zeros(node.tag.test_value.shape, node.tag.test_value.dtype)
    else:
        raise ValueError("Can not determine the shape of the node to be sampled")

    if more_replacements is not None:
        node = th.clone(node, more_replacements, strict=False)
    posterior_samples = approx.random(size)
    node = approx.to_flat_input(node)

    def add_sample_to_cum_sum(posterior_sample, _cum_sum):
        new_sample = th.clone(node, {approx.input: posterior_sample}, strict=False)
        return _cum_sum + tt.patternbroadcast(new_sample, _cum_sum.broadcastable)

    outputs, _ = th.scan(add_sample_to_cum_sum,
                         sequences=[posterior_samples],
                         outputs_info=[cum_sum],
                         n_steps=size)

    return outputs[-1] / size
Example #3
0
def get_sampling_generator_for_model_approximation(model_approx: pm.MeanField, model_var_name: str,
                                                   num_samples: int = 250) -> Generator:
    """Get a generator that returns samples of a precomputed model approximation for a specific variable in that model

    Args:
        model_approx: an instance of PyMC3 meanfield approximation
        model_var_name: a stochastic node in the model
        num_samples: number of samples to draw

    Returns:
        A generator that will yield `num_samples` samples from an approximation to a posterior
    """
    return (model_approx.sample()[model_var_name] for _ in range(num_samples))
Example #4
0
def get_sampling_generator_for_model_approximation(model_approx: pm.MeanField, node,
                                                   num_samples: int = 20) -> Generator:
    """Get a generator that returns samples of a precomputed model approximation for a specific variable in that model

    Args:
        model_approx: an instance of PyMC3 mean-field approximation
        node: a stochastic node in the model
        num_samples: number of samples to draw

    Returns:
        A generator that will yield `num_samples` samples from an approximation to a posterior
    """

    sample = model_approx.sample_node(node, size=1)[0]
    return (sample.eval() for _ in range(num_samples))
Example #5
0
def get_sampling_generator_for_model_approximation(model_approx: pm.MeanField, node,
                                                   num_samples: int = 20) -> Generator:
    """Get a generator that returns samples of a precomputed model approximation for a specific variable in that model

    Args:
        model_approx: an instance of PyMC3 mean-field approximation
        node: a stochastic node in the model
        num_samples: number of samples to draw

    Returns:
        A generator that will yield `num_samples` samples from an approximation to a posterior
    """

    sample = model_approx.sample_node(node, size=1)[0]
    return (sample.eval() for _ in range(num_samples))