Reserve a data! O Google I / O retorna de 18 a 20 de maio Registre-se agora
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Atualizar automaticamente o código para TensorFlow 2

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

O TensorFlow 2.0 inclui muitas alterações de API, como reordenar argumentos, renomear símbolos e alterar os valores padrão dos parâmetros. Realizar manualmente todas essas modificações seria tedioso e sujeito a erros. Para agilizar as mudanças e tornar sua transição para o TF 2.0 o mais perfeita possível, a equipe do tf_upgrade_v2 criou o utilitário tf_upgrade_v2 para ajudar na transição do código legado para a nova API.

O uso típico é assim:

tf_upgrade_v2 \
  --intree my_project/ \
  --outtree my_project_v2/ \
  --reportfile report.txt

Isso acelera o processo de atualização, convertendo os scripts Python do TensorFlow 1.x existentes para o TensorFlow 2.0.

O script de conversão automatiza o máximo possível, mas ainda há mudanças sintáticas e estilísticas que não podem ser executadas pelo script.

Módulos de compatibilidade

Certos símbolos API não podem ser atualizados simplesmente usando uma substituição de string. Para garantir que seu código ainda seja compatível com o TensorFlow 2.0, o script de upgrade inclui um módulo compat.v1 . Este módulo substitui os símbolos TF 1.x como tf.foo pela referência tf.compat.v1.foo equivalente. Embora o módulo de compatibilidade seja bom, recomendamos que você revise manualmente as substituições e migre-as para novas APIs no namespace tf.* vez do namespace tf.compat.v1 mais rápido possível.

Por causa das suspensões do módulo TensorFlow 2.x (por exemplo, tf.flags e tf.contrib ), algumas alterações não podem ser contornadas mudando para compat.v1 . A atualização deste código pode exigir o uso de uma biblioteca adicional (por exemplo, absl.flags ) ou a mudança para um pacote em tensorflow / addons .

O restante deste guia demonstra como usar o script de atualização. Embora o script de atualização seja fácil de usar, é altamente recomendável que você use o script como parte do seguinte processo:

  1. Teste de unidade : certifique-se de que o código que você está atualizando tenha um conjunto de testes de unidade com cobertura razoável. Este é o código Python, então a linguagem não o protegerá de muitas classes de erros. Certifique-se também de que qualquer dependência que você já tenha feito upgrade para ser compatível com o TensorFlow 2.0.

  2. Instale o TensorFlow 1.14 : atualize seu TensorFlow para a versão mais recente do TensorFlow 1.x, pelo menos 1.14. Isso inclui a API TensorFlow 2.0 final em tf.compat.v2 .

  3. Teste com 1.14 : Certifique-se de que seus testes de unidade sejam aprovados neste ponto. Você os executará repetidamente durante a atualização, portanto, começar do verde é importante.

  4. Execute o script de atualização : Execute tf_upgrade_v2 em toda a sua árvore de origem, testes incluídos. Isso atualizará seu código para um formato em que ele usa apenas os símbolos disponíveis no TensorFlow 2.0. Os símbolos obsoletos serão acessados ​​com tf.compat.v1 . Eventualmente, isso exigirá atenção manual, mas não imediatamente.

  5. Execute os testes convertidos com o TensorFlow 1.14 : seu código ainda deve funcionar bem no TensorFlow 1.14. Execute seus testes de unidade novamente. Qualquer erro em seus testes aqui significa que há um bug no script de atualização. Por favor, deixe-nos saber .

  6. Verifique se há avisos e erros no relatório de atualização : o script grava um arquivo de relatório que explica todas as conversões que você deve verificar novamente ou qualquer ação manual que você precise realizar. Por exemplo: Quaisquer instâncias restantes de contrib exigirão ação manual para remover. Consulte o RFC para obter mais instruções .

  7. Instale o TensorFlow 2.0 : neste ponto, deve ser seguro mudar para o TensorFlow 2.0

  8. Teste com v1.disable_v2_behavior : v1.disable_v2_behavior novamente seus testes com al v1.disable_v2_behavior() na função principal de testes deve dar os mesmos resultados da execução em 1.14.

  9. Habilitar comportamento V2 : agora que seus testes funcionam usando a API v2, você pode começar a olhar para como ativar o comportamento v2. Dependendo de como seu código foi escrito, isso pode exigir algumas alterações. Consulte o guia de migração para obter detalhes.

Usando o script de atualização

Configurar

Antes de começar, verifique se o TensorlFlow 2.0 está instalado.

import tensorflow as tf

print(tf.__version__)
2.3.0

Clone o repositório git tensorflow / models para que você tenha algum código para testar:

