自动重写 TF 1.x 和 compat.v1 API 符号

在 TensorFlow.org 上查看 在 Google Colab 中运行 在 GitHub 上查看源代码 下载笔记本

TensorFlow 2.x 包含许多来自 TF 1.x 和 tf.compat.v1 API 的 API 更改,例如重新排序参数、重命名符号以及更改参数的默认值。手动执行所有这些修改将非常繁琐且容易出错。为了简化这些更改,并使您尽可能无缝地过渡到 TF 2.x,TensorFlow 团队创建了 tf_upgrade_v2 实用程序来帮助将旧代码迁移到新的 API。

典型用法如下

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

它将通过将现有的 TensorFlow 1.x Python 脚本转换为 TensorFlow 2.x 来加速您的升级过程。

转换脚本自动执行了许多机械 API 转换,但许多 API 无法自动迁移。它也无法完全使您的代码与 TF2 行为和 API 兼容。因此,它只是您迁移旅程的一部分。

兼容性模块

某些 API 符号无法仅通过使用字符串替换来升级。无法自动升级的符号将映射到它们在 compat.v1 模块中的位置。此模块将 TF 1.x 符号(如 tf.foo)替换为等效的 tf.compat.v1.foo 引用。如果您已经通过 import tensorflow.compat.v1 as tf 导入 TF 来使用 compat.v1 API,则 tf_upgrade_v2 脚本将尝试将这些用法尽可能转换为非兼容 API。请注意,虽然某些 compat.v1 API 与 TF2.x 行为兼容,但许多 API 不兼容。因此,建议您尽快手动校对替换并将其迁移到 tf.* 命名空间中的新 API,而不是 tf.compat.v1 命名空间。

由于 TensorFlow 2.x 模块已弃用(例如,tf.flagstf.contrib),因此某些更改无法通过切换到 compat.v1 来解决。升级此代码可能需要使用其他库(例如,absl.flags)或切换到 tensorflow/addons 中的包。

本指南的其余部分演示了如何使用符号重写脚本。虽然该脚本易于使用,但强烈建议您将该脚本用作以下流程的一部分

  1. 单元测试:确保您要升级的代码具有覆盖范围合理的单元测试套件。这是 Python 代码,因此语言不会保护您免受许多错误类别。还要确保您拥有的任何依赖项都已升级为与 TensorFlow 2.x 兼容。

  2. 安装 TensorFlow 1.15:将您的 TensorFlow 升级到最新的 TensorFlow 1.x 版本,至少为 1.15。这包括 tf.compat.v2 中的最终 TensorFlow 2.0 API。

  3. 使用 1.15 测试:确保您的单元测试在此阶段通过。您将在升级时反复运行它们,因此从绿色开始很重要。

  4. 运行升级脚本:在您的整个源代码树(包括测试)上运行 tf_upgrade_v2。这将把您的代码升级到仅使用 TensorFlow 2.0 中可用的符号的格式。已弃用的符号将使用 tf.compat.v1 访问。这些最终将需要手动操作,但不是立即。

  5. 使用 TensorFlow 1.15 运行转换后的测试:您的代码应该仍然可以在 TensorFlow 1.15 中正常运行。再次运行您的单元测试。如果您的测试在此处出现任何错误,则意味着升级脚本中存在错误。请告诉我们

  6. 检查升级报告以获取警告和错误:该脚本会写入一个报告文件,解释您应该仔细检查的任何转换,或您需要采取的任何手动操作。例如:任何剩余的 contrib 实例都需要手动操作才能删除。请咨询RFC 以获取更多说明

  7. 安装 TensorFlow 2.x:此时,即使您使用的是旧行为,也应该可以安全地切换到 TensorFlow 2.x 二进制文件

  8. 使用 v1.disable_v2_behavior 测试:在测试的主函数中使用 v1.disable_v2_behavior() 重新运行您的测试应该与在 1.15 下运行产生相同的结果。

  9. 启用 V2 行为:现在您的测试可以使用 TF2 二进制文件,您可以开始迁移您的代码,避免使用 tf.estimator,只使用支持的 TF2 行为(不禁用 TF2 行为)。有关详细信息,请参阅 迁移指南

