TensorFlow2.0 Guide官方教程 学习笔记23 -‘Automatically upgrade code to TensorFlow 2’

本笔记参照TensorFlow Guide官方教程,主要是对‘Automatically upgrade code to TensorFlow 2’教程内容翻译和内容结构编排,原文链接:Automatically upgrade code to TensorFlow 2

目录
一、兼容模块(Compatibility modules)
二、主推升级过程(Recommended upgrade process)
三、使用升级脚本
3.1 设置(Setup)
3.2 阅读帮助(Read the help)
3.3 TF1 代码示例
3.4 单个文件
3.5 目录树(directory tree)
四、详细报告
五、‘安全’模式
六、警告(Caveats)


TensorFlow 2.0包含许多API更改,比如重新排序参数、重命名符合和更改参数的默认值。手动执行所有这些修改将是冗长乏味的,而且容易出错。为了简化这些更改,并尽可能无缝地过渡到TF 2.0, TensorFlow团队创建了tf_upgrade_v2实用工具来帮助将遗留代码过渡到新的API。

	注意:TF1.13及以上版本中‘tf_upgrade_v2’是自动安装的(包括TF 2.0 builds)

典型使用用例如下:

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

它将通过转换现有的TF 1.x脚本到TF 2.0来加速我们的升级过程。
转换脚本尽可能地自动化,但是仍然有一些语法和风格上的变化不能由脚本执行。

一、兼容模块(Compatibility modules)

某些API符号不能简单地通过使用字符串替换来升级。为了确保TensorFlow 2.0仍然支持您的代码,升级脚本包含一个compat.v1模块。此模块替换TF1.x符号,比如tf.foo,替换成等效的tf.compat.v1.foo。虽然兼容性模块很好,但我们建议您手动校对替换并将它们迁移到tf.*命名空间中的新api而不是tf.com .v1命名空间。
因为TF 2.0弃用了一些模块(比如tf.flags和tf.contrib),一些改变不能通过切换到compat.v1来实现。升级此代码可能需要使用额外的库(例如,absl.flags)或切换到tensorflow/addons中的包。

二、推荐的升级过程(Recommended upgrade process)

下面的内容就是演示如何使用升级脚本。虽然升级脚本易于使用,但谷歌强烈建议我们以下过程中使用该脚本:
1.单元测试(Unit Test):确保我们正在升级的代码有一个具有合理覆盖率的单元测试套件。这是Python代码,因此该语言不会保护我们避免许多类错误。另外还要确保我们拥有的任何依赖项已经升级到与TensorFlow2.0兼容。
2.安装TensorFlow 1.14(Install TensorFlow 1.14):升级我们的TensorFlow到TF 1.x的最新版本,至少1.14。这包括‘tf.compat.v2’中的最终TensorFlow 2.0 API。
3.用1.14测试:确保我们的单元测试通过这一项。当你升级时,你会反复运行它们,所以从绿色开始很重要。
4.运行升级脚本:包括测试在内的整个源代码树上运行‘tf_upgrade_v2’。这将把我们的代码升级到只使用TensorFlow 2.0中可用的符号格式。已废弃的符号将通过‘tf.compat.v1’访问。这些最终将需要手工处理,但不是立即处理。
5.用TF 1.14运行转换过的测试:我们的代码仍然需要在1.14版本上运行正常。再次运行我们的单元测试。有任何错误表面升级脚本有漏洞(bug)
6.检查升级报告查看报警和错误:升级脚本会编写一个报告文件,该文件解释了我们需要两遍检查(double-check)的任何转换,或我们需要执行的任何手动操作。例如:任何剩余的‘contrib’实例都需要手动操作才能删除。更多请说明咨询RFC
7.安装TensorFlow 2.0:这个时候转换到TF2.0应该是安全的。
8.用‘v1.disable_v2_behavior’测试:用‘v1.disable_v2_behavior()’再次运行测试,得到的结果应该与1.14版本一样。
9.使能V2行为(Enable V2 Behavior):既然我们的测试在v2版的API中运行有效,我们可以开启v2 行为。基于每个人写代码的方式可能需要一些改动。具体参考Migration guide(笔记21-22)。

三、使用升级脚本

3.1 设置(Setup)

升级之前需确保TF 2.0已经安装

from __future__ import absolute_import, division, print_function, unicode_literals
try:
  import tensorflow.compat.v2 as tf
except Exception:
  pass

tf.enable_v2_behavior()

