Эта страница переведена с помощью Cloud Translation API.
Switch to English

Доступ к данным TensorBoard как DataFrames

Обзор

Главная особенность TensorBoard - интерактивный графический интерфейс. Однако пользователи иногда хотят программно читать журналы данных, хранящиеся в TensorBoard, для таких целей, как выполнение апостериорного анализа и создание настраиваемых визуализаций данных журнала.

TensorBoard 2.3 поддерживает этот вариант использования с tensorboard.data.experimental.ExperimentFromDev() . Он обеспечивает программный доступ к скалярным журналам TensorBoard. Эта страница демонстрирует базовое использование этого нового API.

Настроить

Чтобы использовать программный API, убедитесь, что вы установили pandas вместе с tensorboard .

Мы будем использовать matplotlib и seaborn для пользовательских графиков в этом руководстве, но вы можете выбрать предпочтительный инструмент для анализа и визуализации DataFrame s.

pip install tensorboard pandas
pip install matplotlib seaborn
from packaging import version

import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
from scipy import stats
import tensorboard as tb
major_ver, minor_ver, _ = version.parse(tb.__version__).release
assert major_ver >= 2 and minor_ver >= 3, \
    "This notebook requires TensorBoard 2.3 or later."
print("TensorBoard version: ", tb.__version__)
TensorBoard version:  2.3.0a20200626

Загрузка скаляров TensorBoard как pandas.DataFrame

Как только лог-каталог TensorBoard загружен в TensorBoard.dev, он становится тем, что мы называем экспериментом . У каждого эксперимента есть уникальный идентификатор, который можно найти в URL-адресе эксперимента TensorBoard.dev. Для нашей демонстрации ниже мы будем использовать эксперимент TensorBoard.dev по адресу: https://tensorboard.dev/experiment/c1KCv3X3QvGwaXfgX1c4tg.

experiment_id = "c1KCv3X3QvGwaXfgX1c4tg"
experiment = tb.data.experimental.ExperimentFromDev(experiment_id)
df = experiment.get_scalars()
df

df - это pandas.DataFrame , содержащий все скалярные журналы эксперимента.

Столбцы DataFrame :

  • run : каждый запуск соответствует подкаталогу исходного каталога журнала. В этом эксперименте каждый запуск основан на полном обучении сверточной нейронной сети (CNN) на наборе данных MNIST с заданным типом оптимизатора (обучающий гиперпараметр). Этот DataFrame содержит несколько таких запусков, которые соответствуют повторяющимся обучающим запускам с разными типами оптимизатора.
  • tag : описывает, что означает value в той же строке, то есть какую метрику представляет значение в строке. В этом эксперименте у нас есть только два уникальных epoch_accuracy : epoch_accuracy и epoch_loss для показателей точности и потерь соответственно.
  • step : это номер, который отражает порядковый номер соответствующей строки в ее прогоне. Здесь step фактически относится к номеру эпохи. Если вы хотите получить отметки времени в дополнение к значениям step , вы можете использовать аргумент ключевого слова include_wall_time=True при вызове get_scalars() .
  • value : это действительное числовое значение, представляющее интерес. Как описано выше, каждое value в этом конкретном DataFrame является либо потерей, либо точностью, в зависимости от tag строки.
print(df["run"].unique())
print(df["tag"].unique())
['adam,run_1/train' 'adam,run_1/validation' 'adam,run_2/train'
 'adam,run_2/validation' 'adam,run_3/train' 'adam,run_3/validation'
 'adam,run_4/train' 'adam,run_4/validation' 'adam,run_5/train'
 'adam,run_5/validation' 'rmsprop,run_1/train' 'rmsprop,run_1/validation'
 'rmsprop,run_2/train' 'rmsprop,run_2/validation' 'rmsprop,run_3/train'
 'rmsprop,run_3/validation' 'rmsprop,run_4/train'
 'rmsprop,run_4/validation' 'rmsprop,run_5/train'
 'rmsprop,run_5/validation' 'sgd,run_1/train' 'sgd,run_1/validation'
 'sgd,run_2/train' 'sgd,run_2/validation' 'sgd,run_3/train'
 'sgd,run_3/validation' 'sgd,run_4/train' 'sgd,run_4/validation'
 'sgd,run_5/train' 'sgd,run_5/validation']
['epoch_accuracy' 'epoch_loss']

Получение развернутого (широкоформатного) DataFrame

В нашем эксперименте два epoch_loss ( epoch_loss и epoch_accuracy ) присутствуют на одном и том же наборе шагов при каждом запуске. Это позволяет получить DataFrame «широкой формы» непосредственно из get_scalars() с помощью аргумента ключевого слова pivot=True . В широкоформатном DataFrame все теги включены как столбцы DataFrame, что в некоторых случаях, в том числе и с этим, более удобно для работы.

