mirror of
https://github.com/wassname/ray.git
synced 2026-07-07 00:36:34 +08:00
f861124b9a
Improve the Evolutionary Strategies example.
224 lines
5.6 KiB
Python
224 lines
5.6 KiB
Python
# Code in this file is copied and adapted from
|
|
# https://github.com/openai/evolution-strategies-starter.
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
from collections import OrderedDict
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
import tensorflow as tf
|
|
from tensorflow.core.util import event_pb2
|
|
from tensorflow.python import pywrap_tensorflow
|
|
from tensorflow.python.util import compat
|
|
|
|
DEBUG = 10
|
|
INFO = 20
|
|
WARN = 30
|
|
ERROR = 40
|
|
|
|
DISABLED = 50
|
|
|
|
|
|
class TbWriter(object):
|
|
"""Based on SummaryWriter, but changed to allow for a different prefix."""
|
|
def __init__(self, dir, prefix):
|
|
self.dir = dir
|
|
# Start at 1, because EvWriter automatically generates an object with
|
|
# step = 0.
|
|
self.step = 1
|
|
self.evwriter = pywrap_tensorflow.EventsWriter(
|
|
compat.as_bytes(os.path.join(dir, prefix)))
|
|
|
|
def write_values(self, key2val):
|
|
summary = tf.Summary(value=[tf.Summary.Value(tag=k, simple_value=float(v))
|
|
for (k, v) in key2val.items()])
|
|
event = event_pb2.Event(wall_time=time.time(), summary=summary)
|
|
event.step = self.step
|
|
self.evwriter.WriteEvent(event)
|
|
self.evwriter.Flush()
|
|
self.step += 1
|
|
|
|
def close(self):
|
|
self.evwriter.Close()
|
|
|
|
# API
|
|
|
|
|
|
def start(dir):
|
|
if _Logger.CURRENT is not _Logger.DEFAULT:
|
|
sys.stderr.write("WARNING: You asked to start logging (dir=%s), but you "
|
|
"never stopped the previous logger (dir=%s)."
|
|
"\n" % (dir, _Logger.CURRENT.dir))
|
|
_Logger.CURRENT = _Logger(dir=dir)
|
|
|
|
|
|
def stop():
|
|
if _Logger.CURRENT is _Logger.DEFAULT:
|
|
sys.stderr.write("WARNING: You asked to stop logging, but you never "
|
|
"started any previous logger."
|
|
"\n" % (dir, _Logger.CURRENT.dir))
|
|
return
|
|
_Logger.CURRENT.close()
|
|
_Logger.CURRENT = _Logger.DEFAULT
|
|
|
|
|
|
def record_tabular(key, val):
|
|
"""Log a value of some diagnostic.
|
|
|
|
Call this once for each diagnostic quantity, each iteration.
|
|
"""
|
|
_Logger.CURRENT.record_tabular(key, val)
|
|
|
|
|
|
def dump_tabular():
|
|
"""Write all of the diagnostics from the current iteration."""
|
|
_Logger.CURRENT.dump_tabular()
|
|
|
|
|
|
def log(*args, **kwargs):
|
|
"""Write the sequence of args, with no separators.
|
|
|
|
This is written to the console and output files (if you've configured an
|
|
output file).
|
|
"""
|
|
level = kwargs['level'] if 'level' in kwargs else INFO
|
|
_Logger.CURRENT.log(*args, level=level)
|
|
|
|
|
|
def debug(*args):
|
|
log(*args, level=DEBUG)
|
|
|
|
|
|
def info(*args):
|
|
log(*args, level=INFO)
|
|
|
|
|
|
def warn(*args):
|
|
log(*args, level=WARN)
|
|
|
|
|
|
def error(*args):
|
|
log(*args, level=ERROR)
|
|
|
|
|
|
def set_level(level):
|
|
"""
|
|
Set logging threshold on current logger.
|
|
"""
|
|
_Logger.CURRENT.set_level(level)
|
|
|
|
|
|
def get_dir():
|
|
"""
|
|
Get directory that log files are being written to.
|
|
will be None if there is no output directory (i.e., if you didn't call start)
|
|
"""
|
|
return _Logger.CURRENT.get_dir()
|
|
|
|
|
|
def get_expt_dir():
|
|
sys.stderr.write("get_expt_dir() is Deprecated. Switch to get_dir()\n")
|
|
return get_dir()
|
|
|
|
# Backend
|
|
|
|
|
|
class _Logger(object):
|
|
# A logger with no output files. (See right below class definition) so that
|
|
# you can still log to the terminal without setting up any output files.
|
|
DEFAULT = None
|
|
# Current logger being used by the free functions above.
|
|
CURRENT = None
|
|
|
|
def __init__(self, dir=None):
|
|
self.name2val = OrderedDict() # Values this iteration.
|
|
self.level = INFO
|
|
self.dir = dir
|
|
self.text_outputs = [sys.stdout]
|
|
if dir is not None:
|
|
os.makedirs(dir, exist_ok=True)
|
|
self.text_outputs.append(open(os.path.join(dir, "log.txt"), "w"))
|
|
self.tbwriter = TbWriter(dir=dir, prefix="events")
|
|
else:
|
|
self.tbwriter = None
|
|
|
|
# Logging API, forwarded
|
|
|
|
def record_tabular(self, key, val):
|
|
self.name2val[key] = val
|
|
|
|
def dump_tabular(self):
|
|
# Create strings for printing.
|
|
key2str = OrderedDict()
|
|
for (key, val) in self.name2val.items():
|
|
if hasattr(val, "__float__"):
|
|
valstr = "%-8.3g" % val
|
|
else:
|
|
valstr = val
|
|
key2str[self._truncate(key)] = self._truncate(valstr)
|
|
keywidth = max(map(len, key2str.keys()))
|
|
valwidth = max(map(len, key2str.values()))
|
|
# Write to all text outputs
|
|
self._write_text("-" * (keywidth + valwidth + 7), "\n")
|
|
for (key, val) in key2str.items():
|
|
self._write_text("| ", key, " " * (keywidth - len(key)), " | ", val,
|
|
" " * (valwidth - len(val)), " |\n")
|
|
self._write_text("-" * (keywidth + valwidth + 7), "\n")
|
|
for f in self.text_outputs:
|
|
try:
|
|
f.flush()
|
|
except OSError:
|
|
sys.stderr.write('Warning! OSError when flushing.\n')
|
|
# Write to tensorboard
|
|
if self.tbwriter is not None:
|
|
self.tbwriter.write_values(self.name2val)
|
|
self.name2val.clear()
|
|
|
|
def log(self, *args, **kwargs):
|
|
level = kwargs['level'] if 'level' in kwargs else INFO
|
|
if self.level <= level:
|
|
self._do_log(*args)
|
|
|
|
# Configuration
|
|
|
|
def set_level(self, level):
|
|
self.level = level
|
|
|
|
def get_dir(self):
|
|
return self.dir
|
|
|
|
def close(self):
|
|
for f in self.text_outputs[1:]:
|
|
f.close()
|
|
if self.tbwriter:
|
|
self.tbwriter.close()
|
|
|
|
# Misc
|
|
|
|
def _do_log(self, *args):
|
|
self._write_text(*args + ('\n',))
|
|
for f in self.text_outputs:
|
|
try:
|
|
f.flush()
|
|
except OSError:
|
|
print('Warning! OSError when flushing.')
|
|
|
|
def _write_text(self, *strings):
|
|
for f in self.text_outputs:
|
|
for string in strings:
|
|
f.write(string)
|
|
|
|
def _truncate(self, s):
|
|
if len(s) > 33:
|
|
return s[:30] + "..."
|
|
else:
|
|
return s
|
|
|
|
|
|
_Logger.DEFAULT = _Logger()
|
|
_Logger.CURRENT = _Logger.DEFAULT
|