Ver no TensorFlow.org | Executar no Google Colab | Ver fonte no GitHub | Baixar caderno |
import tensorflow as tf
TensorFlow 2.x inclui mudanças significativas para o tf.summary
API usado para dados de resumo de gravação para visualização em TensorBoard.
O que mudou
É útil pensar no tf.summary
API como dois sub-APIs:
- Um conjunto de ops para gravação resumos individuais -
summary.scalar()
,summary.histogram()
,summary.image()
,summary.audio()
, esummary.text()
- que são chamados de linha do seu código modelo. - Lógica de gravação que coleta esses resumos individuais e os grava em um arquivo de registro formatado especialmente (que o TensorBoard lê para gerar visualizações).
Em TF 1.x
As duas metades tiveram de ser ligado manualmente juntos - por buscar as saídas op resumo via Session.run()
e chamando FileWriter.add_summary(output, step)
. O v1.summary.merge_all()
op feito isso mais fácil usando uma coleção gráfico para agregar todas as saídas op resumo, mas esta abordagem ainda funcionou mal para execução ansioso e fluxo de controle, tornando-se especialmente mal adequado para TF 2.x.
Em TF 2.X
As duas metades são totalmente integrados, e agora individuais tf.summary
ops escrever seus dados imediatamente quando executado. Usar a API do código do seu modelo ainda deve parecer familiar, mas agora é amigável para execução rápida enquanto permanece compatível com o modo gráfico. Integrando as duas metades dos meios de API do summary.FileWriter
agora faz parte do contexto de execução TensorFlow e é acessado diretamente pelo tf.summary
ops, assim configurando escritores é a parte principal que parece diferente.
Exemplo de uso com execução rápida, 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
events.out.tfevents.1633086727.kokoro-gcp-ubuntu-prod-1386032077.31590.0.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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.1.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.1633086728.kokoro-gcp-ubuntu-prod-1386032077.31590.2.v2
Convertendo seu código
Convertendo existente tf.summary
uso da API TF 2.x não pode ser confiavelmente automatizado, assim que o tf_upgrade_v2
roteiro apenas reescreve tudo para tf.compat.v1.summary
. Para migrar para o TF 2.x, você precisará adaptar seu código da seguinte maneira:
Um conjunto escritor default via
.as_default()
deve estar presente para uso ops sumárias- 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
- Escritores padrão não (ainda) propagam-se através do
@tf.function
limite de execução - eles só são detectados quando a função é rastreada - para a melhor prática é chamarwriter.as_default()
dentro do corpo da função, e para garantir que o objeto escritor continua a existir enquanto o@tf.function
está sendo usado
O valor "passo" deve ser passado para cada op através de um o
step
argumento- 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 clichê, suporte experimental para registrar um valor etapa padrão está disponível como
tf.summary.experimental.set_step()
, mas esta é a funcionalidade provisória que pode ser alterada sem aviso prévio
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 parâmetro de nome (se usado) foi alterado de
tensor
dedata
- O
collections
parâmetro foi removido; coleções são TF 1.x apenas - A
family
parâmetro foi removido; apenas usotf.name_scope()
[Apenas para usuários de modo de gráfico legado / execução de sessão]
Primeiro inicializar o escritor com
v1.Session.run(writer.init())
Use
v1.summary.all_v2_summary_ops()
para obter todos os ops sumárias TF 2.x para o gráfico atual, por exemplo, para executá-los viaSession.run()
Lave o escritor com
v1.Session.run(writer.flush())
e também paraclose()
Se o seu código 1.x TF foi em vez de usar tf.contrib.summary
API, é muito mais parecida com a API TF 2.x, então tf_upgrade_v2
script irá automatizar a maioria das etapas de migração (e emitem avisos ou erros para qualquer uso que não pode ser totalmente migrado). Para a maior parte apenas reescreve as chamadas de API para tf.compat.v2.summary
; Se você só precisa de compatibilidade com TF 2.x você pode soltar a 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
- Para ops controle e código associado, envolvê-los em um regular if (que funciona no modo ansioso e em
@tf.function
via autógrafo ) ou umtf.cond
- Para controlar apenas resumos, usar o novo
tf.summary.record_if()
gerente de contexto, e passá-lo a condição boolean de sua escolha Eles substituem o padrão TF 1.x:
if condition: writer.add_summary()
- Para ops controle e código associado, envolvê-los em um regular if (que funciona no modo ansioso e em
Sem escrita direta de
tf.compat.v1.Graph
- em vez funções uso de rastreamento- Execução Graph em usos TF 2.x
@tf.function
em vez do Graph explícita - Em TF 2.x, utilize o APIs novo estilo de traçado
tf.summary.trace_on()
etf.summary.trace_export()
para gravar os gráficos das funções executadas
- Execução Graph em usos TF 2.x
Sem cache escritor mais global per logdir com
tf.summary.FileWriterCache
- Os usuários devem quer implementar seu próprio cache / compartilhamento de objetos escritor, ou simplesmente usar escritores independentes (suporte TensorBoard para o último é 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 para numpy