Есть вопрос? Присоединяйтесь к сообществу на форуме TensorFlow. Посетите форум.

Автоматически обновить код до TensorFlow 2

Посмотреть на TensorFlow.org Запускаем в Google Colab Посмотреть исходный код на GitHub Скачать блокнот

TensorFlow 2.0 включает множество изменений API, таких как переупорядочивание аргументов, переименование символов и изменение значений по умолчанию для параметров. Выполнение всех этих модификаций вручную было бы утомительно и чревато ошибками. Чтобы упростить внесение изменений и сделать ваш переход на TF 2.0 как можно более плавным, команда tf_upgrade_v2 утилиту tf_upgrade_v2 которая помогает tf_upgrade_v2 устаревший код на новый API.

Типичное использование выглядит так:

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

Это ускорит процесс обновления за счет преобразования существующих скриптов Python TensorFlow 1.x в TensorFlow 2.0.

Сценарий преобразования максимально автоматизирует, но все же есть синтаксические и стилистические изменения, которые не могут быть выполнены сценарием.

Модули совместимости

Некоторые символы API нельзя обновить, просто заменив строку. Чтобы ваш код по-прежнему поддерживался в TensorFlow 2.0, сценарий обновления включает модуль compat.v1 . Этот модуль заменяет символы TF 1.x, такие как tf.foo эквивалентной ссылкой на tf.compat.v1.foo . Хотя модуль совместимости хорош, мы рекомендуем вам вручную вычитать замены и как можно быстрее перенести их на новые API в пространстве имен tf.* Вместо tf.compat.v1 .

Из-за устаревания модуля TensorFlow 2.x (например, tf.flags и tf.contrib ) некоторые изменения нельзя обойти, переключившись на compat.v1 . Для обновления этого кода может потребоваться использование дополнительной библиотеки (например, absl.flags ) или переключение на пакет в tenorflow / addons .

Остальная часть этого руководства демонстрирует, как использовать сценарий обновления. Хотя сценарий обновления прост в использовании, настоятельно рекомендуется использовать его как часть следующего процесса:

  1. Модульный тест : убедитесь, что в обновляемом коде есть набор модульных тестов с разумным покрытием. Это код Python, поэтому язык не защитит вас от многих классов ошибок. Также убедитесь, что все ваши зависимости уже были обновлены для совместимости с TensorFlow 2.0.

  2. Установите TensorFlow 1.14 : обновите свой TensorFlow до последней версии TensorFlow 1.x, по крайней мере, 1.14. Сюда входит последний API tf.compat.v2 2.0 в tf.compat.v2 .

  3. Test With 1.14 : Убедитесь, что ваши модульные тесты пройдены на этом этапе. Вы будете запускать их несколько раз при обновлении, поэтому важно начинать с зеленого.

  4. Запустите сценарий обновления : запустите tf_upgrade_v2 для всего исходного дерева, включая тесты. Это обновит ваш код до формата, в котором используются только символы, доступные в TensorFlow 2.0. Доступ к устаревшим символам будет осуществляться с помощью tf.compat.v1 . В конечном итоге это потребует ручного вмешательства, но не сразу.

  5. Запустите преобразованные тесты с помощью TensorFlow 1.14 : ваш код по-прежнему должен нормально работать в TensorFlow 1.14. Снова запустите модульные тесты. Любая ошибка в ваших тестах означает ошибку в сценарии обновления. Пожалуйста, дайте нам знать .

  6. Проверьте отчет об обновлении на наличие предупреждений и ошибок : сценарий создает файл отчета, в котором объясняются все преобразования, которые необходимо проверить дважды, или любые действия, которые необходимо предпринять вручную. Например: для удаления любых оставшихся экземпляров contrib потребуется принять меры вручную. Пожалуйста, обратитесь к RFC для получения дополнительных инструкций .

  7. Установите TensorFlow 2.0 : на этом этапе переход на TensorFlow 2.0 должен быть безопасным.

  8. Тест с v1.disable_v2_behavior : повторный запуск ваших тестов с al v1.disable_v2_behavior() в основной функции tests должен дать те же результаты, что и в версии 1.14.

  9. Включение поведения версии 2 : теперь, когда ваши тесты работают с использованием API версии 2, вы можете приступить к изучению включения поведения версии 2. В зависимости от того, как написан ваш код, могут потребоваться некоторые изменения. См. Подробности в руководстве по миграции .

С помощью сценария обновления

Настраивать

Перед началом работы убедитесь, что TensorlFlow 2.0 установлен.

import tensorflow as tf

print(tf.__version__)
2.3.0

Клонируйте репозиторий tenorflow / models git, чтобы у вас был код для тестирования:

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.

Прочтите справку

Скрипт должен быть установлен вместе с TensorFlow. Вот встроенная справка:

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

Пример кода TF1

Вот простой скрипт 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)

С установленным TensorFlow 2.0 он не запускается:

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

Отдельный файл

Сценарий обновления можно запустить для одного файла 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'

Сценарий будет печатать ошибки, если не сможет найти исправления для кода.

Дерево каталогов

Типичные проекты, включая этот простой пример, будут использовать гораздо больше, чем один файл. Обычно требуется обновить весь пакет, поэтому сценарий также можно запустить в дереве каталогов:

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

Обратите внимание на одно предупреждение о функции dataset.make_one_shot_iterator .

Теперь скрипт работает с TensorFlow 2.0:

Обратите внимание, что из-за модуля tf.compat.v1 преобразованный скрипт также будет работать в 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.

Детальный отчет

Скрипт также сообщает список подробных изменений. В этом примере он обнаружил одно возможно небезопасное преобразование и включил предупреждение в верхней части файла:

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'

Dataset.make_one_shot_iterator function раз обратите внимание на одно предупреждение о Dataset.make_one_shot_iterator function .

В других случаях вывод объяснит причину нетривиальных изменений:

%%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.
--------------------------------------------------------------------------------

Вот измененное содержимое файла, обратите внимание, как сценарий добавляет имена аргументов для работы с перемещенными и переименованными аргументами:

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)

В более крупном проекте может быть несколько ошибок. Например, преобразовать модель 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

Он произвел выходные файлы:

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

Но были ошибки. Отчет поможет вам точно определить, что вам нужно исправить, прежде чем это будет запущено. Вот первые три ошибки:

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.

«Безопасный» режим

Скрипт преобразования также имеет менее агрессивный режим SAFETY который просто изменяет импорт для использования модуля 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)

Как видите, это не обновляет ваш код, но позволяет коду TensorFlow 1 работать в TensorFlow 2.

Предостережения

  • Не обновляйте части вашего кода вручную перед запуском этого скрипта. В частности, функции с переупорядоченными аргументами, такими как tf.argmax или tf.batch_to_space приводят к тому, что сценарий неправильно добавляет аргументы ключевого слова, которые не соответствуют существующему коду.

  • Скрипт предполагает, что tensorflow импортируется с использованием import tensorflow as tf .

  • Этот сценарий не меняет порядок аргументов. Вместо этого сценарий добавляет аргументы ключевого слова к функциям, чьи аргументы переупорядочены.

  • Ознакомьтесь с tf2up.ml, чтобы найти удобный инструмент для обновления записных книжек Jupyter и файлов Python в репозитории GitHub.

Чтобы сообщить об ошибках в сценарии обновления или отправить запрос на добавление функций, сообщите о проблеме на GitHub . И если вы тестируете TensorFlow 2.0, мы хотим об этом услышать! Присоединяйтесь к сообществу тестирования TF 2.0 и отправляйте вопросы и обсуждения по адресу testing@tensorflow.org .