git clone --branch r1.13.0 --depth 1 https://github.com/tensorflow/models
Cloning into 'models'...
remote: Enumerating objects: 2927, done.[K
remote: Counting objects: 100% (2927/2927), done.[K
remote: Compressing objects: 100% (2449/2449), done.[K
remote: Total 2927 (delta 509), reused 2036 (delta 403), pack-reused 0[K
Receiving objects: 100% (2927/2927), 369.04 MiB | 44.65 MiB/s, done.
Resolving deltas: 100% (509/509), done.
Checking out files: 100% (2768/2768), done.

Leia a ajuda

O script deve ser instalado com TensorFlow. Aqui está a ajuda integrada:

tf_upgrade_v2 -h
2020-09-10 01:42:59.274658: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
usage: tf_upgrade_v2 [-h] [--infile INPUT_FILE] [--outfile OUTPUT_FILE]
                     [--intree INPUT_TREE] [--outtree OUTPUT_TREE]
                     [--copyotherfiles COPY_OTHER_FILES] [--inplace]
                     [--no_import_rename] [--no_upgrade_compat_v1_import]
                     [--reportfile REPORT_FILENAME] [--mode {DEFAULT,SAFETY}]
                     [--print_all]

Convert a TensorFlow Python file from 1.x to 2.0

Simple usage:
  tf_upgrade_v2.py --infile foo.py --outfile bar.py
  tf_upgrade_v2.py --infile foo.ipynb --outfile bar.ipynb
  tf_upgrade_v2.py --intree ~/code/old --outtree ~/code/new

optional arguments:
  -h, --help            show this help message and exit
  --infile INPUT_FILE   If converting a single file, the name of the file to
                        convert
  --outfile OUTPUT_FILE
                        If converting a single file, the output filename.
  --intree INPUT_TREE   If converting a whole tree of files, the directory to
                        read from (relative or absolute).
  --outtree OUTPUT_TREE
                        If converting a whole tree of files, the output
                        directory (relative or absolute).
  --copyotherfiles COPY_OTHER_FILES
                        If converting a whole tree of files, whether to copy
                        the other files.
  --inplace             If converting a set of files, whether to allow the
                        conversion to be performed on the input files.
  --no_import_rename    Not to rename import to compat.v2 explicitly.
  --no_upgrade_compat_v1_import
                        If specified, don't upgrade explicit imports of
                        `tensorflow.compat.v1 as tf` to the v2 apis.
                        Otherwise, explicit imports of the form
                        `tensorflow.compat.v1 as tf` will be upgraded.
  --reportfile REPORT_FILENAME
                        The name of the file where the report log is
                        stored.(default: report.txt)
  --mode {DEFAULT,SAFETY}
                        Upgrade script mode. Supported modes: DEFAULT: Perform
                        only straightforward conversions to upgrade to 2.0. In
                        more difficult cases, switch to use compat.v1. SAFETY:
                        Keep 1.* code intact and import compat.v1 module.
  --print_all           Print full log to stdout instead of just printing
                        errors

Exemplo de código TF1

Aqui está um script simples do TensorFlow 1.0:

head -n 65 models/samples/cookbook/regression/custom_regression.py | tail -n 10
# Calculate loss using mean squared error
  average_loss = tf.losses.mean_squared_error(labels, predictions)

  # Pre-made estimators use the total_loss instead of the average,
  # so report total_loss for compatibility.
  batch_size = tf.shape(labels)[0]
  total_loss = tf.to_float(batch_size) * average_loss

  if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = params.get("optimizer", tf.train.AdamOptimizer)

Com o TensorFlow 2.0 instalado, ele não executa:

(cd models/samples/cookbook/regression && python custom_regression.py)
2020-09-10 01:43:01.613673: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
Traceback (most recent call last):
  File "custom_regression.py", line 162, in <module>
    tf.logging.set_verbosity(tf.logging.INFO)
AttributeError: module 'tensorflow' has no attribute 'logging'

Único arquivo

O script de atualização pode ser executado em um único arquivo Python:

!tf_upgrade_v2 \
  --infile models/samples/cookbook/regression/custom_regression.py \
  --outfile /tmp/custom_regression_v2.py
2020-09-10 01:43:03.844314: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
INFO line 38:8: Renamed 'tf.feature_column.input_layer' to 'tf.compat.v1.feature_column.input_layer'
INFO line 43:10: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 46:17: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 57:17: tf.losses.mean_squared_error requires manual check. tf.losses have been replaced with object oriented versions in TF 2.0 and after. The loss function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 57:17: Renamed 'tf.losses.mean_squared_error' to 'tf.compat.v1.losses.mean_squared_error'
INFO line 61:15: Added keywords to args of function 'tf.shape'
INFO line 62:15: Changed tf.to_float call to tf.cast(..., dtype=tf.float32).
INFO line 65:40: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 68:39: Renamed 'tf.train.get_global_step' to 'tf.compat.v1.train.get_global_step'
INFO line 83:9: tf.metrics.root_mean_squared_error requires manual check. tf.metrics have been replaced with object oriented versions in TF 2.0 and after. The metric function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 83:9: Renamed 'tf.metrics.root_mean_squared_error' to 'tf.compat.v1.metrics.root_mean_squared_error'
INFO line 142:23: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 162:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 162:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 163:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 1 files
Detected 0 issues that require attention
--------------------------------------------------------------------------------


Make sure to read the detailed log 'report.txt'

O script imprimirá erros se não conseguir encontrar uma correção para o código.

Árvore de diretório

Projetos típicos, incluindo este exemplo simples, usarão muito mais de um arquivo. Normalmente deseja atualizar um pacote inteiro, então o script também pode ser executado em uma árvore de diretório:

# upgrade the .py files and copy all the other files to the outtree
!tf_upgrade_v2 \
    --intree models/samples/cookbook/regression/ \
    --outtree regression_v2/ \
    --reportfile tree_report.txt
2020-09-10 01:43:06.108169: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
INFO line 82:10: tf.estimator.LinearRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 105:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 105:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 106:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 58:10: tf.estimator.LinearRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 101:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 101:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 102:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
WARNING line 125:15: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.

INFO line 72:10: tf.estimator.DNNRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 96:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 96:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 97:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 38:8: Renamed 'tf.feature_column.input_layer' to 'tf.compat.v1.feature_column.input_layer'
INFO line 43:10: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 46:17: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 57:17: tf.losses.mean_squared_error requires manual check. tf.losses have been replaced with object oriented versions in TF 2.0 and after. The loss function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 57:17: Renamed 'tf.losses.mean_squared_error' to 'tf.compat.v1.losses.mean_squared_error'
INFO line 61:15: Added keywords to args of function 'tf.shape'
INFO line 62:15: Changed tf.to_float call to tf.cast(..., dtype=tf.float32).
INFO line 65:40: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 68:39: Renamed 'tf.train.get_global_step' to 'tf.compat.v1.train.get_global_step'
INFO line 83:9: tf.metrics.root_mean_squared_error requires manual check. tf.metrics have been replaced with object oriented versions in TF 2.0 and after. The metric function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 83:9: Renamed 'tf.metrics.root_mean_squared_error' to 'tf.compat.v1.metrics.root_mean_squared_error'
INFO line 142:23: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 162:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 162:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 163:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 40:7: Renamed 'tf.test.mock' to 'tf.compat.v1.test.mock'
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 7 files
Detected 1 issues that require attention
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
File: models/samples/cookbook/regression/automobile_data.py
--------------------------------------------------------------------------------
models/samples/cookbook/regression/automobile_data.py:125:15: WARNING: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.



Make sure to read the detailed log 'tree_report.txt'

Observe o único aviso sobre a função dataset.make_one_shot_iterator .

Agora o script funciona com o TensorFlow 2.0:

Observe que, por causa do módulo tf.compat.v1 , o script convertido também será executado no TensorFlow 1.14.

(cd regression_v2 && python custom_regression.py 2>&1) | tail
data = raw_dataframe()
  File "/tmpfs/src/temp/site/en/guide/regression_v2/automobile_data.py", line 67, in raw_dataframe
    dtype=COLUMN_TYPES, na_values="?")
  File "/home/kbuilder/.local/lib/python3.6/site-packages/pandas/io/parsers.py", line 686, in read_csv
    return _read(filepath_or_buffer, kwds)
  File "/home/kbuilder/.local/lib/python3.6/site-packages/pandas/io/parsers.py", line 449, in _read
    _validate_names(kwds.get("names", None))
  File "/home/kbuilder/.local/lib/python3.6/site-packages/pandas/io/parsers.py", line 417, in _validate_names
    raise ValueError("Names should be an ordered collection.")
ValueError: Names should be an ordered collection.

Relatório detalhado

O script também relata uma lista de mudanças detalhadas. Neste exemplo, ele encontrou uma transformação possivelmente insegura e incluiu um aviso na parte superior do arquivo:

head -n 20 tree_report.txt
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 7 files
Detected 1 issues that require attention
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
File: models/samples/cookbook/regression/automobile_data.py
--------------------------------------------------------------------------------
models/samples/cookbook/regression/automobile_data.py:125:15: WARNING: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.

================================================================================
Detailed log follows:

================================================================================
================================================================================
Input tree: 'models/samples/cookbook/regression/'
================================================================================
--------------------------------------------------------------------------------
Processing file 'models/samples/cookbook/regression/linear_regression_categorical.py'
 outputting to 'regression_v2/linear_regression_categorical.py'

Observe novamente o único aviso sobre a Dataset.make_one_shot_iterator function .

Em outros casos, a saída explicará o motivo para mudanças não triviais:

%%writefile dropout.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)
Writing dropout.py
!tf_upgrade_v2 \
  --infile dropout.py \
  --outfile dropout_v2.py \
  --reportfile dropout_report.txt > /dev/null
2020-09-10 01:43:10.977249: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
cat dropout_report.txt
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 1 files
Detected 0 issues that require attention
--------------------------------------------------------------------------------
================================================================================
Detailed log follows:

================================================================================
--------------------------------------------------------------------------------
Processing file 'dropout.py'
 outputting to 'dropout_v2.py'
--------------------------------------------------------------------------------

3:4: INFO: Changing keep_prob arg of tf.nn.dropout to rate, and recomputing value.

4:4: INFO: Renaming tf.zeros_like to tf.compat.v1.zeros_like because argument optimize is present. tf.zeros_like no longer takes an optimize argument, and behaves as if optimize=True. This call site specifies something other than optimize=True, so it was converted to compat.v1.
--------------------------------------------------------------------------------

Aqui está o conteúdo do arquivo modificado, observe como o script adiciona nomes de argumento para lidar com argumentos movidos e renomeados:

cat dropout_v2.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), 1 - (0.2))
z = tf.compat.v1.zeros_like(d, optimize=False)

