          return processed
  
      def _apply_mask(self, filenames, batch, side):
          """ Applies the mask to the 4th channel of the image. If masks are not being used
          applies a dummy all ones mask """
          logger.trace("Input batch shape: %s, side: %s", batch.shape, side)
          if self._masks is None:
              logger.trace("Creating dummy masks. side: %s", side)
              masks = np.ones_like(batch[..., :1], dtype=batch.dtype)
          else:
              logger.trace("Obtaining masks for batch. side: %s", side)
              masks = np.array([self._masks[side][filename].mask
                                for filename, face in zip(filenames, batch)], dtype=batch.dtype)
              masks = self._resize_masks(batch.shape[1], masks)
  
          logger.trace("masks shape: %s", masks.shape)
          batch = np.concatenate((batch, masks), axis=-1)
          logger.trace("Output batch shape: %s, side: %s", batch.shape, side)
          return batch
 
</s> remove         logger.trace("masks shape: %s", masks.shape)
        batch = np.concatenate((batch, masks), axis=-1)
 </s> add         Returns
        -------
        :class:`numpy.ndarray`
            The batch with masks applied to the final channels
        """
        logger.trace("Input batch shape: %s, side: %s", batch.shape, side)
        size = batch.shape[1]
        for key in ("masks", "eyes", "mouths"):
            item = self._masks[key]
            if item is None and key != "masks":
                continue
            if item is None and key == "masks":
                logger.trace("Creating dummy masks. side: %s", side)
                masks = np.ones_like(batch[..., :1], dtype=batch.dtype)
            else:
                logger.trace("Obtaining masks for batch. (key: %s side: %s)", key, side)
                masks = np.array([self._get_mask(item[side][filename], size)
                                  for filename, face in zip(filenames, batch)], dtype=batch.dtype)
                masks = self._resize_masks(size, masks)

            logger.trace("masks: (key: %s, shape: %s)", key, masks.shape)
            batch = np.concatenate((batch, masks), axis=-1) </s> remove         masks = targets[-1]
        for idx, tgt in enumerate(targets[:-1]):
 </s> add         if not self._model.config["penalized_mask_loss"] and additional_masks is None:
            logger.trace("No masks to compile. Returning targets")
            return targets

        if not self._model.config["penalized_mask_loss"] and additional_masks is not None:
            masks = additional_masks
        elif additional_masks is not None:
            masks = np.concatenate((masks, additional_masks), axis=-1)

        for idx, tgt in enumerate(targets): </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     def _get_next(self, side):
        """ Return the next batch from the :class:`lib.training_data.TrainingDataGenerator` for
        this feeder ready for feeding into the model.

        Returns
        -------
        model_inputs: list
            A list of :class:`numpy.ndarray` for feeding into the model
        model_targets: list
            A list of :class:`numpy.ndarray` for comparing the output of the model
        """
        logger.trace("Generating targets")
        batch = next(self._feeds[side])
        targets_use_mask = (self._model.config["learn_mask"]
                            or self._model.config["penalized_mask_loss"])
        model_targets = batch["targets"] + batch["masks"] if targets_use_mask else batch["targets"]
        return batch["feed"], model_targets

    @classmethod
    def _compile_masks(cls, targets):
        """ Compile the masks into the targets for penalized loss.
 </s> add     def _compile_mask_targets(self, targets, masks, additional_masks):
        """ Compile the masks into the targets for penalized loss and for targeted learning. </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 
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
          return processed
  
      def _apply_mask(self, filenames, batch, side):
          """ Applies the mask to the 4th channel of the image. If masks are not being used
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
        applies a dummy all ones mask.

        If the configuration options `eye_multiplier` and/or `mouth_multiplier` are greater than 1
        then these masks are applied to the final channels of the batch respectively.

        Parameters
        ----------
        filenames: list
            The list of filenames that correspond to this batch
        batch: :class:`numpy.ndarray`
            The batch of faces that have been loaded from disk
        side: str
            '"a"' or '"b"' the side that is being processed
  
          logger.trace("masks shape: %s", masks.shape)
          batch = np.concatenate((batch, masks), axis=-1)
          logger.trace("Output batch shape: %s, side: %s", batch.shape, side)
          return batch
keep keep keep keep replace replace replace replace replace replace replace replace replace replace 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/training_data.py