diff --git a/doc/source/tune-usage.rst b/doc/source/tune-usage.rst index 64990c2639e0..e1b163abef06 100644 --- a/doc/source/tune-usage.rst +++ b/doc/source/tune-usage.rst @@ -618,21 +618,6 @@ You can pass in your own logging mechanisms to output logs in custom formats as These loggers will be called along with the default Tune loggers. All loggers must inherit the `Logger interface `__. Tune enables default loggers for Tensorboard, CSV, and JSON formats. You can also check out `logger.py `__ for implementation details. An example can be found in `logging_example.py `__. -TBXLogger (TensorboardX) -~~~~~~~~~~~~~~~~~~~~~~~~ - -Tune provides a logger using `TensorBoardX `_. You can install tensorboardX via ``pip install tensorboardX`` or ``pip install 'ray[tune]'``. This logger automatically outputs loggers similar to using a default TensorFlow logging format. By default, it will log any scalar value provided via the result dictionary along with HParams information. - -.. code-block:: python - - from ray.tune.logger import TBXLogger - - tune.run( - MyTrainableClass, - name="experiment_name", - loggers=[TBXLogger] - ) - MLFlow ~~~~~~ diff --git a/python/ray/tune/logger.py b/python/ray/tune/logger.py index 176dc467bc4f..f41b133bb8e8 100644 --- a/python/ray/tune/logger.py +++ b/python/ray/tune/logger.py @@ -3,7 +3,6 @@ import logging import os import yaml -import distutils.version import numbers import numpy as np @@ -132,155 +131,6 @@ def update_config(self, config): cloudpickle.dump(self.config, f) -def tf2_compat_logger(config, logdir, trial=None): - """Chooses TensorBoard logger depending on imported TF version.""" - global tf - if "RLLIB_TEST_NO_TF_IMPORT" in os.environ: - logger.warning("Not importing TensorFlow for test purposes") - tf = None - raise RuntimeError("Not importing TensorFlow for test purposes") - else: - import tensorflow as tf - use_tf2_api = (distutils.version.LooseVersion(tf.__version__) >= - distutils.version.LooseVersion("1.15.0")) - if use_tf2_api: - # This is temporarily for RLlib because it disables v2 behavior... - from tensorflow.python import tf2 - if not tf2.enabled(): - tf = tf.compat.v1 - return TFLogger(config, logdir, trial) - tf = tf.compat.v2 # setting this for TF2.0 - return TF2Logger(config, logdir, trial) - else: - return TFLogger(config, logdir, trial) - - -class TF2Logger(Logger): - """TensorBoard Logger for TF version >= 2.0.0. - - Automatically flattens nested dicts to show on TensorBoard: - - {"a": {"b": 1, "c": 2}} -> {"a/b": 1, "a/c": 2} - - If you need to do more advanced logging, it is recommended - to use a Summary Writer in the Trainable yourself. - """ - - def _init(self): - global tf - if tf is None: - import tensorflow as tf - tf = tf.compat.v2 # setting this for TF2.0 - self._file_writer = None - self._hp_logged = False - - def on_result(self, result): - if self._file_writer is None: - from tensorflow.python.eager import context - from tensorboard.plugins.hparams import api as hp - self._context = context - self._file_writer = tf.summary.create_file_writer(self.logdir) - with tf.device("/CPU:0"): - with tf.summary.record_if(True), self._file_writer.as_default(): - step = result.get( - TIMESTEPS_TOTAL) or result[TRAINING_ITERATION] - - tmp = result.copy() - if not self._hp_logged: - if self.trial and self.trial.evaluated_params: - try: - hp.hparams( - self.trial.evaluated_params, - trial_id=self.trial.trial_id) - except Exception as exc: - logger.error("HParams failed with %s", exc) - self._hp_logged = True - - for k in [ - "config", "pid", "timestamp", TIME_TOTAL_S, - TRAINING_ITERATION - ]: - if k in tmp: - del tmp[k] # not useful to log these - - flat_result = flatten_dict(tmp, delimiter="/") - path = ["ray", "tune"] - for attr, value in flat_result.items(): - if type(value) in VALID_SUMMARY_TYPES: - tf.summary.scalar( - "/".join(path + [attr]), value, step=step) - self._file_writer.flush() - - def flush(self): - if self._file_writer is not None: - self._file_writer.flush() - - def close(self): - if self._file_writer is not None: - self._file_writer.close() - - -def to_tf_values(result, path): - from tensorboardX.summary import make_histogram - flat_result = flatten_dict(result, delimiter="/") - values = [] - for attr, value in flat_result.items(): - if type(value) in VALID_SUMMARY_TYPES: - values.append( - tf.Summary.Value( - tag="/".join(path + [attr]), simple_value=value)) - elif type(value) is list and len(value) > 0: - values.append( - tf.Summary.Value( - tag="/".join(path + [attr]), - histo=make_histogram(values=np.array(value), bins=10))) - return values - - -class TFLogger(Logger): - """TensorBoard Logger for TF version < 2.0.0. - - Automatically flattens nested dicts to show on TensorBoard: - - {"a": {"b": 1, "c": 2}} -> {"a/b": 1, "a/c": 2} - - If you need to do more advanced logging, it is recommended - to use a Summary Writer in the Trainable yourself. - """ - - def _init(self): - global tf - if tf is None: - import tensorflow as tf - tf = tf.compat.v1 # setting this for regular TF logger - logger.debug("Initializing TFLogger instead of TF2Logger.") - self._file_writer = tf.summary.FileWriter(self.logdir) - - def on_result(self, result): - tmp = result.copy() - for k in [ - "config", "pid", "timestamp", TIME_TOTAL_S, TRAINING_ITERATION - ]: - if k in tmp: - del tmp[k] # not useful to tf log these - values = to_tf_values(tmp, ["ray", "tune"]) - train_stats = tf.Summary(value=values) - t = result.get(TIMESTEPS_TOTAL) or result[TRAINING_ITERATION] - self._file_writer.add_summary(train_stats, t) - iteration_value = to_tf_values({ - TRAINING_ITERATION: result[TRAINING_ITERATION] - }, ["ray", "tune"]) - iteration_stats = tf.Summary(value=iteration_value) - self._file_writer.add_summary(iteration_stats, t) - self._file_writer.flush() - - def flush(self): - self._file_writer.flush() - - def close(self): - self._file_writer.close() - - class CSVLogger(Logger): """Logs results to progress.csv under the trial directory. diff --git a/python/ray/tune/tests/test_logger.py b/python/ray/tune/tests/test_logger.py index ed9a0b3a75fd..28b2b699060e 100644 --- a/python/ray/tune/tests/test_logger.py +++ b/python/ray/tune/tests/test_logger.py @@ -3,7 +3,7 @@ import tempfile import shutil -from ray.tune.logger import tf2_compat_logger, JsonLogger, CSVLogger, TBXLogger +from ray.tune.logger import JsonLogger, CSVLogger, TBXLogger Trial = namedtuple("MockTrial", ["evaluated_params", "trial_id"]) @@ -25,15 +25,6 @@ def setUp(self): def tearDown(self): shutil.rmtree(self.test_dir, ignore_errors=True) - def testTensorBoardLogger(self): - config = {"a": 2, "b": 5} - t = Trial(evaluated_params=config, trial_id=5342) - logger = tf2_compat_logger( - config=config, logdir=self.test_dir, trial=t) - logger.on_result(result(2, 4)) - logger.on_result(result(2, 4)) - logger.close() - def testCSV(self): config = {"a": 2, "b": 5} t = Trial(evaluated_params=config, trial_id="csv")