'Computes scalar box classifier loss tensors.
Uses self._detector_target_assigner to obtain regression and classification
targets for the second stage box classifier, optionally performs
hard mining, and returns losses.  All losses are computed independently
for each image and then averaged across the batch.
This function assumes that the proposal boxes in the "padded" regions are
actually zero (and thus should not be matched to).
Args:
refined_box_encodings: a 3-D tensor with shape
[total_num_proposals, num_classes, box_coder.code_size] representing
predicted (final) refined box encodings.
class_predictions_with_background: a 3-D tensor with shape
[total_num_proposals, num_classes + 1] containing class
predictions (logits) for each of the anchors.  Note that this tensor
*includes* background class predictions (at class index 0).
proposal_boxes: [batch_size, self.max_num_proposals, 4] representing
decoded proposal bounding boxes.
num_proposals: A Tensor of type `int32`. A 1-D tensor of shape [batch]
representing the number of proposals predicted for each image in
the batch.
groundtruth_boxlists: a list of BoxLists containing coordinates of the
groundtruth boxes.
groundtruth_classes_with_background_list: a list of 2-D one-hot
(or k-hot) tensors of shape [num_boxes, num_classes + 1] containing the
class targets with the 0th index assumed to map to the background class.
Returns:
a dictionary mapping loss keys (\'second_stage_localization_loss\',
\'second_stage_classification_loss\') to scalar tensors representing
corresponding loss values.'

def _loss_box_classifier(self, refined_box_encodings, class_predictions_with_background, proposal_boxes, num_proposals, groundtruth_boxlists, groundtruth_classes_with_background_list):

    with tf.name_scope('BoxClassifierLoss'):
        paddings_indicator = self._padded_batched_proposals_indicator(num_proposals, self.max_num_proposals)
        proposal_boxlists = [box_list.BoxList(proposal_boxes_single_image) for proposal_boxes_single_image in tf.unstack(proposal_boxes)]
        batch_size = len(proposal_boxlists)
        num_proposals_or_one = tf.to_float(tf.expand_dims(tf.maximum(num_proposals, tf.ones_like(num_proposals)), 1))
        normalizer = (tf.tile(num_proposals_or_one, [1, self.max_num_proposals]) * batch_size)
        (batch_cls_targets_with_background, batch_cls_weights, batch_reg_targets, batch_reg_weights, _) = target_assigner.batch_assign_targets(self._detector_target_assigner, proposal_boxlists, groundtruth_boxlists, groundtruth_classes_with_background_list)
        flat_cls_targets_with_background = tf.reshape(batch_cls_targets_with_background, [(batch_size * self.max_num_proposals), (-1)])
        refined_box_encodings_with_background = tf.pad(refined_box_encodings, [[0, 0], [1, 0], [0, 0]])
        refined_box_encodings_masked_by_class_targets = tf.boolean_mask(refined_box_encodings_with_background, tf.greater(flat_cls_targets_with_background, 0))
        reshaped_refined_box_encodings = tf.reshape(refined_box_encodings_masked_by_class_targets, [batch_size, (-1), 4])
        second_stage_loc_losses = (self._second_stage_localization_loss(reshaped_refined_box_encodings, batch_reg_targets, weights=batch_reg_weights) / normalizer)
        second_stage_cls_losses = (self._second_stage_classification_loss(class_predictions_with_background, batch_cls_targets_with_background, weights=batch_cls_weights) / normalizer)
        second_stage_loc_loss = tf.reduce_sum(tf.boolean_mask(second_stage_loc_losses, paddings_indicator))
        second_stage_cls_loss = tf.reduce_sum(tf.boolean_mask(second_stage_cls_losses, paddings_indicator))
        if self._hard_example_miner:
            (second_stage_loc_loss, second_stage_cls_loss) = self._unpad_proposals_and_apply_hard_mining(proposal_boxlists, second_stage_loc_losses, second_stage_cls_losses, num_proposals)
        loss_dict = {'second_stage_localization_loss': (self._second_stage_loc_loss_weight * second_stage_loc_loss), 'second_stage_classification_loss': (self._second_stage_cls_loss_weight * second_stage_cls_loss)}
    return loss_dict
