aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <gardener@tensorflow.org>2018-07-27 00:43:16 -0700
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2018-07-27 00:46:18 -0700
commit4af0e25bfe0791f0ec3e9262c8d5051415bf026e (patch)
tree1d6b6f96f25de32baab0b56b763542747b92c689
parent21fbc78e69b3e79f883161601f1ccc62be42a06e (diff)
Automated rollback of commit d4cb01f242dc3ff0f7b0aae7284def46281755f2
PiperOrigin-RevId: 206281287
-rw-r--r--tensorflow/python/keras/callbacks.py73
-rw-r--r--tensorflow/python/keras/callbacks_test.py59
2 files changed, 28 insertions, 104 deletions
diff --git a/tensorflow/python/keras/callbacks.py b/tensorflow/python/keras/callbacks.py
index 070d41147d..d1b9dc27bd 100644
--- a/tensorflow/python/keras/callbacks.py
+++ b/tensorflow/python/keras/callbacks.py
@@ -31,14 +31,12 @@ import time
import numpy as np
import six
-from tensorflow.python.eager import context
from tensorflow.python.framework import dtypes
from tensorflow.python.keras import backend as K
from tensorflow.python.keras.engine.training_utils import standardize_input_data
from tensorflow.python.keras.utils.generic_utils import Progbar
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import state_ops
-from tensorflow.python.ops import summary_ops_v2
from tensorflow.python.ops import variables
from tensorflow.python.platform import tf_logging as logging
from tensorflow.python.summary import summary as tf_summary
@@ -718,15 +716,6 @@ class TensorBoard(Callback):
`embeddings_layer_names`. Numpy array (if the model has a single
input) or list of Numpy arrays (if the model has multiple inputs).
Learn [more about embeddings](https://www.tensorflow.org/programmers_guide/embedding)
-
- Raises:
- ValueError: If histogram_freq is set and no validation data is provided.
-
- @compatbility(eager)
- Using `Tensorboard` callback will work while eager execution is enabled,
- however outputting histogram summaries of weights and gradients is not
- supported, and thus `histogram_freq` will be ignored.
- @end_compatibility
"""
# pylint: enable=line-too-long
@@ -745,11 +734,6 @@ class TensorBoard(Callback):
super(TensorBoard, self).__init__()
self.log_dir = log_dir
self.histogram_freq = histogram_freq
- if self.histogram_freq and context.executing_eagerly():
- logging.warning(
- UserWarning('Weight and gradient histograms not supported for eager'
- 'execution, setting `histogram_freq` to `0`.'))
- self.histogram_freq = 0
self.merged = None
self.write_graph = write_graph
self.write_grads = write_grads
@@ -757,22 +741,18 @@ class TensorBoard(Callback):
self.batch_size = batch_size
self._current_batch = 0
self._total_batches_seen = 0
+ # abstracted writer class to be able to stub for testing
+ self._writer_class = tf_summary.FileWriter
self.embeddings_freq = embeddings_freq
self.embeddings_layer_names = embeddings_layer_names
self.embeddings_metadata = embeddings_metadata
self.embeddings_data = embeddings_data
- def _init_writer(self):
- """Sets file writer."""
- if context.executing_eagerly():
- self.writer = summary_ops_v2.create_file_writer(self.log_dir)
- elif self.write_graph:
- self.writer = tf_summary.FileWriter(self.log_dir, K.get_session().graph)
- else:
- self.writer = tf_summary.FileWriter(self.log_dir)
+ def set_model(self, model):
+ """Sets Keras model and creates summary ops."""
- def _make_histogram_ops(self, model):
- """Defines histogram ops when histogram_freq > 0."""
+ self.model = model
+ self.sess = K.get_session()
# only make histogram summary op if it hasn't already been made
if self.histogram_freq and self.merged is None:
for layer in self.model.layers:
@@ -813,10 +793,8 @@ class TensorBoard(Callback):
def is_indexed_slices(grad):
return type(grad).__name__ == 'IndexedSlices'
- grads = [
- grad.values if is_indexed_slices(grad) else grad
- for grad in grads
- ]
+ grads = [grad.values if is_indexed_slices(grad) else grad
+ for grad in grads]
tf_summary.histogram('{}_grad'.format(mapped_weight_name), grads)
if hasattr(layer, 'output'):
@@ -825,16 +803,12 @@ class TensorBoard(Callback):
tf_summary.histogram('{}_out_{}'.format(layer.name, i), output)
else:
tf_summary.histogram('{}_out'.format(layer.name), layer.output)
+ self.merged = tf_summary.merge_all()
- def set_model(self, model):
- """Sets Keras model and creates summary ops."""
-
- self.model = model
- self._init_writer()
- # histogram summaries only enabled in graph mode
- if not context.executing_eagerly():
- self._make_histogram_ops(model)
- self.merged = tf_summary.merge_all()
+ if self.write_graph:
+ self.writer = self._writer_class(self.log_dir, self.sess.graph)
+ else:
+ self.writer = self._writer_class(self.log_dir)
# If both embedding_freq and embeddings_data are available, we will
# visualize embeddings.
@@ -920,24 +894,17 @@ class TensorBoard(Callback):
"""
logs = logs or {}
- if context.executing_eagerly():
- # use v2 summary ops
- with self.writer.as_default(), summary_ops_v2.always_record_summaries():
- for name, value in logs.items():
- summary_ops_v2.scalar(name, value.item(), step=step)
- else:
- # use FileWriter from v1 summary
- for name, value in logs.items():
- summary = tf_summary.Summary()
- summary_value = summary.value.add()
- summary_value.simple_value = value.item()
- summary_value.tag = name
- self.writer.add_summary(summary, step)
+ for name, value in logs.items():
+ summary = tf_summary.Summary()
+ summary_value = summary.value.add()
+ summary_value.simple_value = value.item()
+ summary_value.tag = name
+ self.writer.add_summary(summary, step)
self.writer.flush()
def on_train_begin(self, logs=None):
"""Checks if histogram summaries can be run."""
- # will never be set when in eager
+
if self.histogram_freq:
if 'validation_steps' in self.params:
self._validation_batches = self.params['validation_steps']
diff --git a/tensorflow/python/keras/callbacks_test.py b/tensorflow/python/keras/callbacks_test.py
index 6d61e9bcee..7d830078ce 100644
--- a/tensorflow/python/keras/callbacks_test.py
+++ b/tensorflow/python/keras/callbacks_test.py
@@ -29,12 +29,10 @@ import numpy as np
from tensorflow.core.framework import summary_pb2
from tensorflow.python import keras
-from tensorflow.python.framework import test_util
from tensorflow.python.keras import testing_utils
from tensorflow.python.platform import test
from tensorflow.python.platform import tf_logging as logging
from tensorflow.python.summary.writer import writer_cache
-from tensorflow.python.training import adam
try:
import h5py # pylint:disable=g-import-not-at-top
@@ -919,9 +917,6 @@ class KerasCallbacksTest(test.TestCase):
def close(self):
pass
- def _init_writer(obj):
- obj.writer = FileWriterStub(obj.log_dir)
-
np.random.seed(1337)
tmpdir = self.get_temp_dir()
self.addCleanup(shutil.rmtree, tmpdir)
@@ -945,13 +940,13 @@ class KerasCallbacksTest(test.TestCase):
loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
- keras.callbacks.TensorBoard._init_writer = _init_writer
tsb = keras.callbacks.TensorBoard(
log_dir=tmpdir,
histogram_freq=1,
write_images=True,
write_grads=True,
batch_size=5)
+ tsb._writer_class = FileWriterStub
cbks = [tsb]
# fit with validation data
@@ -1123,11 +1118,11 @@ class KerasCallbacksTest(test.TestCase):
def close(self):
pass
- temp_dir = self.get_temp_dir()
- self.addCleanup(shutil.rmtree, temp_dir)
+ logdir = 'fake_dir'
- tb_cbk = keras.callbacks.TensorBoard(temp_dir)
- tb_cbk.writer = FileWriterStub(temp_dir)
+ # log every batch
+ tb_cbk = keras.callbacks.TensorBoard(logdir)
+ tb_cbk.writer = FileWriterStub(logdir)
for batch in range(5):
tb_cbk.on_batch_end(batch, {'acc': np.float32(batch)})
@@ -1155,11 +1150,10 @@ class KerasCallbacksTest(test.TestCase):
def close(self):
pass
- temp_dir = self.get_temp_dir()
- self.addCleanup(shutil.rmtree, temp_dir)
+ logdir = 'fake_dir'
- tb_cbk = keras.callbacks.TensorBoard(temp_dir)
- tb_cbk.writer = FileWriterStub(temp_dir)
+ tb_cbk = keras.callbacks.TensorBoard(logdir)
+ tb_cbk.writer = FileWriterStub(logdir)
tb_cbk.on_batch_end(0, {'acc': np.float32(5.0)})
tb_cbk.on_epoch_end(0, {'acc': np.float32(10.0)})
@@ -1170,43 +1164,6 @@ class KerasCallbacksTest(test.TestCase):
self.assertEqual(epoch_step, 0)
self.assertEqual(epoch_summary.value[0].simple_value, 10.0)
- @test_util.run_in_graph_and_eager_modes
- def test_Tensorboard_eager(self):
- with self.test_session():
- temp_dir = self.get_temp_dir()
- self.addCleanup(shutil.rmtree, temp_dir)
-
- (x_train, y_train), (x_test, y_test) = testing_utils.get_test_data(
- train_samples=TRAIN_SAMPLES,
- test_samples=TEST_SAMPLES,
- input_shape=(INPUT_DIM,),
- num_classes=NUM_CLASSES)
- y_test = keras.utils.to_categorical(y_test)
- y_train = keras.utils.to_categorical(y_train)
-
- model = keras.models.Sequential()
- model.add(
- keras.layers.Dense(
- NUM_HIDDEN, input_dim=INPUT_DIM, activation='relu'))
- model.add(keras.layers.Dense(NUM_CLASSES, activation='softmax'))
- model.compile(
- loss='binary_crossentropy',
- optimizer=adam.AdamOptimizer(0.01),
- metrics=['accuracy'])
-
- cbks = [keras.callbacks.TensorBoard(log_dir=temp_dir)]
-
- model.fit(
- x_train,
- y_train,
- batch_size=BATCH_SIZE,
- validation_data=(x_test, y_test),
- callbacks=cbks,
- epochs=2,
- verbose=0)
-
- self.assertTrue(os.path.exists(temp_dir))
-
def test_RemoteMonitorWithJsonPayload(self):
if requests is None:
self.skipTest('`requests` required to run this test')