Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/tensorboard/dataframe_api.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Acesso aos dados do TensorBoard como DataFrames

Visão geral

O principal recurso do TensorBoard é a GUI interativa. No entanto, às vezes, os usuários querem ler programaticamente os logs de dados armazenados no TensorBoard, para fins como realizar análises post-hoc e criar visualizações personalizadas para os dados dos logs.

O TensorBoard 2.3 oferece suporte a esse caso de uso com tensorboard.data.experimental.ExperimentFromDev(). Ele permite o acesso programático aos logs escalares do TensorBoard. Esta página demonstra o uso básico dessa nova API.

Observação:

  1. Essa API ainda está em fase experimental, conforme refletido pelo seu namespace. Isso significa que ela está sujeita a mudanças que causam quebras no futuro.

  2. No momento, esse recurso só aceita logdirs carregados no TensorBoard.dev, um serviço hospedado gratuito para manter e compartilhar seu TensorBoard. O suporte ao logdir do TensorBoard armazenado localmente será adicionado no futuro. Rapidamente, você pode enviar um logdir do TensorBoard no seu sistema de arquivos local para o TensorBoard.dev com uma única linha de comando: tensorboard dev upload --logdir <logdir>. Veja a documentação em tensorboard.dev para mais detalhes.

Configuração

Para usar a API programática, instale o pandas com o tensorboard.

Vamos usar matplotlib e seaborn para as plotagens personalizadas neste guia, mas você pode escolher a ferramenta da sua preferência para analisar e visualizar DataFrames.

!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

Carregue escalares do TensorBoard como pandas.DataFrame

Depois de enviar um logdir do TensorBoard para o TensorBoard.dev, ele se torna o que chamamos de experimento. Cada experimento tem um ID único, que pode ser encontrado na URL do TensorBoard.dev do experimento. Para nossa demonstração abaixo, vamos usar um experimento do TensorBoard.dev em: https://tensorboard.dev/experiment/c1KCv3X3QvGwaXfgX1c4tg

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

df é um pandas.DataFrame que contém todos os logs escalares do experimento.

As colunas do DataFrame são:

  • run: cada execução (run) corresponde a um subdiretório do logdir original. Nesse experimento, cada execução é de um treinamento completo de uma rede neural convolucional (CNN) no dataset MNIST com um determinado tipo de otimizador (um hiperparâmetro de treinamento). Esse DataFrame contém várias execuções assim, que correspondem a execuções de treinamento repetidas em diferentes tipos de otimizadores.

  • tag: descreve o que o value na mesma linha significa, ou seja, a métrica que o valor representa na linha. Nesse experimento, só temos duas tags únicas: epoch_accuracy e epoch_loss para as métricas de exatidão e perda, respectivamente.

  • step: é um número que reflete a ordem serial da linha correspondente na sua execução. Aqui, step se refere ao número de épocas. Para obter os carimbos de data/hora, além dos valores de step, você pode usar o argumento de palavra-chave include_wall_time=True ao chamar get_scalars().

  • value: é o valor numérico de interesse. Como descrito acima, cada value nesse DataFrame específico é uma perda ou uma precisão, dependendo da tag da linha.

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']

Obtenha um DataFrame pivotado (formato amplo)

Em nosso experimento, as duas tags (epoch_loss e epoch_accuracy) estão presentes no mesmo conjunto de passos em cada execução. Isso possibilita obter um DataFrame de "formato amplo" diretamente de get_scalars() ao usar o argumento de palavras-chave pivot=True. O DataFrame de formato amplo tem todas as tags inclusas como colunas do DataFrame, sendo mais conveniente em alguns casos, incluindo esse.

No entanto, se a condição para ter conjuntos uniformes de valores de passos em todas as tags e em todas as execuções não for atendida, o uso de pivot=True resultará em um erro.

dfw = experiment.get_scalars(pivot=True) dfw

Observe que, em vez de uma única coluna de "valor", o DataFrame de formato amplo inclui duas tags (métricas) como suas colunas de maneira explícita: epoch_accuracy e epoch_loss.

Salve o DataFrame como CSV

pandas.DataFrame tem uma boa interoperabilidade com o CSV. Você pode armazená-lo como um arquivo de CSV local e carregá-lo novamente mais tarde. Por exemplo:

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)

Personalize a visualização e faça a análise estatística

# 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')
Image in a Jupyter notebook

As plotagens acima mostram as evoluções temporais da exatidão de validação e da perda de validação. Cada curva mostra a média em 5 execuções com um tipo de otimizador. Devido a uma funcionalidade integrada de seaborn.lineplot(), cada curva também exibe o desvio-padrão ±1 em torno da média, o que fornece uma sensação clara de variabilidade nessas curvas e a significância das diferenças entre os três tipos de otimizadores. Essa visualização de variabilidade ainda não é compatível com a GUI do TensorBoard.

Queremos estudar a hipótese de que a perda de validação mínima difere significativamente entre os otimizadores "adam", "rmsprop" e "sgd". Portanto, extraímos um DataFrame para a perda de validação mínima em cada um dos otimizadores.

Em seguida, criamos um diagrama de caixa para visualizar a diferença nas perdas de validação mínimas.

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>
Image in a Jupyter notebook
# 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

Portanto, em um nível de significância de 0,05, nossa análise confirma a hipótese que a perda de validação mínima é significativamente mais alta (ou seja, pior) no otimizador rmsprop em comparação com os outros dois otimizadores inclusos em nosso experimento.

Resumindo, esse tutorial oferece um exemplo de como acessar os dados escalares como panda.DataFrames a partir do TensorBoard.dev. Ele demonstra o tipo de análise e visualização flexível e avançada que você pode fazer com os DataFrames.