Polyaxon provides several methods for tracking metrics, metadata, summaries, and graphs in your jobs.
Overview
For each run, Polyaxon creates an artifacts folder with a predefined structure to organize your events:
- metrics
- charts
- text
- HTML
- …
Some events create save related assets to these events and are saved under a separate folder called assets
.
Logging single results and outputs
To log single results that do not need to be visualized, do not change over time, or only should be recorded at the end of a job you should use:
from polyaxon import tracking
tracking.log_outputs(foo="bar", scalar=0.1, key="val")
Logging step-wise events
To log texts, HTML, scalars, metrics that change overtime or need to be recorded in a step-wise manner, or if you need to visualize the event in the dashboard you should use:
Tracking changing metrics
from polyaxon import tracking
def get_loss(step):
result = 10 / (step + 1)
noise = (random.random() - 0.5) * 0.5 * result
return result + noise
def get_accuracy(loss):
return (100 - loss) / 100.0
for i in range(1, 5):
loss = get_loss(i)
accuracy = get_accuracy(loss)
tracking.log_metrics(loss=loss, accuracy=accuracy, step=i)
Tracking a changing text value over time or step-wise
from polyaxon import tracking
for i in range(1, 5):
tracking.log_text(name="text-event", value="value at step {}".format(i), step=i)
Tracking a changing HTML value over time or step-wise
from polyaxon import tracking
def get_html(step):
return (
'<span><a href="https://link.com">This is a link {step} </a>'
'<b>Some more html at step {step}</b></span>'.format(step=step)
)
for i in range(1, 5):
tracking.log_html(name="text-event", html=get_html(i), step=i)
Tracking a changing audio over time or step-wise
import numpy as np
from polyaxon import tracking
def get_audio(step):
sample_rate = 44100 + step
freqs = 440
dummy_audio = np.arange(sample_rate * 2, dtype=np.float32)
return np.cos(dummy_audio * (2.0 * freqs * np.pi / sample_rate))
for i in range(1, 5):
tracking.log_audio(data=get_audio(i), name='audio-ex', step=i)
Tracking a changing distribution over time or step-wise
from polyaxon import tracking
def get_dist(step):
x = np.random.random(1000)
return x + step
def get_np_hist(step):
values, counts = np.histogram(np.random.randint(255, size=(1000,)))
return {"values": values, "counts": counts, "step": step}
for i in range(1, 5):
tracking.log_histogram('distribution', get_dist(i), 'auto', step=i)
tracking.log_np_histogram('np-hist', **get_np_hist(i))
- Tracking a changing curves and charts over time or step-wise
import random
import altair as alt
import matplotlib.pyplot as plt
import numpy as np
import plotly.express as px
from bokeh.plotting import figure
from vega_datasets import data
from polyaxon import tracking
def plot_scatter(step):
x = np.random.randn(step)
y = np.random.randn(step)
left, width = 0.1, 0.65
bottom, height = 0.1, 0.65
spacing = 0.005
rect_scatter = [left, bottom, width, height]
rect_histx = [left, bottom + height + spacing, width, 0.2]
rect_histy = [left + width + spacing, bottom, 0.2, height]
figure = plt.figure(figsize=(8, 8))
ax_scatter = plt.axes(rect_scatter)
ax_scatter.tick_params(direction='in', top=True, right=True)
ax_histx = plt.axes(rect_histx)
ax_histx.tick_params(direction='in', labelbottom=False)
ax_histy = plt.axes(rect_histy)
ax_histy.tick_params(direction='in', labelleft=False)
ax_scatter.scatter(x, y)
binwidth = 0.25
lim = np.ceil(np.abs([x, y]).max() / binwidth) * binwidth
ax_scatter.set_xlim((-lim, lim))
ax_scatter.set_ylim((-lim, lim))
bins = np.arange(-lim, lim + binwidth, binwidth)
ax_histx.hist(x, bins=bins)
ax_histy.hist(y, bins=bins, orientation='horizontal')
ax_histx.set_xlim(ax_scatter.get_xlim())
ax_histy.set_ylim(ax_scatter.get_ylim())
tracking.log_mpl_plotly_chart(name='scatter', figure=figure, step=step)
def plot_mpl_figure(step):
np.random.seed(step)
data = np.random.randn(2, 100)
figure, axs = plt.subplots(2, 2, figsize=(5, 5))
axs[0, 0].hist(data[0])
axs[1, 0].scatter(data[0], data[1])
axs[0, 1].plot(data[0], data[1])
axs[1, 1].hist2d(data[0], data[1])
tracking.log_mpl_image(figure, 'mpl_image', step=step)
def log_bokeh(step):
factors = ["a", "b", "c", "d", "e", "f", "g", "h"]
x = [50, 40, 65, 10, 25, 37, 80, 60]
dot = figure(title="Categorical Dot Plot", tools="", toolbar_location=None,
y_range=factors, x_range=[0, 100])
dot.segment(0, factors, x, factors, line_width=2, line_color="green", )
dot.circle(x, factors, size=15, fill_color="orange", line_color="green", line_width=3, )
factors = ["foo 123", "bar:0.2", "baz-10"]
x = ["foo 123", "foo 123", "foo 123", "bar:0.2", "bar:0.2", "bar:0.2", "baz-10", "baz-10",
"baz-10"]
y = ["foo 123", "bar:0.2", "baz-10", "foo 123", "bar:0.2", "baz-10", "foo 123", "bar:0.2",
"baz-10"]
colors = [
"#0B486B", "#79BD9A", "#CFF09E",
"#79BD9A", "#0B486B", "#79BD9A",
"#CFF09E", "#79BD9A", "#0B486B"
]
hm = figure(title="Categorical Heatmap", tools="hover", toolbar_location=None,
x_range=factors, y_range=factors)
hm.rect(x, y, color=colors, width=1, height=1)
tracking.log_bokeh_chart(name='confusion-bokeh', figure=hm, step=step)
def log_altair(step):
source = data.cars()
brush = alt.selection(type='interval')
points = alt.Chart(source).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color=alt.condition(brush, 'Origin:N', alt.value('lightgray'))
).add_selection(
brush
)
bars = alt.Chart(source).mark_bar().encode(
y='Origin:N',
color='Origin:N',
x='count(Origin):Q'
).transform_filter(
brush
)
chart = points & bars
tracking.log_altair_chart(name='altair_chart', figure=chart, step=step)
def log_curves(step):
# ROC curve
x = [
0.0,
0.0,
0.0,
0.0196078431372549,
0.0196078431372549,
0.0784313725490196,
0.0784313725490196,
0.09803921568627451,
0.09803921568627451,
0.11764705882352941,
0.11764705882352941,
0.13725490196078433,
0.13725490196078433,
0.1568627450980392,
0.1568627450980392,
0.17647058823529413,
0.17647058823529413,
0.3137254901960784,
0.3137254901960784,
0.3333333333333333,
0.3333333333333333,
0.35294117647058826,
0.35294117647058826,
0.4117647058823529,
0.4117647058823529,
0.45098039215686275,
0.45098039215686275,
0.47058823529411764,
0.47058823529411764,
0.5098039215686274,
0.5098039215686274,
0.5686274509803921,
0.5686274509803921,
1.0
]
y = [
0.0,
0.041666666666666664,
0.125,
0.125,
0.25,
0.25,
0.2916666666666667,
0.2916666666666667,
0.3333333333333333,
0.3333333333333333,
0.4166666666666667,
0.4166666666666667,
0.5,
0.5,
0.5416666666666666,
0.5416666666666666,
0.5833333333333334,
0.5833333333333334,
0.7083333333333334,
0.7083333333333334,
0.75,
0.75,
0.7916666666666666,
0.7916666666666666,
0.8333333333333334,
0.8333333333333334,
0.875,
0.875,
0.9166666666666666,
0.9166666666666666,
0.9583333333333334,
0.9583333333333334,
1.0,
1.0
]
tracking.log_roc_auc_curve(name='roc-curve-man', fpr=x, tpr=y, auc=0.742149, step=step)
x = [0.66666667, 0.5, 1., 1.]
y = [1., 0.5, 0.5, 0.]
tracking.log_pr_curve(name='pr-curve-man', precision=x, recall=y, average_precision=0.742149,
step=step)
# Random curve
tracking.log_curve(
name='random-curve-man', x=np.random.randn(10 * step), y=np.random.randn(10 * step), step=step
)
def get_sin_plot(step):
x = np.linspace(0, step * np.pi, 400)
y = np.sin(x ** 2)
f, ax = plt.subplots()
ax.plot(x, y)
ax.set_title('Simple plot')
tracking.log_mpl_plotly_chart(name='sin', figure=f, step=step)
def log_confusion(step):
z = np.array([[0.1, 0.3, 0.5, 0.2],
[1.0, 0.8, 0.6, 0.1],
[0.1, 0.3, 0.6, 0.9],
[0.6, 0.4, 0.2, 0.2]]) * step
x = ['healthy', 'multiple diseases', 'rust', 'scab']
y = ['healthy', 'multiple diseases', 'rust', 'scab']
tracking.log_confusion_matrix("confusion_test", x, y, z.tolist(), step=step)
def log_plotly(step):
df = px.data.tips()
fig = px.density_heatmap(df, x="total_bill", y="tip", facet_row="sex", facet_col="smoker")
tracking.log_plotly_chart(name="2d-hist", figure=fig, step=step)
for i in range(1, 5):
plot_scatter(i)
get_sin_plot(i)
plot_mpl_figure(i)
log_bokeh(i)
log_altair(i)
log_curves(i)
log_plotly(i)
log_confusion(i)