使用符号重写 tf_upgrade_v2 脚本

设置

在开始之前,请确保已安装 TensorFlow 2.x。

import tensorflow as tf

print(tf.__version__)

克隆 tensorflow/models git 仓库,以便您有一些代码可以测试。

git clone --branch r1.13.0 --depth 1 https://github.com/tensorflow/models

阅读帮助

该脚本应与 TensorFlow 一起安装。以下是内置帮助

tf_upgrade_v2 -h

示例 TF1 代码

这是一个简单的 TensorFlow 1.0 脚本

head -n 65 models/samples/cookbook/regression/custom_regression.py | tail -n 10

安装了 TensorFlow 2.x 后,它无法运行

(cd models/samples/cookbook/regression && python custom_regression.py)

单个文件

该脚本可以在单个 Python 文件上运行

!tf_upgrade_v2 \
  --infile models/samples/cookbook/regression/custom_regression.py \
  --outfile /tmp/custom_regression_v2.py

如果脚本无法找到代码的修复方法,它将打印错误。

目录树

典型的项目(包括这个简单的示例)将使用不止一个文件。通常希望更新整个包,因此该脚本也可以在目录树上运行

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

请注意有关 dataset.make_one_shot_iterator 函数的一个警告。

现在该脚本可以在 TensorFlow 2.x 中运行

请注意,由于 tf.compat.v1 模块包含在 TF 1.15 中,因此转换后的脚本也可以在 TensorFlow 1.15 中运行。

(cd regression_v2 && python custom_regression.py 2>&1) | tail

详细报告

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

head -n 20 tree_report.txt

再次注意有关 Dataset.make_one_shot_iterator 函数的一个警告。

在其他情况下,输出将解释非平凡更改的原因

%%writefile 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 \
  --infile dropout.py \
  --outfile dropout_v2.py \
  --reportfile dropout_report.txt > /dev/null
cat dropout_report.txt

以下是修改后的文件内容,请注意脚本如何添加参数名称来处理移动和重命名的参数

cat dropout_v2.py

一个更大的项目可能包含一些错误。例如,转换 deeplab 模型

!tf_upgrade_v2 \
    --intree models/research/deeplab \
    --outtree deeplab_v2 \
    --reportfile deeplab_report.txt > /dev/null

它生成了输出文件

ls deeplab_v2

但存在错误。该报告将帮助您确定在运行之前需要修复的内容。以下是前三个错误

cat deeplab_report.txt | grep -i models/research/deeplab | grep -i error | head -n 3

"安全" 模式

转换脚本还具有侵入性较小的 SAFETY 模式,它只是将导入更改为使用 tensorflow.compat.v1 模块

cat dropout.py
tf_upgrade_v2 --mode SAFETY --infile dropout.py --outfile dropout_v2_safe.py > /dev/null
cat dropout_v2_safe.py

如您所见,这不会升级您的代码,但确实允许 TensorFlow 1 代码针对 TensorFlow 2 二进制文件运行。请注意,这并不意味着您的代码正在运行支持的 TF 2.x 行为!

注意事项

  • 在运行此脚本之前,请勿手动更新代码的某些部分。特别是,参数顺序已更改的函数(如 tf.math.argmaxtf.batch_to_space)会导致脚本错误地添加关键字参数,这些参数与您现有的代码不匹配。

  • 该脚本假设 tensorflow 是使用 import tensorflow as tfimport tensorflow.compat.v1 as tf 导入的。

  • 此脚本不会重新排序参数。相反,该脚本会为参数顺序已更改的函数添加关键字参数。

  • 查看 tf2up.ml,这是一个方便的工具,用于升级 GitHub 存储库中的 Jupyter 笔记本和 Python 文件。

要报告升级脚本错误或提出功能请求,请在 GitHub 上提交问题。