{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "id": "6bYaCABobL5q" }, "outputs": [], "source": [ "##### Copyright 2018 The TensorFlow Authors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "id": "FlUw7tSKbtg4", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "08OTcmxgqkc2" }, "source": [ "# 自动将代码升级到 TensorFlow 2\n", "\n", "
\n",
" ![]() | \n",
" \n",
" ![]() | \n",
" \n",
" ![]() | \n",
" \n",
" ![]() | \n",
"
tf_upgrade_v2 \\\n", " --intree my_project/ \\\n", " --outtree my_project_v2/ \\\n", " --reportfile report.txt\n", "\n", "\n", "将现有 TensorFlow 1.x Python 脚本转换为 TensorFlow 2.0 脚本可以加快升级流程。\n", "\n", "转换脚本会尽可能实现自动化处理,但仍有一些语法和样式变更无法通过脚本执行转换。" ] }, { "cell_type": "markdown", "metadata": { "id": "gP9v2vgptdfi" }, "source": [ "## 兼容性模块\n", "\n", "某些 API 符号无法通过简单的字符串替换进行升级。为了确保代码在 TensorFlow 2.0 中仍受支持,升级脚本包含了一个 `compat.v1` 模块。该模块可将 TF 1.x 符号(如 `tf.foo`)替换为等效的 `tf.compat.v1.foo` 引用。虽然该兼容性模块效果不错,但我们仍建议人工校对替换,并尽快将代码迁移到 `tf.*` 命名空间(而不是 `tf.compat.v1` 命名空间)中的新 API。\n", "\n", "由于 TensorFlow 2.x 模块弃用(例如,`tf.flags` 和 `tf.contrib`),切换到 `compat.v1` 无法解决某些更改。升级此代码可能需要其他库(例如,[`absl.flags`](https://github.com/abseil/abseil-py))或切换到 [tensorflow/addons](http://www.github.com/tensorflow/addons) 中的软件包。\n" ] }, { "cell_type": "markdown", "metadata": { "id": "s78bbfjkXYb7" }, "source": [ "## 推荐的升级流程\n", "\n", "本指南的剩余部分演示如何使用升级脚本。虽然升级脚本的使用非常简单,我们仍强烈建议在以下流程中使用脚本:\n", "\n", "1. **单元测试**:确保要升级的代码包含具有合理覆盖范围的单元测试套件。这是 Python 代码,该语言并不会帮助您避免各种类型的错误。同时为了与 TensorFlow 2.0 兼容,还要确保升级所有依赖项。\n", "\n", "2. **安装 TensorFlow 1.14**:将 TensorFlow 升级到最新的 TensorFlow 1.x 版本(最低为 1.14 版本)。其中包括 `tf.compat.v2` 中的最终 TensorFlow 2.0 API。\n", "\n", "3. **通过 1.14 版本进行测试**:确保此时可通过单元测试。在升级过程中,您将反复进行测试,因此,从无错误的代码开始非常重要。\n", "\n", "4. **运行升级脚本**:对整个源代码树运行 `tf_upgrade_v2`(已包含测试)。这样可将代码升级为仅使用 TensorFlow 2.0 中所提供的符号的格式。被弃用的符号将通过 `tf.compat.v1` 进行访问。最终需要人工检查这些升级,但不是现在。\n", "\n", "5. **通过 TensorFlow 1.14 运行转换的测试**:代码在 TensorFlow 1.14 中应该仍可以正常运行。再次运行单元测试。测试在此时产生任何错误都意味着升级脚本存在错误。[请通知我们](https://github.com/tensorflow/tensorflow/issues)。\n", "\n", "6. **检查更新报告中的警告和错误**:该脚本会编写一个对需要复查的转换或需要执行的人工操作进行解释的报告文件。例如:contrib 的所有剩余实例需要通过人工操作删除。请查阅 [RFC 中的详细说明](https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md)。\n", "\n", "7. **安装 TensorFlow 2.0**:此时应该可以安全切换到 TensorFlow 2.0\n", "\n", "8. **使用 `v1.disable_v2_behavior` 进行测试**:使用测试主函数中的 `v1.disable_v2_behavior()` 重新运行测试产生的结果应与在 1.14 下运行时产生的结果相同。\n", "\n", "9. **启用 V2 行为**:现在,使用 v2 API 已经成功通过了测试,不妨开始考虑启用 v2 行为。这可能需要执行一些更改,具体取决于代码编写方式。有关详细信息,请参阅[迁移指南](migrate.ipynb)。" ] }, { "cell_type": "markdown", "metadata": { "id": "6pwSAQEwvscP" }, "source": [ "## 使用升级脚本\n" ] }, { "cell_type": "markdown", "metadata": { "id": "I9NCvDt5GwX4" }, "source": [ "### 设置\n", "\n", "开始之前,请确保已安装 TensorlFlow 2.0。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "DWVYbvi1WCeY", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "import tensorflow as tf\n", "\n", "print(tf.__version__)" ] }, { "cell_type": "markdown", "metadata": { "id": "Ycy3B5PNGutU" }, "source": [ "克隆 [tensorflow/models](https://github.com/tensorflow/models) git 仓库,以便获得一些要测试的代码:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "jyckoWyAZEhZ", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!git clone --branch r1.13.0 --depth 1 https://github.com/tensorflow/models" ] }, { "cell_type": "markdown", "metadata": { "id": "wfHOhbkgvrKr" }, "source": [ "### 读取帮助\n", "\n", "脚本应当随 TensorFlow 安装。下面是内置帮助命令:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "m2GF-tlntqTQ", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!tf_upgrade_v2 -h" ] }, { "cell_type": "markdown", "metadata": { "id": "se9Leqjm1CZR" }, "source": [ "### TF1 代码示例" ] }, { "cell_type": "markdown", "metadata": { "id": "whD5i36s1SuM" }, "source": [ "下面是一个简单的 TensorFlow 1.0 脚本示例:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "mhGbYQ9HwbeU", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!head -n 65 models/samples/cookbook/regression/custom_regression.py | tail -n 10" ] }, { "cell_type": "markdown", "metadata": { "id": "UGO7xSyL89wX" }, "source": [ "对于安装的 TensorFlow 2.0,它不会运行:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "TD7fFphX8_qE", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!(cd models/samples/cookbook/regression && python custom_regression.py)" ] }, { "cell_type": "markdown", "metadata": { "id": "iZZHu0H0wLRJ" }, "source": [ "### 单个文件\n", "\n", "升级脚本可以在单个 Python 文件上运行:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "xIBZVEjkqkc5", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!tf_upgrade_v2 \\\n", " --infile models/samples/cookbook/regression/custom_regression.py \\\n", " --outfile /tmp/custom_regression_v2.py" ] }, { "cell_type": "markdown", "metadata": { "id": "L9X2lxzqqkc9" }, "source": [ "如果无法找到解决代码问题的方法,该脚本会打印错误消息。 " ] }, { "cell_type": "markdown", "metadata": { "id": "r7zpuE1vWSlL" }, "source": [ "### 目录树" ] }, { "cell_type": "markdown", "metadata": { "id": "2q7Gtuu8SdIC" }, "source": [ "典型项目(包括下面的简单示例)会使用远不止一个文件。通常需要升级整个软件包,所以该脚本也可以在目录树上运行:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "XGqcdkAPqkc-", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "# upgrade the .py files and copy all the other files to the outtree\n", "!tf_upgrade_v2 \\\n", " --intree models/samples/cookbook/regression/ \\\n", " --outtree regression_v2/ \\\n", " --reportfile tree_report.txt" ] }, { "cell_type": "markdown", "metadata": { "id": "2S4j7sqbSowC" }, "source": [ "注意关于 `dataset.make_one_shot_iterator` 函数的一条警告。\n", "\n", "现在,对于 TensorFlow 2.0,该脚本已经可以发挥作用:\n", "\n", "请注意,凭借 `tf.compat.v1` 模块,转换的脚本在 TensorFlow 1.14 中也可以运行。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "vh0cmW3y1tX9", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!(cd regression_v2 && python custom_regression.py 2>&1) | tail" ] }, { "cell_type": "markdown", "metadata": { "id": "4EgZGGkdqkdC" }, "source": [ "## 详细报告\n", "\n", "该脚本还会报告一个详细更改列表。在本例中,它发现了一个可能不安全的转换,因此在文件顶部包含了一条警告: " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "CtHaZbVaNMGV", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!head -n 20 tree_report.txt" ] }, { "cell_type": "markdown", "metadata": { "id": "1-UIFXP3cFSa" }, "source": [ "再次注意关于 `Dataset.make_one_shot_iterator` 函数的一条警告。" ] }, { "cell_type": "markdown", "metadata": { "id": "oxQeYS1TN-jv" }, "source": [ "在其他情况下,对于非常用更改,输出会解释原因:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "WQs9kEvVN9th", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "%%writefile dropout.py\n", "import tensorflow as tf\n", "\n", "d = tf.nn.dropout(tf.range(10), 0.2)\n", "z = tf.zeros_like(d, optimize=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "7uOkacZsO3XX", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!tf_upgrade_v2 \\\n", " --infile dropout.py \\\n", " --outfile dropout_v2.py \\\n", " --reportfile dropout_report.txt > /dev/null" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "m-J82-scPMGl", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!cat dropout_report.txt" ] }, { "cell_type": "markdown", "metadata": { "id": "DOOLN21nTGSS" }, "source": [ "以下是经过修改的文件内容,请注意脚本如何通过添加参数名来处理移动和重命名的参数:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "SrYcJk9-TFlU", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!cat dropout_v2.py" ] }, { "cell_type": "markdown", "metadata": { "id": "wI_sVNp_b4C4" }, "source": [ "更大的项目可能会包含一些错误,例如转换 DeepLab 模型:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "uzuY-bOvYBS7", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!tf_upgrade_v2 \\\n", " --intree models/research/deeplab \\\n", " --outtree deeplab_v2 \\\n", " --reportfile deeplab_report.txt > /dev/null" ] }, { "cell_type": "markdown", "metadata": { "id": "FLhw3fm8drae" }, "source": [ "它会生成输出文件:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "4YYLRxWJdSvQ", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!ls deeplab_v2" ] }, { "cell_type": "markdown", "metadata": { "id": "qtTC-cAZdEBy" }, "source": [ "但是其中包含错误。该报告会帮助您找到确保代码可以正常运行所需要解决的错误。下面是前三个错误:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "UVTNOohlcyVZ", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!cat deeplab_report.txt | grep -i models/research/deeplab | grep -i error | head -n 3" ] }, { "cell_type": "markdown", "metadata": { "id": "gGBeDaFVRJ5l" }, "source": [ "## “安全”模式" ] }, { "cell_type": "markdown", "metadata": { "id": "BnfCxB7SVtTO" }, "source": [ "该转换脚本还有一种介入度相对较低的 `SAFETY` 模式。在此模式下,只需更改导入来使用 `tensorflow.compat.v1` 模块:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "XdaVXCPWQCC5", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!cat dropout.py" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "c0tvRJLGRYEb", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!tf_upgrade_v2 --mode SAFETY --infile dropout.py --outfile dropout_v2_safe.py > /dev/null" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "91suN2RaRfIV", "vscode": { "languageId": "python" } }, "outputs": [], "source": [ "!cat dropout_v2_safe.py" ] }, { "cell_type": "markdown", "metadata": { "id": "EOzTF7xbZqqW" }, "source": [ "如您所见,这不会升级代码,但允许 TensorFlow 1 代码在 TensorFlow 2 中运行" ] }, { "cell_type": "markdown", "metadata": { "id": "jGfXVApkqkdG" }, "source": [ "## 注意事项\n", "\n", "- 在运行此脚本之前,不要手动更新代码的某些部分。尤其是更改了参数顺序的函数(如 `tf.argmax` 或 `tf.batch_to_space`),否则会导致代码无法正确添加与现有代码匹配的关键字参数。\n", "\n", "- 该脚本假定使用 `import tensorflow as tf` 导入 `tensorflow`。\n", "\n", "- 该脚本不会更改参数顺序,但是会将关键字参数添加到本身已更改参数顺序的函数。\n", "\n", "- 请查阅 [tf2up.ml](https://github.com/lc0/tf2up),找到一款方便的工具来升级 GitHub 仓库中的 Jupyter 笔记本和 Python 文件。\n", "\n", "要报告升级脚本错误或提出功能请求,请在 [GitHub](https://github.com/tensorflow/tensorflow/issues) 上提交问题。如果您在测试 TensorFlow 2.0,我们非常希望了解您的反馈意见!请加入 [TF 2.0 测试社区](https://groups.google.com/a/tensorflow.org/forum/#!forum/testing),将您的问题和讨论发送到 [testing@tensorflow.org](mailto:testing@tensorflow.org)。" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "upgrade.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 0 }