Um projeto maior pode conter alguns erros. Por exemplo, converta o modelo deeplab:

!tf_upgrade_v2 \
    --intree models/research/deeplab \
    --outtree deeplab_v2 \
    --reportfile deeplab_report.txt > /dev/null
2020-09-10 01:43:13.488610: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1

Ele produziu os arquivos de saída:

ls deeplab_v2
README.md   datasets        input_preprocess.py        train.py
__init__.py deeplab_demo.ipynb  local_test.sh          utils
common.py   eval.py         local_test_mobilenetv2.sh  vis.py
common_test.py  export_model.py     model.py
core        g3doc           model_test.py

Mas houve erros. O relatório o ajudará a identificar o que você precisa corrigir antes de ser executado. Aqui estão os três primeiros erros:

cat deeplab_report.txt | grep -i models/research/deeplab | grep -i error | head -n 3
models/research/deeplab/export_model.py:25:7: ERROR: Using member tf.contrib.slim in deprecated module tf.contrib. tf.contrib.slim cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.
models/research/deeplab/eval.py:28:7: ERROR: Using member tf.contrib.slim in deprecated module tf.contrib. tf.contrib.slim cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.
models/research/deeplab/eval.py:146:8: ERROR: Using member tf.contrib.metrics.aggregate_metric_map in deprecated module tf.contrib. tf.contrib.metrics.aggregate_metric_map cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.

