          msg = "[Saved models]"
          if save_averages:
              lossmsg = ["face_{}: {:.5f}".format(side, avg)
                         for side, avg in zip(("a", "b"), save_averages)]
              msg += " - Average loss since last save: {}".format(", ".join(lossmsg))
          logger.info(msg)
  
      def _get_save_averages(self):
          """ Return the average loss since the last save iteration and reset historical loss """
          logger.debug("Getting save averages")
 
</s> remove             lossmsg = ["face_{}: {:.5f}".format(side, avg)
 </s> add             lossmsg = [f"face_{side}: {avg:.5f}" </s> remove         msg += " {}".format(additional_info)
 </s> add         msg += f" {additional_info}" </s> remove         times, loss = (np.array(times, dtype="float64"), np.array(loss, dtype="float32"))
 </s> add         if is_live and not all(len(val) == len(self._loss_labels) for val in loss):
            # TODO Many attempts have been made to fix this for live graph logging, and the issue
            # of non-consistent loss record sizes keeps coming up. In the meantime we shall swallow
            # any loss values that are of incorrect length so graph remains functional. This will,
            # most likely, lead to a mismatch on iteration count so a proper fix should be
            # implemented.

            # Timestamps and loss appears to remain consistent with each other, but sometimes loss
            # appears non-consistent. eg (lengths):
            # [2, 2, 2, 2, 2, 2, 2, 0] - last loss collection has zero length
            # [1, 2, 2, 2, 2, 2, 2, 2] - 1st loss collection has 1 length
            # [2, 2, 2, 3, 2, 2, 2] - 4th loss collection has 3 length

            logger.debug("Inconsistent loss found in collection: %s", loss)
            for idx in reversed(range(len(loss))):
                if len(loss[idx]) != len(self._loss_labels):
                    logger.debug("Removing loss/timestamps at position %s", idx)
                    del loss[idx]
                    del times[idx] </s> remove     msg = "{}  has been deprecated and will be removed from a future update.".format(function)
 </s> add     msg = f"{function}  has been deprecated and will be removed from a future update." </s> remove         retval = dict()
 </s> add         retval = {}
            msg += f" - Average loss since last save: {', '.join(lossmsg)}"
          msg = "[Saved models]"
          if save_averages:
              lossmsg = ["face_{}: {:.5f}".format(side, avg)
                         for side, avg in zip(("a", "b"), save_averages)]
            msg += f" - Average loss since last save: {', '.join(lossmsg)}"
          logger.info(msg)
  
      def _get_save_averages(self):
          """ Return the average loss since the last save iteration and reset historical loss """
          logger.debug("Getting save averages")
keep keep keep keep replace keep keep keep keep keep
 Update code to support Tensorflow versions up to 2.8 (#1213)

* Update maximum tf version in setup + requirements

* - bump max version of tf version in launcher
- standardise tf version check

* update keras get_custom_objects  for tf>2.6

* bugfix: force black text in GUI file dialogs (linux)

* dssim loss - Move to stock tf.ssim function

* Update optimizer imports for compatibility

* fix logging for tf2.8

* Fix GUI graphing for TF2.8

* update tests

* bump requirements.txt versions

* Remove limit on nvidia-ml-py

* Graphing bugfixes
  - Prevent live graph from displaying if data not yet available

* bugfix: Live graph. Collect loss labels correctly

* fix: live graph - swallow inconsistent loss errors

* Bugfix: Prevent live graph from clearing during training

* Fix graphing for AMD 
plugins/train/model/_base.py