Skip to content

Instantly share code, notes, and snippets.

@henryzord
Last active June 28, 2019 10:12
Show Gist options
  • Save henryzord/010436b43b5889aced40db88666a832a to your computer and use it in GitHub Desktop.
Save henryzord/010436b43b5889aced40db88666a832a to your computer and use it in GitHub Desktop.
A snippet for demonstrating how to log metadata with tensorboard, even if you don't use deep learning models.
"""
Code for demonstrating how to log metadata with tensorflow and tensorboard.
To install required libraries, run the following command in conda, or the equivalent in pip:
conda install matplotlib==2.2.3 numpy==1.16.1 tensorflow==1.13.1 tensorboard==1.13.1 psutil==5.6.2
"""
import argparse
import os
import signal
import subprocess
import webbrowser
import numpy as np
import psutil
import tensorflow as tf
from datetime import datetime as dt
import time
# since viridis is created dynamically, this line will always throw an error when read in an IDE
from matplotlib.cm import viridis
class TfLogger(object):
def __init__(self, logdir_path, open_browser=False):
"""
:param logdir_path: Path in which run paths will be created.
Each run path has metadata regarding one run.
:param open_browser: Whether to open a new browser tab to monitor Tensorboard.
"""
now = dt.now()
if not os.path.isabs(logdir_path):
this_path = os.path.join(os.getcwd(), logdir_path, now.strftime('%d-%m-%Y-%H:%M:%S'))
else:
this_path = os.path.join(logdir_path, now.strftime('%d-%m-%Y-%H:%M:%S'))
os.mkdir(this_path)
self.this_path = this_path
# initializes summary writer
self.summary_writer = tf.summary.FileWriter(self.this_path)
# this doesn't need to be GPU intensive
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.1)
# initializes new tensorflow session
self.tf_session = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))
self.some_placeholder = tf.placeholder(tf.float32, shape=[None]) # type: tf.Tensor
self.some_histogram = tf.summary.histogram('fitness', self.some_placeholder) # type: tf.Tensor
self.summaries = tf.summary.merge_all()
if open_browser:
self.__tensorboard_start__()
def __tensorboard_start__(self):
"""
1. Checks if tensorboard is already running;
1.1 Kill the process, if so;
2. Re-starts tensorboard, now watching the path for the current run;
3. Opens a new browser tab for monitoring this run.
"""
pid = self.__find_process_pid_by_name__('tensorboard')
if pid is not None:
os.kill(pid, signal.SIGKILL)
p = subprocess.Popen(
["tensorboard", "--logdir", self.this_path, "--port", "default"],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT
)
time.sleep(1)
webbrowser.open_new_tab("http://localhost:6006")
@staticmethod
def __find_process_pid_by_name__(process_name):
"""
Returns PID of process if it is alive and running, otherwise returns None.
Adapted from https://thispointer.com/python-check-if-a-process-is-running-by-name-and-find-its-process-id-pid/
"""
# Iterate over the all the running process
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name'])
# Check if process name contains the given name string.
if process_name.lower() == pinfo['name'].lower():
return pinfo['pid']
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return None
def log_scalar(self, tag, value, step):
"""
Logs a scalar variable.
:param tag: The name of the scalar. Must be consistent throughout the live of the algorithm.
:type tag: str
:param value: Current value of the scalar.
:type value: np.float32
:param step: Current step being recorded.
:type step: int
"""
summary = tf.Summary(value=[tf.Summary.Value(tag=tag, simple_value=value)])
self.summary_writer.add_summary(summary, step)
def log_histogram(self, values, step, placeholder, histogram):
"""
:param values: An array of values that will be transformed into a histogram.
:type values: numpy.ndarray
:param step: Current step being recorded.
:type step: int
:param placeholder: Whete to store the values.
:type placeholder: tensorflow.Tensor
:param histogram: Histogram object.
:type histogram: tensorflow.Tensor
"""
summary = self.tf_session.run(
histogram, feed_dict={placeholder: values.astype(placeholder.dtype.as_numpy_dtype)}
)
self.summary_writer.add_summary(summary, step)
self.summary_writer.flush()
def log_image(self, tag, matrix, step):
"""
Given a matrix of values, store it in an image.
:param tag: Name of the image.
:type tag: str
:param matrix: The image, as a numpy array.
:type matrix: numpy.ndarray
:param step: Current step being recorded.
:type step: int
"""
vals = (viridis(matrix) * 255).round().astype(np.uint8)
vals.shape = (1, *vals.shape)
# logging probabilities as image
img = tf.summary.image(name=tag, tensor=vals)
summary = self.tf_session.run(img)
self.summary_writer.add_summary(summary, step)
self.summary_writer.flush()
def main(metadata_path, open_browser):
logger = TfLogger(metadata_path, open_browser)
n_steps = 100
loc = 0.5
scale = 0.1
factor = loc/n_steps
n_samples = 100
all_values = []
for i in range(n_steps):
vals = np.random.normal(loc=loc, scale=scale, size=n_samples)
loc = loc - factor
all_values += [vals]
logger.log_scalar(tag='mean', value=loc, step=i)
logger.log_histogram(
values=np.array(vals), step=i, placeholder=logger.some_placeholder,
histogram=logger.some_histogram
)
time.sleep(1) # naps for 1sec
print('step %d' % i)
logger.log_image(tag='image', matrix=np.array(all_values), step=i)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Toy script for showing how to log data with Tensorboard.'
)
parser.add_argument(
'--metadata', action='store', required=True,
help='Path to folder where Tensorflow metadata will be stored. Must be pre-existent. A new folder will be'
' created for each run.'
)
parser.add_argument(
'--open-browser', action='store_true', required=False, default=False,
help='Whether to open a new Browser tab to monitor the algorithm, or not. If you don\'t pass this parameter to'
' the algorithm, you will have to manually open tensorboard from the command line. The command for doing'
' that is:\n'
'\ttensorboard --logdir <path>'
)
args = parser.parse_args()
main(metadata_path=args.metadata, open_browser=args.open_browser)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment