class_docstr: **Base class for Variational Inference**
  
  Communicates Operator, Approximation and Test Function to build Objective Function
  
  Parameters
  ----------
  op : Operator class    #:class:`~pymc.variational.operators`
  approx : Approximation class or instance    #:class:`~pymc.variational.approximations`
  tf : TestFunction instance  #?
  model : Model
      PyMC Model
  kwargs : kwargs passed to :class:`Operator` #:class:`~pymc.variational.operators`, optional
code: def _iterate_with_loss(self, s, n, step_func, progress, callbacks):
      def _infmean(input_array):
          """Return the mean of the finite values of the array"""
          input_array = input_array[np.isfinite(input_array)].astype(
              "float64"
          )
          if len(input_array) == 0:
              return np.nan
          else:
              return np.mean(input_array)
  
      scores = np.empty(n)
      scores[:] = np.nan
      i = 0
      try:
          for i in progress:
              e = step_func()
              if np.isnan(e):
                  scores = scores[:i]
                  self.hist = np.concatenate([self.hist, scores])
                  current_param = self.approx.params[0].get_value()
                  name_slc = []
                  tmp_hold = list(range(current_param.size))
                  for varname, slice_info in self.approx.groups[
                      0
                  ].ordering.items():
                      slclen = len(tmp_hold[slice_info[1]])
                      for j in range(slclen):
                          name_slc.append((varname, j))
                  index = np.where(np.isnan(current_param))[0]
                  errmsg = ["NaN occurred in optimization. "]
                  suggest_solution = (
                      "Try tracking this parameter: "
                      "http://docs.pymc.io/notebooks/variational_api_quickstart.html#Tracking-parameters"
                  )
                  try:
                      for ii in index:
                          errmsg.append(
                              "The current approximation of RV `{}`.ravel()[{}]"
                              " is NaN.".format(*name_slc[ii])
                          )
                      errmsg.append(suggest_solution)
                  except IndexError:
                      pass
                  raise FloatingPointError("\n".join(errmsg))
              scores[i] = e
              if i % 10 == 0:
                  avg_loss = _infmean(scores[max(0, i - 1000) : i + 1])
                  if hasattr(progress, "comment"):
                      progress.comment = (
                          f"Average Loss = {avg_loss:,.5g}"
                      )
                  avg_loss = scores[max(0, i - 1000) : i + 1].mean()
                  if hasattr(progress, "comment"):
                      progress.comment = (
                          f"Average Loss = {avg_loss:,.5g}"
                      )
              for callback in callbacks:
                  callback(self.approx, scores[: i + 1], i + s + 1)
      except (
          KeyboardInterrupt,
          StopIteration,
      ) as e:  # pragma: no cover
          # do not print log on the same line
          scores = scores[:i]
          if isinstance(e, StopIteration):
              logger.info(str(e))
          if n < 10:
              logger.info(
                  f"Interrupted at {i:,d} [{100 * i // n:.0f}%]: Loss = {scores[i]:,.5g}"
              )
          else:
              avg_loss = _infmean(scores[min(0, i - 1000) : i + 1])
              logger.info(
                  f"Interrupted at {i:,d} [{100 * i // n:.0f}%]: Average Loss = {avg_loss:,.5g}"
              )
      else:
          if n == 0:
              logger.info("Initialization only")
          elif n < 10:
              logger.info(f"Finished [100%]: Loss = {scores[-1]:,.5g}")
          else:
              avg_loss = _infmean(scores[max(0, i - 1000) : i + 1])
              logger.info(
                  f"Finished [100%]: Average Loss = {avg_loss:,.5g}"
              )
      self.hist = np.concatenate([self.hist, scores])
      return State(
          i + s, step=step_func, callbacks=callbacks, score=True
      )
  
imports: import collections
  import logging
  import warnings
  import numpy
  from fastprogress.fastprogress import progress_bar
  import pymc
  from pymc.variational import test_functions
  from pymc.variational.approximations import Empirical, FullRank, MeanField
  from pymc.variational.operators import KL, KSD
label_desc: Use image node_id 6 for calling the Inference obj's underlying member method code with example usage: obj._iterate_with_loss(s, n, step_func, progress, callbacks) and returns: State, np, np