本頁面由 Cloud Translation API 翻譯而成。
Switch to English

將TensorBoard數據作為DataFrames訪問

總覽

TensorBoard的主要功能是其交互式GUI。但是,用戶有時希望以編程方式讀取TensorBoard中存儲的數據日誌,以進行事後分析和創建日誌數據的自定義可視化等目的。

TensorBoard 2.3通過tensorboard.data.experimental.ExperimentFromDev()支持此用例。它允許以編程方式訪問TensorBoard的標量日誌 。此頁面演示了此新API的基本用法。

建立

為了使用編程API,請確保在tensorboard旁邊安裝pandas

在本指南中,我們將使用matplotlibseaborn進行自定義圖,但是您可以選擇首選工具來分析和可視化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後,它就成為我們稱為實驗 。每個實驗都有一個唯一的ID,該ID可在實驗的TensorBoard.dev URL中找到。對於下面的演示,我們將在以下位置使用TensorBoard.dev實驗: https ://tensorboard.dev/experiment/c1KCv3X3QvGwaXfgX1c4tg

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

dfpandas.DataFrame ,其中包含實驗的所有標量日誌。

DataFrame

  • run :每次運行都對應於原始logdir的子目錄。在此實驗中,每次運行都來自對具有給定優化器類型(訓練超參數)的MNIST數據集的捲積神經網絡(CNN)的完整訓練。此DataFrame包含多個此類運行,它們對應於不同優化器類型下的重複訓練運行。
  • tag :描述同一行中的value的含義,即該值在行中表示的度量。在此實驗中,我們只有兩個唯一的標記: epoch_accuracyepoch_loss用於準確性和損耗度量。
  • step :這是一個數字,它反映相應行在運行中的序列順序。這裡的step實際上是指紀元號。如果您希望獲取除step值以外的時間戳,則可以在調用get_scalars()時使用關鍵字參數include_wall_time=True
  • value :這是實際的實際數值。如上所述,取決於行的tag ,此特定DataFrame每個value要么是損失,要么是準確性。
 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_lossepoch_accuracy )在每次運行中都出現在相同的一組步驟中。這樣就可以通過使用get_scalars() pivot=True關鍵字參數直接從get_scalars()獲得“寬格式” DataFrame 。寬格式的DataFrame所有標籤都包含在DataFrame的列中,在某些情況下(包括該標籤),使用起來更加方便。

但是,請注意,如果不滿足在所有運行中跨所有標籤具有統一步長值集合的條件,則使用pivot=True將導致錯誤。

 dfw = experiment.get_scalars(pivot=True) 
dfw
 

請注意,寬格式的DataFrame包含兩個標籤(指標)作為其列,而不是單個“值”列: epoch_accuracyepoch_loss

將DataFrame保存為CSV

pandas.DataFrameCSV具有良好的互操作性。您可以將其存儲為本地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的GUI尚不支持這種可變性的可視化。

我們想研究一個假設,即“ 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優化器的最小驗證損失顯著更高(即更差)。

總之,本教程提供了一個示例,說明如何從TensorBoard.dev中以panda.DataFrame的形式訪問標量數據。它展示了您可以使用DataFrame進行的靈活而強大的分析和可視化。