              * loss - If old `dssim_loss` is ``true`` set new `loss_function` to `ssim` otherwise
              set it to `mae`. Remove old `dssim_loss` item
  
              * masks - If `learn_mask` does not exist then it is set to ``True`` if `mask_type` is
              not ``None`` otherwise it is set to ``False``.
  
              * masks type - Replace removed masks 'dfl_full' and 'facehull' with `components` mask
 
</s> remove         priors = ["dssim_loss", "mask_type", "mask_type"]
        new_items = ["loss_function", "learn_mask", "mask_type"]
 </s> add         priors = ["dssim_loss", "mask_type", "mask_type", "l2_reg_term"]
        new_items = ["loss_function", "learn_mask", "mask_type", "loss_function_2"] </s> remove             choices=["mae", "mse", "logcosh", "smooth_loss", "l_inf_norm", "ssim", "ms_ssim",
                     "gmsd", "pixel_gradient_diff"],
            info="The loss function to use."
                 "\n\t MAE - Mean absolute error will guide reconstructions of each pixel "
                 "towards its median value in the training dataset. Robust to outliers but as "
                 "a median, it can potentially ignore some infrequent image types in the dataset."
                 "\n\t MSE - Mean squared error will guide reconstructions of each pixel "
                 "towards its average value in the training dataset. As an avg, it will be "
                 "susceptible to outliers and typically produces slightly blurrier results."
                 "\n\t LogCosh - log(cosh(x)) acts similar to MSE for small errors and to "
                 "MAE for large errors. Like MSE, it is very stable and prevents overshoots "
                 "when errors are near zero. Like MAE, it is robust to outliers. NB: Due to a bug "
                 "in PlaidML, this loss does not work on AMD cards."
                 "\n\t Smooth_L1 --- Modification of the MAE loss to correct two of its "
                 "disadvantages. This loss has improved stability and guidance for small errors."
                 "\n\t L_inf_norm --- The L_inf norm will reduce the largest individual pixel "
                 "error in an image. As each largest error is minimized sequentially, the "
                 "overall error is improved. This loss will be extremely focused on outliers."
                 "\n\t SSIM - Structural Similarity Index Metric is a perception-based "
                 "loss that considers changes in texture, luminance, contrast, and local spatial "
                 "statistics of an image. Potentially delivers more realistic looking images."
                 "\n\t MS_SSIM - Multiscale Structural Similarity Index Metric is similar to SSIM "
                 "except that it performs the calculations along multiple scales of the input "
                 "image. NB: This loss currently does not work on AMD Cards."
                 "\n\t GMSD - Gradient Magnitude Similarity Deviation seeks to match "
                 "the global standard deviation of the pixel to pixel differences between two "
                 "images. Similar in approach to SSIM. NB: This loss does not currently work on "
                 "AMD cards."
                 "\n\t Pixel_Gradient_Difference - Instead of minimizing the difference between "
                 "the absolute value of each pixel in two reference images, compute the pixel to "
                 "pixel spatial difference in each image and then minimize that difference "
                 "between two images. Allows for large color shifts, but maintains the structure "
                 "of the image.")
 </s> add             fixed=False,
            choices=[x for x in sorted(_LOSS_HELP) if x not in _NON_PRIMARY_LOSS],
            info="The loss function to use.\n\n\t" +
                 "\n\t".join(f"{k}: {v}"
                             for k, v in sorted(_LOSS_HELP.items()) if k not in _NON_PRIMARY_LOSS))
        self.add_item(
            section=section,
            title="loss_function_2",
            datatype=str,
            group="loss",
            default="mse",
            fixed=False,
            choices=list(sorted(_LOSS_HELP)),
            info="The second loss function to use. If using a structural based loss (such as "
                 "SSIM, MS-SSIM or GMSD) it is common to add an L1 regularization(MAE) or L2 "
                 "regularization (MSE) function. You can adjust the weighting of this loss "
                 "function with the loss_weight_2 option.\n\n\t" +
                 "\n\t".join(f"{k}: {v}"
                             for k, v in sorted(_LOSS_HELP.items())))
        self.add_item(
            section=section,
            title="loss_weight_2",
            datatype=int,
            group="loss",
            min_max=(0, 400),
            rounding=1,
            default=100,
            fixed=False,
            info="The amount of weight to apply to the second loss function.\n\n"
                 "\n\nThe value given here is as a percentage denoting how much the selected "
                 "function should contribute to the overall loss cost of the model. For example:"
                 "\n\t 100 - The loss calculated for the second loss function will be applied at "
                 "its full amount towards the overall loss score. "
                 "\n\t 25 - The loss calculated for the second loss function will be reduced by a "
                 "quarter prior to adding to the overall loss score. "
                 "\n\t 400 - The loss calculated for the second loss function will be mulitplied "
                 "4 times prior to adding to the overall loss score. "
                 "\n\t 0 - Disables the second loss function altogether.")
        self.add_item(
            section=section,
            title="loss_function_3",
            datatype=str,
            group="loss",
            default="none",
            fixed=False,
            choices=list(sorted(_LOSS_HELP)),
            info="The third loss function to use. You can adjust the weighting of this loss "
                 "function with the loss_weight_3 option.\n\n\t" +
                 "\n\t".join(f"{k}: {v}"
                             for k, v in sorted(_LOSS_HELP.items())))
        self.add_item(
            section=section,
            title="loss_weight_3",
            datatype=int,
            group="loss",
            min_max=(0, 400),
            rounding=1,
            default=0,
            fixed=False,
            info="The amount of weight to apply to the third loss function.\n\n"
                 "\n\nThe value given here is as a percentage denoting how much the selected "
                 "function should contribute to the overall loss cost of the model. For example:"
                 "\n\t 100 - The loss calculated for the third loss function will be applied at "
                 "its full amount towards the overall loss score. "
                 "\n\t 25 - The loss calculated for the third loss function will be reduced by a "
                 "quarter prior to adding to the overall loss score. "
                 "\n\t 400 - The loss calculated for the third loss function will be mulitplied 4 "
                 "times prior to adding to the overall loss score. "
                 "\n\t 0 - Disables the third loss function altogether.")
        self.add_item(
            section=section,
            title="loss_function_4",
            datatype=str,
            group="loss",
            default="none",
            fixed=False,
            choices=list(sorted(_LOSS_HELP)),
            info="The fourth loss function to use. You can adjust the weighting of this loss "
                 "function with the loss_weight_3 option.\n\n\t" +
                 "\n\t".join(f"{k}: {v}"
                             for k, v in sorted(_LOSS_HELP.items())))
        self.add_item(
            section=section,
            title="loss_weight_4",
            datatype=int,
            group="loss",
            min_max=(0, 400),
            rounding=1,
            default=0,
            fixed=False,
            info="The amount of weight to apply to the fourth loss function.\n\n"
                 "\n\nThe value given here is as a percentage denoting how much the selected "
                 "function should contribute to the overall loss cost of the model. For example:"
                 "\n\t 100 - The loss calculated for the fourth loss function will be applied at "
                 "its full amount towards the overall loss score. "
                 "\n\t 25 - The loss calculated for the fourth loss function will be reduced by a "
                 "quarter prior to adding to the overall loss score. "
                 "\n\t 400 - The loss calculated for the fourth loss function will be mulitplied "
                 "4 times prior to adding to the overall loss score. "
                 "\n\t 0 - Disables the fourth loss function altogether.") </s> remove         if self._config["loss_function"] in self._uses_l2_reg and self._config["l2_reg_term"] > 0:
            logger.debug("Adding L2 Regularization for Structural Loss")
            loss_wrapper.add_loss(self._loss_dict["mse"],
                                  weight=self._config["l2_reg_term"] / 100.0,
                                  mask_channel=mask_channel)
 </s> add         logger.debug("Adding loss function: %s, weight: %s", loss_function, weight)
        loss_wrapper.add_loss(loss_function,
                              weight=weight,
                              mask_channel=self._mask_channels[0])

        channel_idx = 1
        for section in ("eye_multiplier", "mouth_multiplier"):
            mask_channel = self._mask_channels[channel_idx]
            multiplier = self._config[section] * 1.
            if multiplier > 1.:
                logger.debug("Adding section loss %s: %s", section, multiplier)
                loss_wrapper.add_loss(loss_function,
                                      weight=weight * multiplier,
                                      mask_channel=mask_channel)
            channel_idx += 1 </s> remove         self.add_item(
            section=section,
            title="l2_reg_term",
            datatype=int,
            group="loss",
            min_max=(0, 400),
            rounding=1,
            default=100,
            info="The amount of L2 Regularization to apply as a penalty to Structural Similarity "
                 "loss functions.\n\nNB: You should only adjust this if you know what you are "
                 "doing!\n\n"
                 "L2 regularization applies a penalty term to the given Loss function. This "
                 "penalty will only be applied if SSIM, MS-SSIM or GMSD is selected for the main "
                 "loss function, otherwise it is ignored."
                 "\n\nThe value given here is as a percentage weight of the main loss function. "
                 "For example:"
                 "\n\t 100 - Will give equal weighting to the main loss and the penalty function. "
                 "\n\t 25 - Will give the penalty function 1/4 of the weight of the main loss "
                 "function. "
                 "\n\t 400 - Will give the penalty function 4x as much importance as the main "
                 "loss function."
                 "\n\t 0 - Disables L2 Regularization altogether.")
 </s> add  </s> remove         mask_channel: int
            The channel that holds the mask in `y_true`, if a mask is used for the loss.
            `-1` if the input is not masked
 </s> add         loss_func: :class:`keras.losses.Loss`
            The loss function to add to the loss wrapper
        weight: float
            The amount of weight to apply to the given loss function
            * l2_reg_term - If this exists, set loss_function_2 to ``mse`` and loss_weight_2 to
            the value held in the old ``l2_reg_term`` item

              * loss - If old `dssim_loss` is ``true`` set new `loss_function` to `ssim` otherwise
              set it to `mae`. Remove old `dssim_loss` item
  
            * l2_reg_term - If this exists, set loss_function_2 to ``mse`` and loss_weight_2 to
            the value held in the old ``l2_reg_term`` item

              * masks - If `learn_mask` does not exist then it is set to ``True`` if `mask_type` is
              not ``None`` otherwise it is set to ``False``.
  
              * masks type - Replace removed masks 'dfl_full' and 'facehull' with `components` mask
keep keep add keep keep keep keep
 Training updates
  - Add multiple selected loss functions
  - Unlock loss as a model configuration
  - Phaze-A remove encoder scaling max xap 
plugins/train/model/_base/model.py