Esta página foi traduzida pela API Cloud Translation.
Switch to English

Migrando o uso de tf.summary para TF 2.0

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub
import tensorflow as tf

O TensorFlow 2.0 inclui mudanças significativas na API tf.summary usada para escrever dados resumidos para visualização no TensorBoard.

O que mudou

É útil pensar na API tf.summary como duas sub APIs:

Em TF 1.x

As duas metades tiveram que ser conectadas manualmente - obtendo as saídas de Session.run() resumidas por meio de Session.run() e chamando FileWriter.add_summary(output, step) . A v1.summary.merge_all() tornou isso mais fácil usando uma coleção de gráficos para agregar todas as saídas de v1.summary.merge_all() resumidas, mas essa abordagem ainda funcionou mal para execução rápida e fluxo de controle, tornando-a especialmente inadequada para TF 2.0.

Em TF 2.X

As duas metades estão totalmente integradas, e agora operações tf.summary individuais tf.summary seus dados imediatamente quando executados. Usar a API do código do modelo ainda deve parecer familiar, mas agora é fácil de executar e ainda é compatível com o modo gráfico. Integrar as duas metades da API significa que o summary.FileWriter agora faz parte do contexto de execução do TensorFlow e é acessado diretamente por operações tf.summary , portanto, configurar os tf.summary é a parte principal que parece diferente.

Exemplo de uso com execução rápida, o padrão no TF 2.0:

writer = tf.summary.create_file_writer("/tmp/mylogs/eager")

with writer.as_default():
  for step in range(100):
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)
    writer.flush()
ls /tmp/mylogs/eager
events.out.tfevents.1599908770.kokoro-gcp-ubuntu-prod-1849198075.22428.5.v2

Exemplo de uso com execução de gráfico tf.function:

writer = tf.summary.create_file_writer("/tmp/mylogs/tf_function")

@tf.function
def my_func(step):
  with writer.as_default():
    # other model code would go here
    tf.summary.scalar("my_metric", 0.5, step=step)

for step in tf.range(100, dtype=tf.int64):
  my_func(step)
  writer.flush()
ls /tmp/mylogs/tf_function
events.out.tfevents.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1013.v2

Exemplo de uso com execução de gráfico TF 1.x legado:

g = tf.compat.v1.Graph()
with g.as_default():
  step = tf.Variable(0, dtype=tf.int64)
  step_update = step.assign_add(1)
  writer = tf.summary.create_file_writer("/tmp/mylogs/session")
  with writer.as_default():
    tf.summary.scalar("my_metric", 0.5, step=step)
  all_summary_ops = tf.compat.v1.summary.all_v2_summary_ops()
  writer_flush = writer.flush()


with tf.compat.v1.Session(graph=g) as sess:
  sess.run([writer.init(), step.initializer])

  for i in range(100):
    sess.run(all_summary_ops)
    sess.run(step_update)
    sess.run(writer_flush)  
ls /tmp/mylogs/session
events.out.tfevents.1599908771.kokoro-gcp-ubuntu-prod-1849198075.22428.1446.v2

Convertendo seu código

A conversão do uso de tf.summary existente para a API do TF 2.0 não pode ser automatizada de forma confiável, então o script tf_upgrade_v2 apenas reescreve tudo em tf.compat.v1.summary . Para migrar para o TF 2.0, você precisará adaptar seu código da seguinte maneira:

  1. Um gravador padrão definido via .as_default() deve estar presente para usar operações de resumo

    • Isso significa executar ops avidamente ou usar ops na construção de gráficos
    • Sem um gravador padrão, as operações de resumo tornam-se silenciosas
    • Os @tf.function padrão (ainda) não se propagam através do limite de execução de @tf.function - eles só são detectados quando a função é rastreada - então a prática recomendada é chamar writer.as_default() dentro do corpo da função e garantir que o objeto escritor continua a existir enquanto a função @tf.function estiver sendo usada
  2. O valor "step" deve ser passado em cada op por meio de um argumento the step

    • TensorBoard requer um valor de etapa para renderizar os dados como uma série temporal
    • A passagem explícita é necessária porque a etapa global do TF 1.x foi removida, então cada op deve saber a variável de etapa desejada para ler
    • Para reduzir o boilerplate, o suporte experimental para registrar um valor de etapa padrão está disponível como tf.summary.experimental.set_step() , mas esta é uma funcionalidade provisória que pode ser alterada sem aviso prévio
  3. As assinaturas de funções de operações de resumo individuais foram alteradas

    • O valor de retorno agora é um booleano (indicando se um resumo foi realmente escrito)
    • O segundo nome do parâmetro (se usado) mudou de tensor para data
    • O parâmetro de collections foi removido; coleções são TF 1.x apenas
    • O parâmetro da family foi removido; apenas use tf.name_scope()
  4. [Apenas para usuários de modo de gráfico legado / execução de sessão]

    • Inicialize primeiro o gravador com v1.Session.run(writer.init())

    • Use v1.summary.all_v2_summary_ops() para obter todas as operações de resumo do TF 2.0 para o gráfico atual, por exemplo, para executá-las via Session.run()

    • Limpe o gravador com v1.Session.run(writer.flush()) e da mesma forma para close()

Se seu código TF 1.x estava usando a API tf.contrib.summary , é muito mais semelhante à API TF 2.0, então o script tf_upgrade_v2 automatizará a maioria das etapas de migração (e emitirá avisos ou erros para qualquer uso que não possa ser totalmente migrado). Na maior parte, ele apenas reescreve as chamadas de API para tf.compat.v2.summary ; se você só precisa de compatibilidade com TF 2.0+, pode descartar o compat.v2 e apenas referenciá-lo como tf.summary .

Dicas adicionais

Além das áreas críticas acima, alguns aspectos auxiliares também mudaram:

  • A gravação condicional (como "registrar a cada 100 etapas") tem uma nova aparência

if condition:
  writer.add_summary()
  • Sem escrita direta de tf.compat.v1.Graph - em vez disso, use funções de rastreamento

    • A execução do gráfico no TF 2.0 usa @tf.function vez do gráfico explícito
    • No TF 2.0, use as novas APIs de estilo de rastreamento tf.summary.trace_on() e tf.summary.trace_export() para registrar os gráficos de função executados
  • Não há mais armazenamento em cache do gravador global por logdir com tf.summary.FileWriterCache

    • Os usuários devem implementar seu próprio armazenamento em cache / compartilhamento de objetos de gravação ou apenas usar gravadores separados (o suporte do TensorBoard para o último está em andamento )
  • A representação binária do arquivo de evento mudou

    • O TensorBoard 1.x já oferece suporte ao novo formato; esta diferença afeta apenas os usuários que estão analisando manualmente os dados de resumo dos arquivos de eventos
    • Os dados de resumo agora são armazenados como bytes de tensor; você pode usar tf.make_ndarray(event.summary.value[0].tensor) para convertê-lo em numpy