  
          Weights are returned as the weighted sum of the chosen losses.
  
          Parameters
          ----------
          y_true: tensor or variable
              The ground truth value
          y_pred: tensor or variable
 
</s> remove class PenalizedLoss(tf.keras.losses.Loss):
    """ Penalized Loss function.

    Applies the given loss function just to the masked area of the image.

    Parameters
    ----------
    loss_func: function
        The actual loss function to use
    mask_prop: float, optional
        The amount of mask propagation. Default: `1.0`
    """
    def __init__(self, loss_func, mask_prop=1.0):
        super().__init__(name="penalized_loss")
        self._loss_func = compile_utils.LossesContainer(loss_func)
        self._mask_prop = mask_prop

    def call(self, y_true, y_pred):
        """ Apply the loss function to the masked area of the image.

        Parameters
        ----------
        y_true: tensor or variable
            The ground truth value. This should contain the mask in the 4th channel that will be
            split off for penalizing.
        y_pred: tensor or variable
            The predicted value

        Returns
        -------
        tensor
            The Loss value
        """
        mask = self._prepare_mask(K.expand_dims(y_true[..., -1], axis=-1))
        y_true = y_true[..., :-1]
        n_true = K.concatenate([y_true[:, :, :, i:i+1] * mask for i in range(3)], axis=-1)
        n_pred = K.concatenate([y_pred[:, :, :, i:i+1] * mask for i in range(3)], axis=-1)
        return self._loss_func(n_true, n_pred)

    def _prepare_mask(self, mask):
        """ Prepare the masks for calculating loss

        Parameters
        ----------
        mask: :class:`numpy.ndarray`
            The masks for the current batch

        Returns
        -------
        tensor
            The prepared mask for applying to loss
        """
        mask_as_k_inv_prop = 1 - self._mask_prop
        mask = (mask * self._mask_prop) + mask_as_k_inv_prop
        return mask


 </s> add  </s> remove class PenalizedLoss():  # pylint:disable=too-few-public-methods
    """ Penalized Loss function.

    Applies the given loss function just to the masked area of the image.

    Parameters
    ----------
    loss_func: function
        The actual loss function to use
    mask_prop: float, optional
        The amount of mask propagation. Default: `1.0`
    """
    def __init__(self, loss_func, mask_prop=1.0):
        self._loss_func = loss_func
        self._mask_prop = mask_prop

    def __call__(self, y_true, y_pred):
        """ Apply the loss function to the masked area of the image.

        Parameters
        ----------
        y_true: tensor or variable
            The ground truth value. This should contain the mask in the 4th channel that will be
            split off for penalizing.
        y_pred: tensor or variable
            The predicted value

        Returns
        -------
        tensor
            The Loss value
        """
        mask = self._prepare_mask(K.expand_dims(y_true[..., -1], axis=-1))
        y_true = y_true[..., :-1]
        n_true = y_true * mask
        n_pred = y_pred * mask
        if isinstance(self._loss_func, DSSIMObjective):
            # Extract Image Patches in SSIM requires that y_pred be of a known shape, so
            # specifically reshape the tensor.
            n_pred = K.reshape(n_pred, K.int_shape(y_pred))
        return self._loss_func(n_true, n_pred)

    def _prepare_mask(self, mask):
        """ Prepare the masks for calculating loss

        Parameters
        ----------
        mask: :class:`numpy.ndarray`
            The masks for the current batch

        Returns
        -------
        tensor
            The prepared mask for applying to loss
        """
        mask_as_k_inv_prop = 1 - self._mask_prop
        mask = (mask * self._mask_prop) + mask_as_k_inv_prop
        return mask


 </s> add  </s> remove         loss_functions: list
            A list of either a tuple of (:class:`keras.losses.Loss`, scalar weight) or just a
            :class:`keras.losses.Loss` function. If just the loss function is passed, then the
            weight is assumed to be 1.0 """
        for loss_func in loss_functions:
            if isinstance(loss_func, tuple):
                assert len(loss_func) == 2, "Tuple loss functions should contain 2 items"
                assert isinstance(loss_func[1], float), "weight should be a float"
                func, weight = loss_func
            else:
                func = loss_func
                weight = 1.0
            self._loss_functions.append(compile_utils.LossesContainer(func))
            self._loss_weights.append(weight)
        logger.debug("Compiled losses: (functions: %s, weights: %s",
                     self._loss_functions, self._loss_weights)
 </s> add         function: :class:`keras.losses.Loss`
            The loss function to add to the loss chain
        weight: float, optional
            The weighting to apply to the loss function. Default: `1.0`
        mask_channel: int, optional
            The channel in the `y_true` image that the mask exists in. Set to `-1` if there is no
            mask for the given loss function. Default: `-1`
        """
        logger.debug("Adding loss: (function: %s, weight: %s, mask_channel: %s)",
                     function, weight, mask_channel)
        self._loss_functions.append(compile_utils.LossesContainer(function))
        self._loss_weights.append(weight)
        self._mask_channels.append(mask_channel) </s> remove         loss_functions: list
            A list of either a tuple of (:class:`keras.losses.Loss`, scalar weight) or just a
            :class:`keras.losses.Loss` function. If just the loss function is passed, then the
            weight is assumed to be 1.0 """
        for loss_func in loss_functions:
            if isinstance(loss_func, tuple):
                assert len(loss_func) == 2, "Tuple loss functions should contain 2 items"
                assert isinstance(loss_func[1], float), "weight should be a float"
                func, weight = loss_func
            else:
                func = loss_func
                weight = 1.0
            self._loss_functions.append(func)
            self._loss_weights.append(weight)
        logger.debug("Compiled losses: (functions: %s, weights: %s",
                     self._loss_functions, self._loss_weights)
 </s> add         function: :class:`keras.losses.Loss`
            The loss function to add to the loss chain
        weight: float, optional
            The weighting to apply to the loss function. Default: `1.0`
        mask_channel: int, optional
            The channel in the `y_true` image that the mask exists in. Set to `-1` if there is no
            mask for the given loss function. Default: `-1`
        """
        logger.debug("Adding loss: (function: %s, weight: %s, mask_channel: %s)",
                     function, weight, mask_channel)
        self._loss_functions.append(function)
        self._loss_weights.append(weight)
        self._mask_channels.append(mask_channel) </s> remove         Returns the targets as a list of 4-dimensional :class:`numpy.ndarray` s of shape
        (`batchsize`, `height`, `width`, `3`).
 </s> add         Parameters
        ----------
        target_batch: list
            List of 4 dimension :class:`numpy.ndarray` objects resized the model outputs.
            The 4th channel of the array contains the face mask, any additional channels after
            this are additional masks (e.g. eye mask and mouth mask)
        If a mask is being applied to the loss, then the appropriate mask is extracted from y_true
        and added as the 4th channel being passed to the penalized loss function.

  
          Weights are returned as the weighted sum of the chosen losses.
  
        If a mask is being applied to the loss, then the appropriate mask is extracted from y_true
        and added as the 4th channel being passed to the penalized loss function.

          Parameters
          ----------
          y_true: tensor or variable
              The ground truth value
          y_pred: tensor or variable
keep keep add keep keep keep keep keep
 Add Mouth and Eye Priority to Loss options (#1054)

* Priority Training for Mouth and Eyes - Tensorflow

* Use chosen loss function for area multipliers

* loss multipliers for AMD

* Fix mask multipliers for plaid and roll PenalizedMaskLoss into LossWrapper

* losses_tf: roll PenalizedMaskLoss into LossWrapper 
lib/model/losses_tf.py