Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/tensorboard/migrate.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.

Observação: esta documentação é para quem já está familiarizado com o TensorBoard do TensorFlow 1.x e quer migrar grandes bases de código do TensorFlow 1.x para o 2.x. Se você for iniciante no TensorBoard, veja a documentação para começar. Se estiver usando o tf.keras, talvez não seja necessária nenhuma ação para fazer upgrade para o TensorFlow 2.x.

import tensorflow as tf

O TensorFlow 2.x inclui mudanças significativas na API tf.summary usada para escrever dados de resumo para a visualização no TensorBoard.

O que mudou

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

  • Um conjunto de ops para gravar resumos individuais — summary.scalar(), summary.histogram(), summary.image(), summary.audio() e summary.text() — que são chamadas inline no código do seu modelo.

  • A escrita da lógica que coleta esses resumos individuais e os escreve em um arquivo de log especialmente formatado (que o TensorBoard lê para gerar visualizações).

No TF 1.x

As duas partes precisam ser conectadas manualmente — ao buscar as saídas da op de resumo pela Session.run() e chamar FileWriter.add_summary(output, step). A op v1.summary.merge_all() facilitou isso ao usar uma coleção de grafos para agregar todas as saídas da op de resumo, mas essa abordagem ainda teve um desempenho ruim para a eager execution e o fluxo de controle, tornando-a especialmente inadequada para o TF 2.x.

No TF 2.X

As duas metades são estreitamente integradas, e agora ops tf.summary individuais escrevem seus dados imediatamente quando executadas. O uso da API a partir do código do seu modelo ainda deve ser familiar, mas ela funciona com a eager execution sem deixar de ser compatível com o modo grafo. A integração das duas metades da API significa que summary.FileWriter faz parte do contexto de execução do TensorFlow e é acessado diretamente pelas ops tf.summary, então a configuração dos escritores é o que mais parece diferente.

Exemplo de uso com a eager execution, o padrão no TF 2.x:

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

Exemplo de uso com a graph execution da 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

Exemplo de uso com a graph execution legada do TF 1.x:

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

Conversão do código

A conversão do uso da tf.summary existente para a API do TF 2.x não pode ser automatizada com confiança, então o script tf_upgrade_v2 só reescreve tudo para tf.compat.v1.summary e não ativa os comportamentos do TF 2.x automaticamente.

Migração parcial

Para facilitar a migração ao TF 2.x para os usuários do código do modelo que ainda dependem bastante das ops de registro da API de resumo do TF 1.x, como tf.compat.v1.summary.scalar(), é possível migrar apenas as APIs de escrita, permitindo que as ops de resumo individuais do TF 1.x dentro do código do modelo sejam totalmente migradas mais tarde.

Para dar suporte a esse estilo de migração, tf.compat.v1.summary encaminhará automaticamente aos equivalentes do TF 2.x nas seguintes condições:

Observe que, quando a implementação de resumo do TF 2.x é invocada, o valor de retorno será um tensor bytestring vazio, para evitar a duplicação da escrita de resumo. Além disso, o encaminhamento dos argumentos de entrada é baseado em melhor esforço e nem todos os argumentos serão preservados (por exemplo, o argumento family será compatível, enquanto collections será removido).

Exemplo para invocar os comportamentos de tf.summary.scalar em tf.compat.v1.summary.scalar:

# Enable eager execution. tf.compat.v1.enable_v2_behavior() # A default TF 2.x summary writer is available. writer = tf.summary.create_file_writer("/tmp/mylogs/enable_v2_in_v1") # A step is set for the writer. with writer.as_default(step=0): # Below invokes `tf.summary.scalar`, and the return value is an empty bytestring. tf.compat.v1.summary.scalar('float', tf.constant(1.0), family="family")

Migração completa

Para migrar totalmente para o TF 2.x, você precisará adaptar seu código da seguinte maneira:

  1. Um escritor padrão definido por .as_default() precisa estar presente para usar as ops de resumo

    • Isso significa executar ops de maneira eager ou usar ops na construção do grafo

    • Sem um escritor padrão, as ops de resumo se tornam no-ops silenciosas

    • Os escritores padrão (ainda) não propagam no limite de execução da @tf.function — eles só são detectados com o tracing da função — então, a prática recomendada é chamar writer.as_default() no corpo da função, e para garantir que o objeto do escritor continue a existir enquanto a @tf.function estiver em uso

  2. O valor "step" precisa ser passado a cada op pelo argumento step

    • O TensorBoard exige um valor de passo para renderizar os dados como uma série temporal

    • A passagem explícita é necessária, porque o passo global do TF 1.x foi removido, então cada op precisa saber a variável de passo desejada para ler

    • Para reduzir o boilerplate, está disponível suporte experimental para registrar um valor de passo padrão como tf.summary.experimental.set_step(), mas essa é uma funcionalidade provisória que pode ser alterada sem aviso prévio

  3. As assinaturas da função de ops de resumo individuais mudaram

    • O valor de retorno é agora um booleano (indicando se um resumo foi mesmo escrito)

    • O nome do segundo parâmetro (se usado) mudou de tensor para data

    • O parâmetro collections foi removido: as coleções são apenas TF 1.x

    • O parâmetro family foi removido. Só use tf.name_scope()

  4. [Somente para usuários do modo grafo legado / execução da sessão]

    • Primeiro inicialize o escritor com v1.Session.run(writer.init())

    • Use v1.summary.all_v2_summary_ops() para obter todas as ops de resumo do TF 2.x para o grafo atual, por exemplo, para executá-las por Session.run()

    • Libere o escritor com v1.Session.run(writer.flush()) e também para close()

Se, em vez disso, seu código do TF 1.x usava a API tf.contrib.summary, é muito mais parecida com a API do TF 2.x, então o script tf_upgrade_v2 automatizará a maior parte dos passos de migração (e emitirá avisos ou erros para qualquer uso que não possa ser totalmente migrado). Para grande parte, ele só reescreve as chamadas de API para tf.compat.v2.summary, Se você só precisa de compatibilidade com o TF 2.x, pode descartar o compat.v2 e só fazer referência a tf.summary.

Dicas adicionais

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

  • A gravação condicional (como "registre a cada 100 passos") ganhou um novo visual

    • Para controlar as ops e o código associado, envolva-os em uma declaração if regular (que funciona no modo eager e na @tf.function pelo autografo) ou uma tf.cond

    • Para controlar só os resumos, use o novo gerenciador de contexto tf.summary.record_if() e passe a ele a condição booleana de sua preferência.

    • Isso substitui o padrão do TF 1.x:

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

    • A graph execution no TF 2.x usa @tf.function em vez do grafo explícito

    • No TF 2.x, use as novas APIs de estilo tracing tf.summary.trace_on() e tf.summary.trace_export() para registrar grafos de função executados

  • Sem mais armazenamento de cache do escritor global por logdir com tf.summary.FileWriterCache

    • Os usuários devem implementar os próprios objetos de escritor de armazenamento de cache/compartilhamento ou só usar escritores separados (o suporte do TensorBoard ao último está em andamento)

  • A representação do binário do arquivo de evento mudou

    • O TensorBoard 1.x já é compatível com o novo formato. Essa diferença só afeta usuários que estão processando manualmente os dados de resumo dos arquivos de evento

    • Os dados de resumo agora são armazenados como bytes de tensores. Você pode usar tf.make_ndarray(event.summary.value[0].tensor) para convertê-los para numpy