print(tf.__version__)

克隆‘tensorflow/models’git仓库,这样我们可以直接在上面测试代码:

!git clone --branch r1.13.0 --depth 1 https://github.com/tensorflow/models
Cloning into 'models'...
remote: Enumerating objects: 2927, done.
remote: Counting objects: 100% (2927/2927), done.
remote: Compressing objects: 100% (2447/2447), done.
remote: Total 2927 (delta 512), reused 2068 (delta 405), pack-reused 0
Receiving objects: 100% (2927/2927), 369.04 MiB | 1.72 MiB/s, done.
Resolving deltas: 100% (512/512), done.
Checking out files: 100% (2768/2768), done.

3.2 阅读帮助(Read the help)

应该用TensorFlow安装脚本。下面是构造帮助:

!tf_upgrade_v2 -h
usage: tf_upgrade_v2 [-h] [--infile INPUT_FILE] [--outfile OUTPUT_FILE]
                     [--intree INPUT_TREE] [--outtree OUTPUT_TREE]
                     [--copyotherfiles COPY_OTHER_FILES] [--inplace]
                     [--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.
  --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. Also
                        disable 2.0 behavior to ensure code that requires 1.X
                        behavior continues to work.
  --print_all           Print full log to stdout instead of just printing
                        errors

3.3 TF1 代码示例

下面是一个简单的TF 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)

在TF2.0版本上它无法运行:

!(cd models/samples/cookbook/regression && python custom_regression.py)
Traceback (most recent call last):
  File "custom_regression.py", line 162, in 
    tf.logging.set_verbosity(tf.logging.INFO)
AttributeError: module 'tensorflow' has no attribute 'logging'

3.4 单个文件

升级脚本可以在单个Python文件上运行:

!tf_upgrade_v2 \
  --infile models/samples/cookbook/regression/custom_regression.py \
  --outfile /tmp/custom_regression_v2.py
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'

如果错误无法修复,脚本会打印出来
3.5 目录树(directory tree)

典型的项目,包括这个简单的例子,将使用多个文件。我们通常想要升级整个包,所以脚本也可以在目录树上运行:

# 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
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 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 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'
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 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'
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’函数的警告。

现在我们的脚本可以在TF2.0上运行了

注意:因为有‘tf.compat.v1’模块,转换脚本同样可以在TensorFlow 1.14上运行。

!(cd regression_v2 && python custom_regression.py 2>&1) | tail
I1114 02:27:42.381641 140483167123264 estimator.py:2049] Saving dict for global step 1000: global_step = 1000, loss = 383.16257, rmse = 2.8253412
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 1000: /tmp/tmpii4osvbr/model.ckpt-1000
I1114 02:27:42.424447 140483167123264 estimator.py:2109] Saving 'checkpoint_path' summary for global step 1000: /tmp/tmpii4osvbr/model.ckpt-1000
Tensor("IteratorGetNext:25", shape=(None,), dtype=float64, device=/device:CPU:0)
Tensor("Squeeze:0", shape=(None,), dtype=float32)

********************************************************************************

RMS error for the test set: $2825

四、详细报告

该脚本还报告详细的更改列表。在这个例子中,它发现了一个可能不安全的转换,并在文件的顶部包括一个警告:

!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/custom_regression.py'
 outputting to 'regression_v2/custom_regression.py'

再次注意关于‘Dataset.make_one_shot_iterator’功能的警告。

其它场景下,输出将解释非琐碎变化(not-trivial changes)的原因:

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

它产生的输入文件为:

!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/vis.py:31: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.

五、‘安全’模式

转换脚本也有一个安全模式,只简单地更改导入(imports)以使用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
!cat dropout_v2_safe.py
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

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

从上可以看到,它没有升级代码,但是可以运行TF1代码在TF2上运行。

六、警告(Caveats)

  • 在运行此脚本前不要手动改动代码。特别是像‘tf.argmax’和‘tf.batch_to_space’这种具有重新排序参数的函数,那样会导致脚本错误地添加关键字参数,从而错误地映射到现有代码。
  • 脚本假设‘TensorFlow’按照‘import TensorFlow as tf’导入的
  • 此脚本没有重新排序参数。相反,它会添加关键字参数给已经把参数重新排序的函数当中去。
  • tf2up.ml提供了一个方便的工具用来升级Jupyter notebook和GitHub仓库中的Python文件。

你可能感兴趣的:(TensorFlow学习笔记)