# Module `bbrl.utils.logger`

Expand source code

    # This source code is licensed under the MIT license found in the
    # LICENSE file in the root directory of this source tree.
    #

    import bz2
    import pickle
    import time

    import numpy as np
    import pandas as pd

    from omegaconf import DictConfig
    from torch.utils.tensorboard import SummaryWriter
    from tqdm import tqdm

    class TFPrefixLogger:
        def __init__(self, prefix, logger):
            self.logger = logger
            self.prefix = prefix

        def add_images(self, name, value, iteration):
            self.logger.add_images(self.prefix + name, value, iteration)

        def add_figure(self, name, value, iteration):
            self.logger.add_figure(self.prefix + name, value, iteration)

        def add_scalar(self, name, value, iteration):
            self.logger.add_scalar(self.prefix + name, value, iteration)

        def add_video(self, name, value, iteration, fps=10):
            self.logger.add_video(self.prefix + name, value, iteration, fps)

        def message(self, msg, from_name=""):
            self.logger.message(msg, from_name=self.prefix + from_name)

        def debug(self, msg, from_name=""):
            self.logger.debug(msg, from_name=self.prefix + from_name)

        def get_logger(self, prefix):
            return TFPrefixLogger(self.prefix + prefix, self.logger)

        def close(self):
            pass

    class TFLogger(SummaryWriter):
        """A logger that stores informations both in tensorboard and CSV formats"""

        def __init__(
            self,
            log_dir=None,
            hps={},
            cache_size=10000,
            every_n_seconds=None,
            modulo=1,
            verbose=False,
            use_zip=True,
            save_tensorboard=True,
        ):
            SummaryWriter.__init__(self, log_dir=log_dir)
            self.save_tensorboard = save_tensorboard
            self.use_zip = use_zip
            self.save_every = cache_size
            self.modulo = modulo
            self.written_values = {}
            self.log_dir = log_dir
            self.every_n_seconds = every_n_seconds
            if self.every_n_seconds is None:
                print(
                    "[Deprecated] bbrl.utils.logger: use 'every_n_seconds' instead of cache_size"
                )
            else:
                self.save_every = None
            self._start_time = time.time()
            self.verbose = verbose

            self.picklename = log_dir + "/db.pickle.bzip2"
            if not self.use_zip:
                self.picklename = log_dir + "/db.pickle"
            self.to_pickle = []
            if len(hps) > 0:
                f = open(log_dir + "/params.json", "wt")
                f.write(str(hps) + "\n")
                f.close()

                outfile = open(log_dir + "/params.pickle", "wb")
                pickle.dump(hps, outfile)
                outfile.close()
                self.add_text("Hyperparameters", str(hps))

        def _omegaconf_to_dict(self, hps):
            d = {}
            for k, v in hps.items():
                if isinstance(v, DictConfig):
                    d[k] = self._omegaconf_to_dict(v)
                else:
                    d[k] = v
            return d

        def _to_dict(self, h):
            if isinstance(h, dict):
                return {k: self._to_dict(v) for k, v in h.items()}
            if isinstance(h, DictConfig):
                return {k: self._to_dict(v) for k, v in h.items()}
            else:
                return h

        def save_hps(self, hps, verbose=True):
            hps = self._to_dict(hps)
            if verbose:
                print(hps)
            f = open(self.log_dir + "/params.json", "wt")
            f.write(str(hps) + "\n")
            f.close()

            outfile = open(self.log_dir + "/params.pickle", "wb")
            pickle.dump(hps, outfile)
            outfile.close()
            self.add_text("Hyperparameters", str(hps))

        def get_logger(self, prefix):
            return TFPrefixLogger(prefix, self)

        def message(self, msg, from_name=""):
            print("[", from_name, "]: ", msg)

        def debug(self, msg, from_name=""):
            print("[DEBUG] [", from_name, "]: ", msg)

        def _to_pickle(self, name, value, iteration):
            self.to_pickle.append((name, iteration, value))

            if self.every_n_seconds is not None:
                if time.time() - self._start_time > self.every_n_seconds:
                    if self.use_zip:
                        f = bz2.BZ2File(self.picklename, "ab")
                        pickle.dump(self.to_pickle, f)
                        f.close()
                    else:
                        f = open(self.picklename, "ab")
                        pickle.dump(self.to_pickle, f)
                        f.close()
                    self._start_time = time.time()
                    self.to_pickle = []
            else:
                if len(self.to_pickle) > self.save_every:
                    if self.use_zip:
                        f = bz2.BZ2File(self.picklename, "ab")
                        pickle.dump(self.to_pickle, f)
                        f.close()
                    else:
                        f = open(self.picklename, "ab")
                        pickle.dump(self.to_pickle, f)
                        f.close()
                    self.to_pickle = []

        def add_images(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.save_tensorboard:
                SummaryWriter.add_images(self, name, value, iteration)

        def add_figure(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.save_tensorboard:
                SummaryWriter.add_figure(self, name, value, iteration)

        def add_scalar(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.verbose:
                print("['" + name + "' at " + str(iteration) + "] = " + str(value))

            if isinstance(value, int) or isinstance(value, float):
                if self.save_tensorboard:
                    SummaryWriter.add_scalar(self, name, value, iteration)

        def add_video(self, name, value, iteration, fps=10):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value.numpy(), iteration)
            if self.save_tensorboard:
                SummaryWriter.add_video(self, name, value, iteration, fps=fps)

        def close(self):
            if len(self.to_pickle) > 0:
                if self.use_zip:
                    f = bz2.BZ2File(self.picklename, "ab")
                    pickle.dump(self.to_pickle, f)
                    f.close()
                else:
                    f = open(self.picklename, "ab")
                    pickle.dump(self.to_pickle, f)
                    f.close()
                self.to_pickle = []

            SummaryWriter.close(self)

            f = open(self.log_dir + "/done", "wt")
            f.write("Done\n")
            f.close()

    class Log:
        def __init__(self, hps, values):
            self.hps = hps
            self.values = values
            max_length = max([len(v) for v in self.values])
            for k in values:
                while len(values[k]) < max_length:
                    values[k].append(None)
            self.length = max_length

        def to_xy(self, name):
            assert name in self.values
            x, y = [], []
            for k, v in enumerate(self.values[name]):
                if v is not None:
                    x.append(k)
                    y.append(v)
            return x, y

        def to_dataframe(self, with_hps=False):
            max_len = np.max([len(k) for v, k in self.values.items()])
            nv = {}
            for k, v in self.values.items():
                nnv = [None] * (max_len - len(v))
                nv[k] = v + nnv
            self.values = nv
            it = list(np.arange(max_len))
            d = {**self.values, **{"iteration": it}}
            _pd = pd.DataFrame(d)
            if with_hps:
                for k in self.hps:
                    _pd["_hp/" + k] = self.hps[k]
            return _pd

        def get_at(self, name, iteration):
            return self.values[name][iteration]

        def get(self, name, keep_none=False):
            v = self.values[name]
            if not keep_none:
                return [k for k in v if k is not None]
            else:
                return v

        def replace_none_(self, name):
            v = self.values[name]
            last_v = None
            first_v = None
            r = []
            for k in range(len(v)):
                if v[k] is None:
                    r.append(last_v)
                else:
                    r.append(v[k])
                    if last_v is None:
                        first_v = v[k]
                    last_v = v[k]

            p = 0
            while r[p] is None:
                r[p] = first_v
                p += 1
            self.values[name] = r

        def max(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            return np.max(vv)

        def min(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            return np.min(vv)

        def argmin(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            _max = np.max(vv)

            for k in range(len(v)):
                if v[k] is None:
                    vv.append(_max + 1.0)
                else:
                    vv.append(v[k])
            return np.argmin(vv)

        def argmax(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            _min = np.min(vv)
            vv = []
            for k in range(len(v)):
                if v[k] is None:
                    vv.append(_min - 1.0)
                else:
                    vv.append(v[k])
            return np.argmax(vv)

    class Logs:
        def __init__(self):
            self.logs = []
            self.hp_names = None
            self.filenames = []

        def _add(self, log):
            self.hp_names = {k: True for k in log.hps}
            for log in self.logs:
                for k in log.hps:
                    if k not in log.hps:
                        log.hps[k] = "none"

            self.logs.append(log)

        def add(self, logs):
            if isinstance(logs, Log):
                self._add(logs)
            else:
                for log in logs:
                    self._add(log)

        def max(self, function):
            alls = [function(log) for log in self.logs]
            idx = np.argmax(alls)
            return self.logs[idx]

        def columns(self):
            return list(self.logs[0].values)

        def hps(self):
            return list(self.hp_names)

        def size(self):
            return len(self.logs)

        def filter(self, hp_name, test_fn):
            logs = Logs()
            if not callable(test_fn):
                for log in self.logs:
                    h = log.hps[hp_name]
                    if h == test_fn:
                        logs.add(log)
            else:
                for log in self.logs:
                    if test_fn(log.hps[hp_name]):
                        logs.add(log)
            return logs

        def unique_hps(self, name):
            r = {}
            for log in self.logs:
                v = log.hps[name]
                r[v] = 1
            return list(r.keys())

        def __len__(self):
            return len(self.logs)

        def to_dataframe(self):
            rdf = None
            for log in tqdm(self.logs):
                df = log.to_dataframe(with_hps=True)
                if rdf is None:
                    rdf = [df]
                else:
                    rdf.append(df)
            return pd.concat(rdf)

        # def plot(self, y, x, hue=None, style=None, row=None, col=None, kind="line"):

    def flattify(d):
        r = {}
        for k, v in d.items():
            if isinstance(v, dict):
                rr = flattify(v)
                rrr = {k + "/" + kk: rrr for kk, rrr in rr.items()}
                r = {**r, **rrr}
            elif isinstance(v, list):
                r[k] = str(v)
            else:
                r[k] = v
        return r

    def read_log(directory, use_bz2=True, debug=False):
        if use_bz2:
            picklename = directory + "/db.pickle.bzip2"
            f = bz2.BZ2File(picklename, "rb")
        else:
            picklename = directory + "/db.pickle"
            f = open(picklename, "rb")
        values = {}

        try:
            while True:
                a = pickle.load(f)
                if a is not None:
                    for name, iteration, value in a:
                        # print(name,iteration,value)
                        if debug:
                            print(name, value, type(value))
                        if isinstance(value, np.int64):
                            value = int(value)
                        if (
                            isinstance(value, int)
                            or isinstance(value, float)
                            or isinstance(value, str)
                        ):
                            if name not in values:
                                values[name] = []
                            while len(values[name]) < iteration + 1:
                                values[name].append(None)
                            values[name][iteration] = value
        except pickle.PickleError:
            f.close()
        f = open(directory + "/params.pickle", "rb")
        params = pickle.load(f)
        params = eval(str(params))
        params = flattify(params)
        f.close()
        log = Log(params, values)
        log.from_directory = directory
        # f=open(directory+"/fast.pickle","wb")
        # pickle.dump(log,f)
        # f.close()

        return log

    def get_directories(directory, use_bz2=True):
        import os.path

        name = "db.pickle"
        if use_bz2:
            name = "db.pickle.bzip2"

        return [
            dirpath
            for dirpath, dirnames, filenames in os.walk(directory)
            if name in filenames
        ]

    def read_directories(directories, use_bz2=True):

        logs = Logs()
        for dirpath in directories:
            log = read_log(dirpath, use_bz2)
            logs.add(log)
        print("Found %d logs" % logs.size())
        return logs

    def read_directory(directory, use_bz2=True):
        import os.path

        logs = Logs()
        name = "db.pickle"
        if use_bz2:
            name = "db.pickle.bzip2"
        for dirpath, dirnames, filenames in os.walk(directory):
            if name in filenames:
                log = read_log(dirpath, use_bz2)
                logs.add(log)
        print("Found %d logs" % logs.size())
        return logs

    def _create_col(df, hps, _name):
        vs = []
        for k, v in df.groupby(hps):
            n = {hps[i]: k[i] for i in range(len(hps))}
            v = v.copy()
            name = ",".join([str(k) + "=" + str(n[k]) for k in n])
            print(name)
            print(_name)
            v[_name] = name
            vs.append(v)
        return pd.concat(vs)

    def plot_dataframe(
        df, y, x="iteration", hue=None, style=None, row=None, col=None, kind="line"
    ):
        import seaborn as sns

        cols = [y, x]
        if isinstance(row, list):
            cols += row
        else:
            cols += [row]
        if isinstance(col, list):
            cols += col
        else:
            cols += [col]
        if isinstance(style, list):
            cols += style
        else:
            cols += [style]
        if isinstance(hue, list):
            cols += hue
        else:
            cols += [hue]
        cols = [c for c in cols if c is not None]
        df = df[cols].dropna()

        if isinstance(row, list):
            df = _create_col(df, row, "__row")
            row = "__row"
        if isinstance(col, list):
            df = _create_col(df, col, "__col")
            col = "__col"
        if isinstance(style, list):
            df = _create_col(df, style, "__style")
            style = "__style"
        if isinstance(hue, list):
            df = _create_col(df, hue, "__hue")
            hue = "__hue"

        # df = convert_iteration_to_steps(df)

        sns.relplot(x=x, y=y, hue=hue, style=style, row=row, col=col, data=df, kind=kind)

## Functions

`def flattify(d)`
  Expand source code

      def flattify(d):
          r = {}
          for k, v in d.items():
              if isinstance(v, dict):
                  rr = flattify(v)
                  rrr = {k + "/" + kk: rrr for kk, rrr in rr.items()}
                  r = {**r, **rrr}
              elif isinstance(v, list):
                  r[k] = str(v)
              else:
                  r[k] = v
          return r

`def get_directories(directory, use_bz2=True)`
  Expand source code

      def get_directories(directory, use_bz2=True):
          import os.path

          name = "db.pickle"
          if use_bz2:
              name = "db.pickle.bzip2"

          return [
              dirpath
              for dirpath, dirnames, filenames in os.walk(directory)
              if name in filenames
          ]

`def plot_dataframe(df, y, x='iteration', hue=None, style=None, row=None, col=None, kind='line')`
  Expand source code

      def plot_dataframe(
          df, y, x="iteration", hue=None, style=None, row=None, col=None, kind="line"
      ):
          import seaborn as sns

          cols = [y, x]
          if isinstance(row, list):
              cols += row
          else:
              cols += [row]
          if isinstance(col, list):
              cols += col
          else:
              cols += [col]
          if isinstance(style, list):
              cols += style
          else:
              cols += [style]
          if isinstance(hue, list):
              cols += hue
          else:
              cols += [hue]
          cols = [c for c in cols if c is not None]
          df = df[cols].dropna()

          if isinstance(row, list):
              df = _create_col(df, row, "__row")
              row = "__row"
          if isinstance(col, list):
              df = _create_col(df, col, "__col")
              col = "__col"
          if isinstance(style, list):
              df = _create_col(df, style, "__style")
              style = "__style"
          if isinstance(hue, list):
              df = _create_col(df, hue, "__hue")
              hue = "__hue"

          # df = convert_iteration_to_steps(df)

          sns.relplot(x=x, y=y, hue=hue, style=style, row=row, col=col, data=df, kind=kind)

`def read_directories(directories, use_bz2=True)`
  Expand source code

      def read_directories(directories, use_bz2=True):

          logs = Logs()
          for dirpath in directories:
              log = read_log(dirpath, use_bz2)
              logs.add(log)
          print("Found %d logs" % logs.size())
          return logs

`def read_directory(directory, use_bz2=True)`
  Expand source code

      def read_directory(directory, use_bz2=True):
          import os.path

          logs = Logs()
          name = "db.pickle"
          if use_bz2:
              name = "db.pickle.bzip2"
          for dirpath, dirnames, filenames in os.walk(directory):
              if name in filenames:
                  log = read_log(dirpath, use_bz2)
                  logs.add(log)
          print("Found %d logs" % logs.size())
          return logs

`def read_log(directory, use_bz2=True, debug=False)`
  Expand source code

      def read_log(directory, use_bz2=True, debug=False):
          if use_bz2:
              picklename = directory + "/db.pickle.bzip2"
              f = bz2.BZ2File(picklename, "rb")
          else:
              picklename = directory + "/db.pickle"
              f = open(picklename, "rb")
          values = {}

          try:
              while True:
                  a = pickle.load(f)
                  if a is not None:
                      for name, iteration, value in a:
                          # print(name,iteration,value)
                          if debug:
                              print(name, value, type(value))
                          if isinstance(value, np.int64):
                              value = int(value)
                          if (
                              isinstance(value, int)
                              or isinstance(value, float)
                              or isinstance(value, str)
                          ):
                              if name not in values:
                                  values[name] = []
                              while len(values[name]) < iteration + 1:
                                  values[name].append(None)
                              values[name][iteration] = value
          except pickle.PickleError:
              f.close()
          f = open(directory + "/params.pickle", "rb")
          params = pickle.load(f)
          params = eval(str(params))
          params = flattify(params)
          f.close()
          log = Log(params, values)
          log.from_directory = directory
          # f=open(directory+"/fast.pickle","wb")
          # pickle.dump(log,f)
          # f.close()

          return log

## Classes

`class Log (hps, values)`
  Expand source code

      class Log:
          def __init__(self, hps, values):
              self.hps = hps
              self.values = values
              max_length = max([len(v) for v in self.values])
              for k in values:
                  while len(values[k]) < max_length:
                      values[k].append(None)
              self.length = max_length

          def to_xy(self, name):
              assert name in self.values
              x, y = [], []
              for k, v in enumerate(self.values[name]):
                  if v is not None:
                      x.append(k)
                      y.append(v)
              return x, y

          def to_dataframe(self, with_hps=False):
              max_len = np.max([len(k) for v, k in self.values.items()])
              nv = {}
              for k, v in self.values.items():
                  nnv = [None] * (max_len - len(v))
                  nv[k] = v + nnv
              self.values = nv
              it = list(np.arange(max_len))
              d = {**self.values, **{"iteration": it}}
              _pd = pd.DataFrame(d)
              if with_hps:
                  for k in self.hps:
                      _pd["_hp/" + k] = self.hps[k]
              return _pd

          def get_at(self, name, iteration):
              return self.values[name][iteration]

          def get(self, name, keep_none=False):
              v = self.values[name]
              if not keep_none:
                  return [k for k in v if k is not None]
              else:
                  return v

          def replace_none_(self, name):
              v = self.values[name]
              last_v = None
              first_v = None
              r = []
              for k in range(len(v)):
                  if v[k] is None:
                      r.append(last_v)
                  else:
                      r.append(v[k])
                      if last_v is None:
                          first_v = v[k]
                      last_v = v[k]

              p = 0
              while r[p] is None:
                  r[p] = first_v
                  p += 1
              self.values[name] = r

          def max(self, name):
              v = self.values[name]
              vv = [k for k in v if k is not None]
              return np.max(vv)

          def min(self, name):
              v = self.values[name]
              vv = [k for k in v if k is not None]
              return np.min(vv)

          def argmin(self, name):
              v = self.values[name]
              vv = [k for k in v if k is not None]
              _max = np.max(vv)

              for k in range(len(v)):
                  if v[k] is None:
                      vv.append(_max + 1.0)
                  else:
                      vv.append(v[k])
              return np.argmin(vv)

          def argmax(self, name):
              v = self.values[name]
              vv = [k for k in v if k is not None]
              _min = np.min(vv)
              vv = []
              for k in range(len(v)):
                  if v[k] is None:
                      vv.append(_min - 1.0)
                  else:
                      vv.append(v[k])
              return np.argmax(vv)

  ### Methods

  `def argmax(self, name)`
    Expand source code

        def argmax(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            _min = np.min(vv)
            vv = []
            for k in range(len(v)):
                if v[k] is None:
                    vv.append(_min - 1.0)
                else:
                    vv.append(v[k])
            return np.argmax(vv)

  `def argmin(self, name)`
    Expand source code

        def argmin(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            _max = np.max(vv)

            for k in range(len(v)):
                if v[k] is None:
                    vv.append(_max + 1.0)
                else:
                    vv.append(v[k])
            return np.argmin(vv)

  `def get(self, name, keep_none=False)`
    Expand source code

        def get(self, name, keep_none=False):
            v = self.values[name]
            if not keep_none:
                return [k for k in v if k is not None]
            else:
                return v

  `def get_at(self, name, iteration)`
    Expand source code

        def get_at(self, name, iteration):
            return self.values[name][iteration]

  `def max(self, name)`
    Expand source code

        def max(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            return np.max(vv)

  `def min(self, name)`
    Expand source code

        def min(self, name):
            v = self.values[name]
            vv = [k for k in v if k is not None]
            return np.min(vv)

  `def replace_none_(self, name)`
    Expand source code

        def replace_none_(self, name):
            v = self.values[name]
            last_v = None
            first_v = None
            r = []
            for k in range(len(v)):
                if v[k] is None:
                    r.append(last_v)
                else:
                    r.append(v[k])
                    if last_v is None:
                        first_v = v[k]
                    last_v = v[k]

            p = 0
            while r[p] is None:
                r[p] = first_v
                p += 1
            self.values[name] = r

  `def to_dataframe(self, with_hps=False)`
    Expand source code

        def to_dataframe(self, with_hps=False):
            max_len = np.max([len(k) for v, k in self.values.items()])
            nv = {}
            for k, v in self.values.items():
                nnv = [None] * (max_len - len(v))
                nv[k] = v + nnv
            self.values = nv
            it = list(np.arange(max_len))
            d = {**self.values, **{"iteration": it}}
            _pd = pd.DataFrame(d)
            if with_hps:
                for k in self.hps:
                    _pd["_hp/" + k] = self.hps[k]
            return _pd

  `def to_xy(self, name)`
    Expand source code

        def to_xy(self, name):
            assert name in self.values
            x, y = [], []
            for k, v in enumerate(self.values[name]):
                if v is not None:
                    x.append(k)
                    y.append(v)
            return x, y

`class Logs`
  Expand source code

      class Logs:
          def __init__(self):
              self.logs = []
              self.hp_names = None
              self.filenames = []

          def _add(self, log):
              self.hp_names = {k: True for k in log.hps}
              for log in self.logs:
                  for k in log.hps:
                      if k not in log.hps:
                          log.hps[k] = "none"

              self.logs.append(log)

          def add(self, logs):
              if isinstance(logs, Log):
                  self._add(logs)
              else:
                  for log in logs:
                      self._add(log)

          def max(self, function):
              alls = [function(log) for log in self.logs]
              idx = np.argmax(alls)
              return self.logs[idx]

          def columns(self):
              return list(self.logs[0].values)

          def hps(self):
              return list(self.hp_names)

          def size(self):
              return len(self.logs)

          def filter(self, hp_name, test_fn):
              logs = Logs()
              if not callable(test_fn):
                  for log in self.logs:
                      h = log.hps[hp_name]
                      if h == test_fn:
                          logs.add(log)
              else:
                  for log in self.logs:
                      if test_fn(log.hps[hp_name]):
                          logs.add(log)
              return logs

          def unique_hps(self, name):
              r = {}
              for log in self.logs:
                  v = log.hps[name]
                  r[v] = 1
              return list(r.keys())

          def __len__(self):
              return len(self.logs)

          def to_dataframe(self):
              rdf = None
              for log in tqdm(self.logs):
                  df = log.to_dataframe(with_hps=True)
                  if rdf is None:
                      rdf = [df]
                  else:
                      rdf.append(df)
              return pd.concat(rdf)

          # def plot(self, y, x, hue=None, style=None, row=None, col=None, kind="line"):

  ### Methods

  `def add(self, logs)`
    Expand source code

        def add(self, logs):
            if isinstance(logs, Log):
                self._add(logs)
            else:
                for log in logs:
                    self._add(log)

  `def columns(self)`
    Expand source code

        def columns(self):
            return list(self.logs[0].values)

  `def filter(self, hp_name, test_fn)`
    Expand source code

        def filter(self, hp_name, test_fn):
            logs = Logs()
            if not callable(test_fn):
                for log in self.logs:
                    h = log.hps[hp_name]
                    if h == test_fn:
                        logs.add(log)
            else:
                for log in self.logs:
                    if test_fn(log.hps[hp_name]):
                        logs.add(log)
            return logs

  `def hps(self)`
    Expand source code

        def hps(self):
            return list(self.hp_names)

  `def max(self, function)`
    Expand source code

        def max(self, function):
            alls = [function(log) for log in self.logs]
            idx = np.argmax(alls)
            return self.logs[idx]

  `def size(self)`
    Expand source code

        def size(self):
            return len(self.logs)

  `def to_dataframe(self)`
    Expand source code

        def to_dataframe(self):
            rdf = None
            for log in tqdm(self.logs):
                df = log.to_dataframe(with_hps=True)
                if rdf is None:
                    rdf = [df]
                else:
                    rdf.append(df)
            return pd.concat(rdf)

  `def unique_hps(self, name)`
    Expand source code

        def unique_hps(self, name):
            r = {}
            for log in self.logs:
                v = log.hps[name]
                r[v] = 1
            return list(r.keys())

`class TFLogger (log_dir=None, hps={}, cache_size=10000, every_n_seconds=None, modulo=1, verbose=False, use_zip=True, save_tensorboard=True)`

  A logger that stores informations both in tensorboard and CSV formats

  Creates a `SummaryWriter` that will write out events and summaries to the event file.

  ## Args

  `log_dir` :`string`
    Save directory location. Default is runs/CURRENT_DATETIME_HOSTNAME, which changes after each run. Use hierarchical folder structure to compare between runs easily. e.g. pass in 'runs/exp1', 'runs/exp2', etc. for each new experiment to compare across them.
  `comment` :`string`
    Comment log_dir suffix appended to the default `log_dir`. If `log_dir` is assigned, this argument has no effect.
  purge_step (int):
  When logging crashes at step :math:`T+X` and restarts at step :math:`T`,
  any events whose global_step larger or equal to :math:`T` will be
  purged and hidden from TensorBoard.
  Note that crashed and resumed experiments should have the same `log_dir`.
  `max_queue` :`int`
    Size of the queue for pending events and summaries before one of the 'add' calls forces a flush to disk. Default is ten items.
  `flush_secs` :`int`
    How often, in seconds, to flush the pending events and summaries to disk. Default is every two minutes.
  `filename_suffix` :`string`
    Suffix added to all event filenames in the log_dir directory. More details on filename construction in tensorboard.summary.writer.event_file_writer.EventFileWriter.

  Examples::

      from torch.utils.tensorboard import SummaryWriter

      # create a summary writer with automatically generated folder name.
      writer = SummaryWriter()
      # folder location: runs/May04_22-14-54_s-MacBook-Pro.local/

      # create a summary writer using the specified folder name.
      writer = SummaryWriter("my_experiment")
      # folder location: my_experiment

      # create a summary writer with comment appended.
      writer = SummaryWriter(comment="LR_0.1_BATCH_16")
      # folder location: runs/May04_22-14-54_s-MacBook-Pro.localLR_0.1_BATCH_16/

  Expand source code

      class TFLogger(SummaryWriter):
          """A logger that stores informations both in tensorboard and CSV formats"""

          def __init__(
              self,
              log_dir=None,
              hps={},
              cache_size=10000,
              every_n_seconds=None,
              modulo=1,
              verbose=False,
              use_zip=True,
              save_tensorboard=True,
          ):
              SummaryWriter.__init__(self, log_dir=log_dir)
              self.save_tensorboard = save_tensorboard
              self.use_zip = use_zip
              self.save_every = cache_size
              self.modulo = modulo
              self.written_values = {}
              self.log_dir = log_dir
              self.every_n_seconds = every_n_seconds
              if self.every_n_seconds is None:
                  print(
                      "[Deprecated] bbrl.utils.logger: use 'every_n_seconds' instead of cache_size"
                  )
              else:
                  self.save_every = None
              self._start_time = time.time()
              self.verbose = verbose

              self.picklename = log_dir + "/db.pickle.bzip2"
              if not self.use_zip:
                  self.picklename = log_dir + "/db.pickle"
              self.to_pickle = []
              if len(hps) > 0:
                  f = open(log_dir + "/params.json", "wt")
                  f.write(str(hps) + "\n")
                  f.close()

                  outfile = open(log_dir + "/params.pickle", "wb")
                  pickle.dump(hps, outfile)
                  outfile.close()
                  self.add_text("Hyperparameters", str(hps))

          def _omegaconf_to_dict(self, hps):
              d = {}
              for k, v in hps.items():
                  if isinstance(v, DictConfig):
                      d[k] = self._omegaconf_to_dict(v)
                  else:
                      d[k] = v
              return d

          def _to_dict(self, h):
              if isinstance(h, dict):
                  return {k: self._to_dict(v) for k, v in h.items()}
              if isinstance(h, DictConfig):
                  return {k: self._to_dict(v) for k, v in h.items()}
              else:
                  return h

          def save_hps(self, hps, verbose=True):
              hps = self._to_dict(hps)
              if verbose:
                  print(hps)
              f = open(self.log_dir + "/params.json", "wt")
              f.write(str(hps) + "\n")
              f.close()

              outfile = open(self.log_dir + "/params.pickle", "wb")
              pickle.dump(hps, outfile)
              outfile.close()
              self.add_text("Hyperparameters", str(hps))

          def get_logger(self, prefix):
              return TFPrefixLogger(prefix, self)

          def message(self, msg, from_name=""):
              print("[", from_name, "]: ", msg)

          def debug(self, msg, from_name=""):
              print("[DEBUG] [", from_name, "]: ", msg)

          def _to_pickle(self, name, value, iteration):
              self.to_pickle.append((name, iteration, value))

              if self.every_n_seconds is not None:
                  if time.time() - self._start_time > self.every_n_seconds:
                      if self.use_zip:
                          f = bz2.BZ2File(self.picklename, "ab")
                          pickle.dump(self.to_pickle, f)
                          f.close()
                      else:
                          f = open(self.picklename, "ab")
                          pickle.dump(self.to_pickle, f)
                          f.close()
                      self._start_time = time.time()
                      self.to_pickle = []
              else:
                  if len(self.to_pickle) > self.save_every:
                      if self.use_zip:
                          f = bz2.BZ2File(self.picklename, "ab")
                          pickle.dump(self.to_pickle, f)
                          f.close()
                      else:
                          f = open(self.picklename, "ab")
                          pickle.dump(self.to_pickle, f)
                          f.close()
                      self.to_pickle = []

          def add_images(self, name, value, iteration):
              iteration = int(iteration / self.modulo) * self.modulo
              if (name, iteration) in self.written_values:
                  return
              else:
                  self.written_values[(name, iteration)] = True

              self._to_pickle(name, value, iteration)
              if self.save_tensorboard:
                  SummaryWriter.add_images(self, name, value, iteration)

          def add_figure(self, name, value, iteration):
              iteration = int(iteration / self.modulo) * self.modulo
              if (name, iteration) in self.written_values:
                  return
              else:
                  self.written_values[(name, iteration)] = True

              self._to_pickle(name, value, iteration)
              if self.save_tensorboard:
                  SummaryWriter.add_figure(self, name, value, iteration)

          def add_scalar(self, name, value, iteration):
              iteration = int(iteration / self.modulo) * self.modulo
              if (name, iteration) in self.written_values:
                  return
              else:
                  self.written_values[(name, iteration)] = True

              self._to_pickle(name, value, iteration)
              if self.verbose:
                  print("['" + name + "' at " + str(iteration) + "] = " + str(value))

              if isinstance(value, int) or isinstance(value, float):
                  if self.save_tensorboard:
                      SummaryWriter.add_scalar(self, name, value, iteration)

          def add_video(self, name, value, iteration, fps=10):
              iteration = int(iteration / self.modulo) * self.modulo
              if (name, iteration) in self.written_values:
                  return
              else:
                  self.written_values[(name, iteration)] = True

              self._to_pickle(name, value.numpy(), iteration)
              if self.save_tensorboard:
                  SummaryWriter.add_video(self, name, value, iteration, fps=fps)

          def close(self):
              if len(self.to_pickle) > 0:
                  if self.use_zip:
                      f = bz2.BZ2File(self.picklename, "ab")
                      pickle.dump(self.to_pickle, f)
                      f.close()
                  else:
                      f = open(self.picklename, "ab")
                      pickle.dump(self.to_pickle, f)
                      f.close()
                  self.to_pickle = []

              SummaryWriter.close(self)

              f = open(self.log_dir + "/done", "wt")
              f.write("Done\n")
              f.close()

  ### Ancestors

  - torch.utils.tensorboard.writer.SummaryWriter

  ### Methods

  `def add_figure(self, name, value, iteration)`

    Render matplotlib figure into an image and add it to summary.

    Note that this requires the `matplotlib` package.

    ## Args

    `tag` :`string`
      Data identifier
    figure (matplotlib.pyplot.figure) or list of figures: Figure or a list of figures
    `global_step` :`int`
      Global step value to record
    `close` :`bool`
      Flag to automatically close the figure
    `walltime` :`float`
      Optional override default walltime (time.time()) seconds after epoch of event
    Expand source code

        def add_figure(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.save_tensorboard:
                SummaryWriter.add_figure(self, name, value, iteration)

  `def add_images(self, name, value, iteration)`

    Add batched image data to summary.

    Note that this requires the `pillow` package.

    ## Args

    `tag` :`string`
      Data identifier
    img_tensor (torch.Tensor, numpy.array, or string/blobname): Image data
    `global_step` :`int`
      Global step value to record
    `walltime` :`float`
      Optional override default walltime (time.time()) seconds after epoch of event
    `dataformats` :`string`
      Image data format specification of the form NCHW, NHWC, CHW, HWC, HW, WH, etc.

    ## Shape

    img_tensor: Default is :math:`(N, 3, H, W)`. If `dataformats` is specified, other shape will be accepted. e.g. NCHW or NHWC.

    Examples::

        from torch.utils.tensorboard import SummaryWriter
        import numpy as np

        img_batch = np.zeros((16, 3, 100, 100))
        for i in range(16):
            img_batch[i, 0] = np.arange(0, 10000).reshape(100, 100) / 10000 / 16 * i
            img_batch[i, 1] = (1 - np.arange(0, 10000).reshape(100, 100) / 10000) / 16 * i

        writer = SummaryWriter()
        writer.add_images('my_image_batch', img_batch, 0)
        writer.close()

    Expected result:

    Expand source code

        def add_images(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.save_tensorboard:
                SummaryWriter.add_images(self, name, value, iteration)

  `def add_scalar(self, name, value, iteration)`

    Add scalar data to summary.

    ## Args

    `tag` :`string`
      Data identifier
    scalar_value (float or string/blobname): Value to save
    `global_step` :`int`
      Global step value to record
    `walltime` :`float`
      Optional override default walltime (time.time()) with seconds after epoch of event
    `new_style` :`boolean`
      Whether to use new style (tensor field) or old style (simple_value field). New style could lead to faster data loading.

    Examples::

        from torch.utils.tensorboard import SummaryWriter
        writer = SummaryWriter()
        x = range(100)
        for i in x:
            writer.add_scalar('y=2x', i * 2, i)
        writer.close()

    Expected result:

    Expand source code

        def add_scalar(self, name, value, iteration):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value, iteration)
            if self.verbose:
                print("['" + name + "' at " + str(iteration) + "] = " + str(value))

            if isinstance(value, int) or isinstance(value, float):
                if self.save_tensorboard:
                    SummaryWriter.add_scalar(self, name, value, iteration)

  `def add_video(self, name, value, iteration, fps=10)`

    Add video data to summary.

    Note that this requires the `moviepy` package.

    ## Args

    `tag` :`string`
      Data identifier
    `vid_tensor` :`torch.Tensor`
      Video data
    `global_step` :`int`
      Global step value to record
    `fps` :`float` or `int`
      Frames per second
    `walltime` :`float`
      Optional override default walltime (time.time()) seconds after epoch of event

    ## Shape

    vid_tensor: :math:`(N, T, C, H, W)`. The values should lie in [0, 255] for type `uint8` or [0, 1] for type `float`.

    Expand source code

        def add_video(self, name, value, iteration, fps=10):
            iteration = int(iteration / self.modulo) * self.modulo
            if (name, iteration) in self.written_values:
                return
            else:
                self.written_values[(name, iteration)] = True

            self._to_pickle(name, value.numpy(), iteration)
            if self.save_tensorboard:
                SummaryWriter.add_video(self, name, value, iteration, fps=fps)

  `def close(self)`
    Expand source code

        def close(self):
            if len(self.to_pickle) > 0:
                if self.use_zip:
                    f = bz2.BZ2File(self.picklename, "ab")
                    pickle.dump(self.to_pickle, f)
                    f.close()
                else:
                    f = open(self.picklename, "ab")
                    pickle.dump(self.to_pickle, f)
                    f.close()
                self.to_pickle = []

            SummaryWriter.close(self)

            f = open(self.log_dir + "/done", "wt")
            f.write("Done\n")
            f.close()

  `def debug(self, msg, from_name='')`
    Expand source code

        def debug(self, msg, from_name=""):
            print("[DEBUG] [", from_name, "]: ", msg)

  `def get_logger(self, prefix)`
    Expand source code

        def get_logger(self, prefix):
            return TFPrefixLogger(prefix, self)

  `def message(self, msg, from_name='')`
    Expand source code

        def message(self, msg, from_name=""):
            print("[", from_name, "]: ", msg)

  `def save_hps(self, hps, verbose=True)`
    Expand source code

        def save_hps(self, hps, verbose=True):
            hps = self._to_dict(hps)
            if verbose:
                print(hps)
            f = open(self.log_dir + "/params.json", "wt")
            f.write(str(hps) + "\n")
            f.close()

            outfile = open(self.log_dir + "/params.pickle", "wb")
            pickle.dump(hps, outfile)
            outfile.close()
            self.add_text("Hyperparameters", str(hps))

`class TFPrefixLogger (prefix, logger)`
  Expand source code

      class TFPrefixLogger:
          def __init__(self, prefix, logger):
              self.logger = logger
              self.prefix = prefix

          def add_images(self, name, value, iteration):
              self.logger.add_images(self.prefix + name, value, iteration)

          def add_figure(self, name, value, iteration):
              self.logger.add_figure(self.prefix + name, value, iteration)

          def add_scalar(self, name, value, iteration):
              self.logger.add_scalar(self.prefix + name, value, iteration)

          def add_video(self, name, value, iteration, fps=10):
              self.logger.add_video(self.prefix + name, value, iteration, fps)

          def message(self, msg, from_name=""):
              self.logger.message(msg, from_name=self.prefix + from_name)

          def debug(self, msg, from_name=""):
              self.logger.debug(msg, from_name=self.prefix + from_name)

          def get_logger(self, prefix):
              return TFPrefixLogger(self.prefix + prefix, self.logger)

          def close(self):
              pass

  ### Methods

  `def add_figure(self, name, value, iteration)`
    Expand source code

        def add_figure(self, name, value, iteration):
            self.logger.add_figure(self.prefix + name, value, iteration)

  `def add_images(self, name, value, iteration)`
    Expand source code

        def add_images(self, name, value, iteration):
            self.logger.add_images(self.prefix + name, value, iteration)

  `def add_scalar(self, name, value, iteration)`
    Expand source code

        def add_scalar(self, name, value, iteration):
            self.logger.add_scalar(self.prefix + name, value, iteration)

  `def add_video(self, name, value, iteration, fps=10)`
    Expand source code

        def add_video(self, name, value, iteration, fps=10):
            self.logger.add_video(self.prefix + name, value, iteration, fps)

  `def close(self)`
    Expand source code

        def close(self):
            pass

  `def debug(self, msg, from_name='')`
    Expand source code

        def debug(self, msg, from_name=""):
            self.logger.debug(msg, from_name=self.prefix + from_name)

  `def get_logger(self, prefix)`
    Expand source code

        def get_logger(self, prefix):
            return TFPrefixLogger(self.prefix + prefix, self.logger)

  `def message(self, msg, from_name='')`
    Expand source code

        def message(self, msg, from_name=""):
            self.logger.message(msg, from_name=self.prefix + from_name)