aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tensorflow/python/keras/_impl/keras/callbacks.py2
-rw-r--r--tensorflow/python/keras/_impl/keras/utils/generic_utils.py112
-rw-r--r--tensorflow/tools/api/golden/tensorflow.keras.utils.-progbar.pbtxt4
3 files changed, 66 insertions, 52 deletions
diff --git a/tensorflow/python/keras/_impl/keras/callbacks.py b/tensorflow/python/keras/_impl/keras/callbacks.py
index b29bc39232..de013c7c3f 100644
--- a/tensorflow/python/keras/_impl/keras/callbacks.py
+++ b/tensorflow/python/keras/_impl/keras/callbacks.py
@@ -328,7 +328,7 @@ class ProgbarLogger(Callback):
if k in logs:
self.log_values.append((k, logs[k]))
if self.verbose:
- self.progbar.update(self.seen, self.log_values, force=True)
+ self.progbar.update(self.seen, self.log_values)
@tf_export('keras.callbacks.History')
diff --git a/tensorflow/python/keras/_impl/keras/utils/generic_utils.py b/tensorflow/python/keras/_impl/keras/utils/generic_utils.py
index fa3b55c59e..462d600bf8 100644
--- a/tensorflow/python/keras/_impl/keras/utils/generic_utils.py
+++ b/tensorflow/python/keras/_impl/keras/utils/generic_utils.py
@@ -291,55 +291,73 @@ class Progbar(object):
Arguments:
target: Total number of steps expected, None if unknown.
+ width: Progress bar width on screen.
+ verbose: Verbosity mode, 0 (silent), 1 (verbose), 2 (semi-verbose)
+ stateful_metrics: Iterable of string names of metrics that
+ should *not* be averaged over time. Metrics in this list
+ will be displayed as-is. All others will be averaged
+ by the progbar before display.
interval: Minimum visual progress update interval (in seconds).
"""
- def __init__(self, target, width=30, verbose=1, interval=0.05):
- self.width = width
- if target is None:
- target = -1
+ def __init__(self, target, width=30, verbose=1, interval=0.05,
+ stateful_metrics=None):
self.target = target
- self.sum_values = {}
- self.unique_values = []
- self.start = time.time()
- self.last_update = 0
- self.interval = interval
- self.total_width = 0
- self.seen_so_far = 0
+ self.width = width
self.verbose = verbose
+ self.interval = interval
+ if stateful_metrics:
+ self.stateful_metrics = set(stateful_metrics)
+ else:
+ self.stateful_metrics = set()
+
self._dynamic_display = ((hasattr(sys.stdout, 'isatty') and
sys.stdout.isatty()) or
- 'ipykernel' in sys.modules)
-
- def update(self, current, values=None, force=False):
+ 'ipykernel' in sys.modules or
+ 'posix' in sys.modules)
+ self._total_width = 0
+ self._seen_so_far = 0
+ # We use a dict + list to avoid garbage collection
+ # issues found in OrderedDict
+ self._values = {}
+ self._values_order = []
+ self._start = time.time()
+ self._last_update = 0
+
+ def update(self, current, values=None):
"""Updates the progress bar.
Arguments:
current: Index of current step.
- values: List of tuples (name, value_for_last_step).
- The progress bar will display averages for these values.
- force: Whether to force visual progress update.
+ values: List of tuples:
+ `(name, value_for_last_step)`.
+ If `name` is in `stateful_metrics`,
+ `value_for_last_step` will be displayed as-is.
+ Else, an average of the metric over time will be displayed.
"""
values = values or []
for k, v in values:
- if k not in self.sum_values:
- self.sum_values[k] = [
- v * (current - self.seen_so_far), current - self.seen_so_far
- ]
- self.unique_values.append(k)
+ if k not in self._values_order:
+ self._values_order.append(k)
+ if k not in self.stateful_metrics:
+ if k not in self._values:
+ self._values[k] = [v * (current - self._seen_so_far),
+ current - self._seen_so_far]
+ else:
+ self._values[k][0] += v * (current - self._seen_so_far)
+ self._values[k][1] += (current - self._seen_so_far)
else:
- self.sum_values[k][0] += v * (current - self.seen_so_far)
- self.sum_values[k][1] += (current - self.seen_so_far)
- self.seen_so_far = current
+ self._values[k] = v
+ self._seen_so_far = current
now = time.time()
- info = ' - %.0fs' % (now - self.start)
+ info = ' - %.0fs' % (now - self._start)
if self.verbose == 1:
- if (not force and (now - self.last_update) < self.interval and
- current < self.target):
+ if (now - self._last_update < self.interval and
+ self.target is not None and current < self.target):
return
- prev_total_width = self.total_width
+ prev_total_width = self._total_width
if self._dynamic_display:
sys.stdout.write('\b' * prev_total_width)
sys.stdout.write('\r')
@@ -360,22 +378,21 @@ class Progbar(object):
bar += '='
bar += ('.' * (self.width - prog_width))
bar += ']'
- sys.stdout.write(bar)
- self.total_width = len(bar)
else:
bar = '%7d/Unknown' % current
- self.total_width = len(bar)
+ self._total_width = len(bar)
sys.stdout.write(bar)
if current:
- time_per_unit = (now - self.start) / current
+ time_per_unit = (now - self._start) / current
else:
time_per_unit = 0
if self.target is not None and current < self.target:
eta = time_per_unit * (self.target - current)
if eta > 3600:
- eta_format = '%d:%02d:%02d' % (eta // 3600, (eta % 3600) // 60,
+ eta_format = '%d:%02d:%02d' % (eta // 3600,
+ (eta % 3600) // 60,
eta % 60)
elif eta > 60:
eta_format = '%d:%02d' % (eta // 60, eta % 60)
@@ -391,35 +408,32 @@ class Progbar(object):
else:
info += ' %.0fus/step' % (time_per_unit * 1e6)
- for k in self.unique_values:
+ for k in self._values_order:
info += ' - %s:' % k
- if isinstance(self.sum_values[k], list):
- avg = np.mean(self.sum_values[k][0] / max(1, self.sum_values[k][1]))
+ if isinstance(self._values[k], list):
+ avg = np.mean(self._values[k][0] / max(1, self._values[k][1]))
if abs(avg) > 1e-3:
info += ' %.4f' % avg
else:
info += ' %.4e' % avg
else:
- info += ' %s' % self.sum_values[k]
+ info += ' %s' % self._values[k]
+
+ self._total_width += len(info)
+ if prev_total_width > self._total_width:
+ info += (' ' * (prev_total_width - self._total_width))
- self.total_width += len(info)
- if prev_total_width > self.total_width:
- info += (' ' * (prev_total_width - self.total_width))
if self.target is not None and current >= self.target:
info += '\n'
sys.stdout.write(info)
sys.stdout.flush()
- if current >= self.target:
- sys.stdout.write('\n')
-
elif self.verbose == 2:
if self.target is None or current >= self.target:
- for k in self.unique_values:
+ for k in self._values_order:
info += ' - %s:' % k
- avg = np.mean(
- self.sum_values[k][0] / max(1, self.sum_values[k][1]))
+ avg = np.mean(self._values[k][0] / max(1, self._values[k][1]))
if avg > 1e-3:
info += ' %.4f' % avg
else:
@@ -429,10 +443,10 @@ class Progbar(object):
sys.stdout.write(info)
sys.stdout.flush()
- self.last_update = now
+ self._last_update = now
def add(self, n, values=None):
- self.update(self.seen_so_far + n, values)
+ self.update(self._seen_so_far + n, values)
def make_batches(size, batch_size):
diff --git a/tensorflow/tools/api/golden/tensorflow.keras.utils.-progbar.pbtxt b/tensorflow/tools/api/golden/tensorflow.keras.utils.-progbar.pbtxt
index 3adc6b6faa..16e1cbe650 100644
--- a/tensorflow/tools/api/golden/tensorflow.keras.utils.-progbar.pbtxt
+++ b/tensorflow/tools/api/golden/tensorflow.keras.utils.-progbar.pbtxt
@@ -4,7 +4,7 @@ tf_class {
is_instance: "<type \'object\'>"
member_method {
name: "__init__"
- argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\'], "
+ argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\', \'stateful_metrics\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\', \'None\'], "
}
member_method {
name: "add"
@@ -12,6 +12,6 @@ tf_class {
}
member_method {
name: "update"
- argspec: "args=[\'self\', \'current\', \'values\', \'force\'], varargs=None, keywords=None, defaults=[\'None\', \'False\'], "
+ argspec: "args=[\'self\', \'current\', \'values\'], varargs=None, keywords=None, defaults=[\'None\'], "
}
}