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
. Iflog_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)
. Ifdataformats
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
orint
- 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 typeuint8
or [0, 1] for typefloat
.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)