Однако имейте в виду, что если условие наличия единых наборов значений шага для всех тегов во всех прогонах не выполняется, использование pivot=True приведет к ошибке.

dfw = experiment.get_scalars(pivot=True) 
dfw

Обратите внимание, что вместо одного столбца «значения» широкоформатный DataFrame включает в себя два тега (метрики) в качестве своих столбцов: epoch_accuracy и epoch_loss .

Сохранение DataFrame как CSV

pandas.DataFrame хорошо взаимодействует с CSV . Вы можете сохранить его как локальный CSV-файл и загрузить его позже. Например:

csv_path = '/tmp/tb_experiment_1.csv'
dfw.to_csv(csv_path, index=False)
dfw_roundtrip = pd.read_csv(csv_path)
pd.testing.assert_frame_equal(dfw_roundtrip, dfw)

Выполнение пользовательской визуализации и статистического анализа

# Filter the DataFrame to only validation data, which is what the subsequent
# analyses and visualization will be focused on.
dfw_validation = dfw[dfw.run.str.endswith("/validation")]
# Get the optimizer value for each row of the validation DataFrame.
optimizer_validation = dfw_validation.run.apply(lambda run: run.split(",")[0])

plt.figure(figsize=(16, 6))
plt.subplot(1, 2, 1)
sns.lineplot(data=dfw_validation, x="step", y="epoch_accuracy",
             hue=optimizer_validation).set_title("accuracy")
plt.subplot(1, 2, 2)
sns.lineplot(data=dfw_validation, x="step", y="epoch_loss",
             hue=optimizer_validation).set_title("loss")
Text(0.5, 1.0, 'loss')

PNG

На графиках выше показаны временные рамки точности валидации и потери валидации. Каждая кривая показывает среднее значение по 5 прогонам для определенного типа оптимизатора. Благодаря встроенной функции seaborn.lineplot() каждая кривая также отображает ± 1 стандартное отклонение от среднего, что дает нам четкое представление об изменчивости этих кривых и значимости различий между тремя типами оптимизаторов. Эта визуализация изменчивости еще не поддерживается в графическом интерфейсе TensorBoard.

Мы хотим изучить гипотезу о том, что минимальные потери при проверке значительно различаются между оптимизаторами «adam», «rmsprop» и «sgd». Итак, мы извлекаем DataFrame для минимальной потери валидации для каждого из оптимизаторов.

Затем мы делаем коробчатую диаграмму, чтобы визуализировать разницу в минимальных потерях при проверке.

adam_min_val_loss = dfw_validation.loc[optimizer_validation=="adam", :].groupby(
    "run", as_index=False).agg({"epoch_loss": "min"})
rmsprop_min_val_loss = dfw_validation.loc[optimizer_validation=="rmsprop", :].groupby(
    "run", as_index=False).agg({"epoch_loss": "min"})
sgd_min_val_loss = dfw_validation.loc[optimizer_validation=="sgd", :].groupby(
    "run", as_index=False).agg({"epoch_loss": "min"})
min_val_loss = pd.concat([adam_min_val_loss, rmsprop_min_val_loss, sgd_min_val_loss])

sns.boxplot(data=min_val_loss, y="epoch_loss",
            x=min_val_loss.run.apply(lambda run: run.split(",")[0]))
<matplotlib.axes._subplots.AxesSubplot at 0x7f5e017c8150>

PNG

# Perform pairwise comparisons between the minimum validation losses
# from the three optimizers.
_, p_adam_vs_rmsprop = stats.ttest_ind(
    adam_min_val_loss["epoch_loss"],
    rmsprop_min_val_loss["epoch_loss"]) 
_, p_adam_vs_sgd = stats.ttest_ind(
    adam_min_val_loss["epoch_loss"],
    sgd_min_val_loss["epoch_loss"]) 
_, p_rmsprop_vs_sgd = stats.ttest_ind(
    rmsprop_min_val_loss["epoch_loss"],
    sgd_min_val_loss["epoch_loss"]) 
print("adam vs. rmsprop: p = %.4f" % p_adam_vs_rmsprop)
print("adam vs. sgd: p = %.4f" % p_adam_vs_sgd)
print("rmsprop vs. sgd: p = %.4f" % p_rmsprop_vs_sgd)
adam vs. rmsprop: p = 0.0244
adam vs. sgd: p = 0.9749
rmsprop vs. sgd: p = 0.0135

Следовательно, при уровне значимости 0,05 наш анализ подтверждает нашу гипотезу о том, что минимальные потери при проверке значительно выше (т. Е. Хуже) в оптимизаторе среднеквадратичного отклонения по сравнению с двумя другими оптимизаторами, включенными в наш эксперимент.

Таким образом, в этом руководстве представлен пример того, как получить доступ к скалярным данным как panda.DataFrame из TensorBoard.dev. Он демонстрирует гибкий и мощный анализ и визуализацию, которые вы можете выполнять с помощью DataFrame .