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

Доступ к данным TensorBoard как к фреймам данных

обзор

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

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

Настроить

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

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

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 : каждый запуск соответствует подкаталогу исходного logdir. В этом эксперименте каждый прогон происходит из полной тренировки сверточной нейронной сети (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 наш анализ подтверждает нашу гипотезу о том, что минимальная потеря проверки достоверности значительно выше (т.е. хуже) в оптимизаторе rmsprop по сравнению с двумя другими оптимизаторами, включенными в наш эксперимент.

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