Beispiel #1
0
def forward_pass(frcs, bu_msg, graph, pool_shape):
    """
    Forward pass inference using a tree-approximation (cf. Sec S4.2).

    Parameters
    ----------
    frcs : numpy.ndarray of numpy.int
        Nx3 array of (feature idx, row, column), where each row represents a
        single pool center.
    bu_msg : 3D numpy.ndarray of float
        The bottom-up messages from the preprocessing layer.
        Shape is (num_feats, rows, cols)
    graph : networkx.Graph
        An undirected graph whose edges describe the pairwise constraints between
        the pool centers.
        The tightness of the constraint is in the 'perturb_radius' edge attribute.
    pool_shape : (int, int)
        Vertical and horizontal pool shapes.

    Returns
    -------
    fp_score : float
        Forward pass score.
    """
    height, width = bu_msg.shape[-2:]
    # Vertical and horizontal pool shapes
    vps, hps = pool_shape

    def _pool_slice(f, r, c):
        assert (r - vps // 2 >= 0 and r + vps - vps // 2 < height and
                c - hps // 2 >= 0 and c + hps - hps // 2 < width), \
            "Some pools are out of the image boundaries. "\
            "Consider increase image padding or reduce pool shapes."
        return np.s_[f, r - vps // 2:r + vps - vps // 2,
                     c - hps // 2:c + hps - hps // 2]

    # Find a schedule to compute the max marginal for the most constrained tree
    tree_schedule = get_tree_schedule(frcs, graph)

    # If we're sending a message out from x to y, it means x has received all
    # incoming messages
    incoming_msgs = {}
    for source, target, perturb_radius in tree_schedule:
        msg_in = bu_msg[_pool_slice(*frcs[source])]
        if source in incoming_msgs:
            msg_in = msg_in + incoming_msgs[source]
            del incoming_msgs[source]
        msg_in = dilate_2d(msg_in,
                           (2 * perturb_radius + 1, 2 * perturb_radius + 1))
        if target in incoming_msgs:
            incoming_msgs[target] += msg_in
        else:
            incoming_msgs[target] = msg_in
    fp_score = np.max(incoming_msgs[tree_schedule[-1, 1]] +
                      bu_msg[_pool_slice(*frcs[tree_schedule[-1, 1]])])

    return fp_score
Beispiel #2
0
def forward_pass(frcs, bu_msg, graph, pool_shape):
    """
    Forward pass inference using a tree-approximation (cf. Sec S4.2).

    Parameters
    ----------
    frcs : numpy.ndarray of numpy.int
        Nx3 array of (feature idx, row, column), where each row represents a
        single pool center.
    bu_msg : 3D numpy.ndarray of float
        The bottom-up messages from the preprocessing layer.
        Shape is (num_feats, rows, cols)
    graph : networkx.Graph
        An undirected graph whose edges describe the pairwise constraints between
        the pool centers.
        The tightness of the constraint is in the 'perturb_radius' edge attribute.
    pool_shape : (int, int)
        Vertical and horizontal pool shapes.

    Returns
    -------
    fp_score : float
        Forward pass score.
    """
    height, width = bu_msg.shape[-2:]
    # Vertical and horizontal pool shapes
    vps, hps = pool_shape

    def _pool_slice(f, r, c):
        assert (r - vps // 2 >= 0 and r + vps - vps // 2 < height and
                c - hps // 2 >= 0 and c + hps - hps // 2 < width), \
            "Some pools are out of the image boundaries. "\
            "Consider increase image padding or reduce pool shapes."
        return np.s_[f,
                     r - vps // 2: r + vps - vps // 2,
                     c - hps // 2: c + hps - hps // 2]

    # Find a schedule to compute the max marginal for the most constrained tree
    tree_schedule = get_tree_schedule(frcs, graph)

    # If we're sending a message out from x to y, it means x has received all
    # incoming messages
    incoming_msgs = {}
    for source, target, perturb_radius in tree_schedule:
        msg_in = bu_msg[_pool_slice(*frcs[source])]
        if source in incoming_msgs:
            msg_in = msg_in + incoming_msgs[source]
            del incoming_msgs[source]
        msg_in = dilate_2d(msg_in, (2 * perturb_radius + 1, 2 * perturb_radius + 1))
        if target in incoming_msgs:
            incoming_msgs[target] += msg_in
        else:
            incoming_msgs[target] = msg_in
    fp_score = np.max(incoming_msgs[tree_schedule[-1, 1]] +
                      bu_msg[_pool_slice(*frcs[tree_schedule[-1, 1]])])
    return fp_score
Beispiel #3
0
    def compute_1pl_message(in_mess, pert_radius):
        """Compute the outgoing message of a lateral factor given the
        perturbation radius and input message.

        Parameters
        ----------
        in_mess : numpy.array
            Input BP messages to the factor. Each message has shape vps x hps.
        pert_radius : int
            Perturbation radius corresponding to the factor.

        Returns
        -------
        out_mess : numpy.array
            Output BP message (at the opposite end of the factor from the input message).
            Shape is (vps, hps).
        """
        pert_diameter = 2 * pert_radius + 1
        out_mess = dilate_2d(in_mess, (pert_diameter, pert_diameter))
        return out_mess - out_mess.max()
Beispiel #4
0
    def compute_1pl_message(in_mess, pert_radius):
        """Compute the outgoing message of a lateral factor given the
        perturbation radius and input message.

        Parameters
        ----------
        in_mess : numpy.array
            Input BP messages to the factor. Each message has shape vps x hps.
        pert_radius : int
            Perturbation radius corresponding to the factor.

        Returns
        -------
        out_mess : numpy.array
            Output BP message (at the opposite end of the factor from the input message).
            Shape is (vps, hps).
        """
        pert_diameter = 2 * pert_radius + 1
        out_mess = dilate_2d(in_mess, (pert_diameter, pert_diameter))
        return out_mess - out_mess.max()