Modo "Segurança"

O script de conversão também tem um modo de SAFETY menos invasivo que simplesmente altera as importações para usar o módulo tensorflow.compat.v1 :

cat dropout.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)
tf_upgrade_v2 --mode SAFETY --infile dropout.py --outfile dropout_v2_safe.py > /dev/null
2020-09-10 01:43:17.892207: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
cat dropout_v2_safe.py
import tensorflow.compat.v1 as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)

Como você pode ver, isso não atualiza seu código, mas permite que o código do TensorFlow 1 seja executado no TensorFlow 2

Ressalvas

  • Não atualize partes do seu código manualmente antes de executar este script. Em particular, as funções que tiveram argumentos reordenados como tf.argmax ou tf.batch_to_space fazem com que o script adicione incorretamente argumentos de palavra-chave que mapeiam incorretamente seu código existente.

  • O script assume que tensorflow é importado usando import tensorflow as tf .

  • Este script não reordena argumentos. Em vez disso, o script adiciona argumentos de palavra-chave a funções que têm seus argumentos reordenados.

  • Confira tf2up.ml para uma ferramenta conveniente para atualizar notebooks Jupyter e arquivos Python em um repositório GitHub.

Para relatar bugs de script de atualização ou fazer solicitações de recursos, registre um problema no GitHub . E se você está testando o TensorFlow 2.0, queremos saber mais sobre ele! Junte-se à comunidade TF 2.0 Testing e envie perguntas e discussões para testing@tensorflow.org .