'Compute scalar loss tensors given prediction tensors.
If first_stage_only=True, only RPN related losses are computed (i.e.,
`rpn_localization_loss` and `rpn_objectness_loss`).  Otherwise all
losses are computed.
Args:
prediction_dict: a dictionary holding prediction tensors (see the
documentation for the predict method.  If first_stage_only=True, we
expect prediction_dict to contain `rpn_box_encodings`,
`rpn_objectness_predictions_with_background`, `rpn_features_to_crop`,
`image_shape`, and `anchors` fields.  Otherwise we expect
prediction_dict to additionally contain `refined_box_encodings`,
`class_predictions_with_background`, `num_proposals`, and
`proposal_boxes` fields.
scope: Optional scope name.
Returns:
a dictionary mapping loss keys (`first_stage_localization_loss`,
`first_stage_objectness_loss`, \'second_stage_localization_loss\',
\'second_stage_classification_loss\') to scalar tensors representing
corresponding loss values.'

def loss(self, prediction_dict, scope=None):

    with tf.name_scope(scope, 'Loss', prediction_dict.values()):
        (groundtruth_boxlists, groundtruth_classes_with_background_list) = self._format_groundtruth_data(prediction_dict['image_shape'])
        loss_dict = self._loss_rpn(prediction_dict['rpn_box_encodings'], prediction_dict['rpn_objectness_predictions_with_background'], prediction_dict['anchors'], groundtruth_boxlists, groundtruth_classes_with_background_list)
        if (not self._first_stage_only):
            loss_dict.update(self._loss_box_classifier(prediction_dict['refined_box_encodings'], prediction_dict['class_predictions_with_background'], prediction_dict['proposal_boxes'], prediction_dict['num_proposals'], groundtruth_boxlists, groundtruth_classes_with_background_list))
    return loss_dict
