{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.2.0\n", "sys.version_info(major=3, minor=6, micro=9, releaselevel='final', serial=0)\n", "matplotlib 3.3.4\n", "numpy 1.19.5\n", "pandas 1.1.5\n", "sklearn 0.24.2\n", "tensorflow 2.2.0\n", "tensorflow.keras 2.3.0-tf\n" ] } ], "source": [ "import matplotlib as mpl\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import numpy as np\n", "import sklearn\n", "import pandas as pd\n", "import os\n", "import sys\n", "import time\n", "import tensorflow as tf\n", "\n", "from tensorflow import keras\n", "\n", "print(tf.__version__)\n", "print(sys.version_info)\n", "for module in mpl, np, pd, sklearn, tf, keras:\n", " print(module.__name__, module.__version__)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(-0.95021296, shape=(), dtype=float32)\n", "tf.Tensor([-0.95021296 -0.917915 ], shape=(2,), dtype=float32)\n", "tf.Tensor(-0.95021296, shape=(), dtype=float32)\n", "tf.Tensor([-0.95021296 -0.917915 ], shape=(2,), dtype=float32)\n", "True\n", "\n", "\n" ] } ], "source": [ "# tf.function and auto-graph.\n", "#自己实现一下elu激活函数,如果scale不为1,那就是selu\n", "def scaled_elu(z, scale=1.0, alpha=1.0):\n", " # z >= 0 ? scale * z : scale * alpha * tf.nn.elu(z)\n", " is_positive = tf.greater_equal(z, 0.0)\n", "# return scale * tf.where(is_positive, z, alpha * tf.nn.elu(z))\n", " return scale * tf.where(is_positive, z, alpha * (tf.math.exp(z)-1))\n", "\n", "#运行一下,这还是py函数\n", "print(scaled_elu(tf.constant(-3.)))\n", "print(scaled_elu(tf.constant([-3., -2.5])))\n", "\n", "#把py实现的函数变为图实现的函数\n", "#scaled_elu_tf就是图\n", "scaled_elu_tf = tf.function(scaled_elu)\n", "print(scaled_elu_tf(tf.constant(-3.)))\n", "print(scaled_elu_tf(tf.constant([-3., -2.5])))\n", "\n", "#可以通过这种方式找回原来的py函数\n", "print(scaled_elu_tf.python_function is scaled_elu)\n", "print(scaled_elu)\n", "print(scaled_elu_tf)#tf的函数的执行效率比较高" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.03 s ± 25.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n", "868 ms ± 6.27 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "#我们来测试一下性能,100万个数\n", "%timeit scaled_elu(tf.random.normal((10000, 10000)))\n", "%timeit scaled_elu_tf(tf.random.normal((10000, 10000)))" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "tf.Tensor(1.9999981, shape=(), dtype=float32)\n" ] } ], "source": [ "# 1 + 1/2 + 1/2^2 + ... + 1/2^n\n", "#加了@tf.function装饰后就变为图结果,但是输入类型上不会有变化\n", "@tf.function\n", "def converge_to_2(n_iters):\n", " total = tf.constant(0.)\n", " increment = tf.constant(1.)\n", " for _ in range(n_iters):\n", " total += increment\n", " increment /= 2.0\n", " return total\n", "print(converge_to_2)\n", "print(converge_to_2(20))" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "#如何看tf的图的代码\n", "def display_tf_code(func):\n", " code = tf.autograph.to_code(func)\n", " from IPython.display import display, Markdown\n", " display(Markdown('```python\\n{}\\n```'.format(code)))" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "```python\n", "def tf__scaled_elu(z, scale=None, alpha=None):\n", " do_return = False\n", " retval_ = ag__.UndefinedReturnValue()\n", " with ag__.FunctionScope('scaled_elu', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:\n", " is_positive = ag__.converted_call(tf.greater_equal, (z, 0.0), None, fscope)\n", " try:\n", " do_return = True\n", " retval_ = fscope.mark_return_value((scale * ag__.converted_call(tf.where, (is_positive, z, (alpha * (ag__.converted_call(tf.math.exp, (z,), None, fscope) - 1))), None, fscope)))\n", " except:\n", " do_return = False\n", " raise\n", " (do_return,)\n", " return ag__.retval(retval_)\n", "\n", "```" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#传普通py函数,返回的是tf图的代码\n", "display_tf_code(scaled_elu)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "```python\n", "def tf__converge_to_2(n_iters):\n", " do_return = False\n", " retval_ = ag__.UndefinedReturnValue()\n", " with ag__.FunctionScope('converge_to_2', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:\n", " total = ag__.converted_call(tf.constant, (0.0,), None, fscope)\n", " increment = ag__.converted_call(tf.constant, (1.0,), None, fscope)\n", "\n", " def get_state():\n", " return (total, increment)\n", "\n", " def set_state(loop_vars):\n", " nonlocal total, increment\n", " (total, increment) = loop_vars\n", "\n", " def loop_body(itr):\n", " nonlocal total, increment\n", " _ = itr\n", " total += increment\n", " increment /= 2.0\n", " ag__.for_stmt(ag__.converted_call(range, (n_iters,), None, fscope), None, loop_body, get_state, set_state, ('total', 'increment'), {})\n", " try:\n", " do_return = True\n", " retval_ = fscope.mark_return_value(total)\n", " except:\n", " do_return = False\n", " raise\n", " (do_return,)\n", " return ag__.retval(retval_)\n", "\n", "```" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "#这个的前提是去除converge_to_2的装饰\n", "# 因为converge_to_2有@tf.function标注,去掉应该就没问题了。to_code函数的输入是module,\n", "# class, method, function, traceback, frame, or code object。不能是tf function.\n", "display_tf_code(converge_to_2.python_function)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tf.Tensor(21.0, shape=(), dtype=float32)\n" ] } ], "source": [ "#tf要把变量定义在函数外面,不能放里边\n", "var = tf.Variable(0.)\n", "\n", "@tf.function\n", "def add_21():\n", " return var.assign_add(21) # += \n", "\n", "print(add_21())" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python inputs incompatible with input_signature:\n", " inputs: (\n", " tf.Tensor([1. 2. 3.], shape=(3,), dtype=float32))\n", " input_signature: (\n", " TensorSpec(shape=(None,), dtype=tf.int32, name='x'))\n", "--------------------------------------------------\n", "tf.Tensor([ 1 8 27], shape=(3,), dtype=int32)\n", "\n" ] } ], "source": [ "#cube计算立方,py是泛型设计,我们通过input_signature加类型限制可以防止调错\n", "# @tf.function(input_signature=[tf.TensorSpec([None], tf.int32, name='x')])\n", "@tf.function\n", "def cube(z):\n", " return tf.pow(z, 3)\n", "\n", "try:\n", " print(cube(tf.constant([1., 2., 3.])))\n", "except ValueError as ex:\n", " print(ex)\n", "\n", "print('-'*50)\n", "#这行没问题\n", "print(cube(tf.constant([1, 2, 3])))\n", "print(cube)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "ename": "ValueError", "evalue": "invalid literal for int() with base 10: 'abc'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'abc'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'abc'" ] } ], "source": [ "int('abc')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "tf.Tensor([ 1 8 27], shape=(3,), dtype=int32)\n" ] } ], "source": [ "# @tf.function py func -> tf graph\n", "# get_concrete_function -> 给tf.function add input signature -> SavedModel\n", "\n", "cube_func_int32 = cube.get_concrete_function(\n", " tf.TensorSpec([None], tf.int32))\n", "print(cube_func_int32)\n", "print(cube)\n", "\n", "try:\n", " print(cube_func_int32(tf.constant([1, 2, 3])))\n", "except Exception as ex:\n", " print(ex)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "True\n" ] } ], "source": [ "#我们只要看原来函数和新生成的是否一致\n", "# print(cube_func_int32 is cube.get_concrete_function())\n", "print(cube.get_concrete_function(\n", " tf.constant([1, 2, 3])))\n", "print(cube_func_int32)\n", "print(cube_func_int32 is cube.get_concrete_function(\n", " tf.constant([1, 2, 3])))" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(cube_func_int32)\n", "cube_func_int32.graph" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[,\n", " ,\n", " ,\n", " ]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#看下图定义都有哪些操作,了解即可\n", "cube_func_int32.graph.get_operations()" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "name: \"x\"\n", "op: \"Placeholder\"\n", "attr {\n", " key: \"_user_specified_name\"\n", " value {\n", " s: \"x\"\n", " }\n", "}\n", "attr {\n", " key: \"dtype\"\n", " value {\n", " type: DT_INT32\n", " }\n", "}\n", "attr {\n", " key: \"shape\"\n", " value {\n", " shape {\n", " dim {\n", " size: -1\n", " }\n", " }\n", " }\n", "}\n", "\n" ] } ], "source": [ "pow_op = cube_func_int32.graph.get_operations()[0]\n", "print(pow_op)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n", "--------------------------------------------------\n", "[]\n" ] } ], "source": [ "print(list(pow_op.inputs))\n", "print('-'*50)\n", "print(list(pow_op.outputs))\n" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#Placeholder用来放输入的地方,2.0中不需要,图中依然保留了\n", "cube_func_int32.graph.get_operation_by_name(\"z\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cube_func_int32.graph.get_tensor_by_name(\"z:0\")" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "node {\n", " name: \"z\"\n", " op: \"Placeholder\"\n", " attr {\n", " key: \"_user_specified_name\"\n", " value {\n", " s: \"z\"\n", " }\n", " }\n", " attr {\n", " key: \"dtype\"\n", " value {\n", " type: DT_INT32\n", " }\n", " }\n", " attr {\n", " key: \"shape\"\n", " value {\n", " shape {\n", " dim {\n", " size: -1\n", " }\n", " }\n", " }\n", " }\n", "}\n", "node {\n", " name: \"Pow/y\"\n", " op: \"Const\"\n", " attr {\n", " key: \"dtype\"\n", " value {\n", " type: DT_INT32\n", " }\n", " }\n", " attr {\n", " key: \"value\"\n", " value {\n", " tensor {\n", " dtype: DT_INT32\n", " tensor_shape {\n", " }\n", " int_val: 3\n", " }\n", " }\n", " }\n", "}\n", "node {\n", " name: \"Pow\"\n", " op: \"Pow\"\n", " input: \"z\"\n", " input: \"Pow/y\"\n", " attr {\n", " key: \"T\"\n", " value {\n", " type: DT_INT32\n", " }\n", " }\n", "}\n", "node {\n", " name: \"Identity\"\n", " op: \"Identity\"\n", " input: \"Pow\"\n", " attr {\n", " key: \"T\"\n", " value {\n", " type: DT_INT32\n", " }\n", " }\n", "}\n", "versions {\n", " producer: 175\n", "}" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#打印出来看看图信息\n", "cube_func_int32.graph.as_graph_def()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.9" } }, "nbformat": 4, "nbformat_minor": 2 }