import json from pathlib import Path from datetime import datetime from itertools import repeat from collections import OrderedDict import numpy as np def ensure_dir(dirname): dirname = Path(dirname) if not dirname.is_dir(): dirname.mkdir(parents=True, exist_ok=False) def read_json(fname): with fname.open('rt') as handle: return json.load(handle, object_hook=OrderedDict) def write_json(content, fname): with fname.open('wt') as handle: json.dump(content, handle, indent=4, sort_keys=False) def inf_loop(data_loader): ''' wrapper function for endless data loader. ''' for loader in repeat(data_loader): yield from loader class Timer: def __init__(self): self.cache = datetime.now() def check(self): now = datetime.now() duration = now - self.cache self.cache = now return duration.total_seconds() def reset(self): self.cache = datetime.now() def sigmoid_rampup(current, rampup_length): """Exponential rampup from 2""" if rampup_length == 0: return 1.0 else: current = np.clip(current, 0.0, rampup_length) phase = 1.0 - current / rampup_length return float(np.exp(-5.0 * phase * phase)) def sigmoid_rampdown(current, rampdown_length): """Exponential rampdown""" if rampdown_length == 0: return 1.0 else: current = np.clip(current, 0.0, rampdown_length) phase = 1.0 - (rampdown_length - current) / rampdown_length return float(np.exp(-12.5 * phase * phase)) def linear_rampup(current, rampup_length): """Linear rampup""" assert current >= 0 and rampup_length >= 0 if current >= rampup_length: return 1.0 else: return current / rampup_length def linear_rampdown(current, rampdown_length): """Linear rampup""" assert current >= 0 and rampdown_length >= 0 if current >= rampdown_length: return 1.0 else: return 1.0 - current / rampdown_length def cosine_rampdown(current, rampdown_length): """Cosine rampdown from https://arxiv.org/abs/1608.03983""" current = np.clip(current, 0.0, rampdown_length) return float(.5 * (np.cos(np.pi * current / rampdown_length) + 1)) def cosine_rampup(current, rampup_length): """Cosine rampup""" current = np.clip(current, 0.0, rampup_length) return float(-.5 * (np.cos(np.pi * current / rampup_length) - 1))