| @@ -0,0 +1,660 @@ | |||
| { | |||
| "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", | |||
| "<function scaled_elu at 0x7f971c419268>\n", | |||
| "<tensorflow.python.eager.def_function.Function object at 0x7f971c408e48>\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": [ | |||
| "<tensorflow.python.eager.def_function.Function object at 0x7f7f1051d780>\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": [ | |||
| "<IPython.core.display.Markdown object>" | |||
| ] | |||
| }, | |||
| "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": [ | |||
| "<IPython.core.display.Markdown object>" | |||
| ] | |||
| }, | |||
| "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", | |||
| "<tensorflow.python.eager.def_function.Function object at 0x7f7e3ef13fd0>\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<ipython-input-13-1e11daa61250>\u001b[0m in \u001b[0;36m<module>\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": [ | |||
| "<tensorflow.python.eager.function.ConcreteFunction object at 0x7f7edb682e48>\n", | |||
| "<tensorflow.python.eager.def_function.Function object at 0x7f7e3ef13fd0>\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": [ | |||
| "<tensorflow.python.eager.function.ConcreteFunction object at 0x7f7edb682e48>\n", | |||
| "<tensorflow.python.eager.function.ConcreteFunction object at 0x7f7edb682e48>\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": [ | |||
| "<tensorflow.python.eager.function.ConcreteFunction object at 0x7f7edb682e48>\n" | |||
| ] | |||
| }, | |||
| { | |||
| "data": { | |||
| "text/plain": [ | |||
| "<tensorflow.python.framework.func_graph.FuncGraph at 0x7f7e3ef7bef0>" | |||
| ] | |||
| }, | |||
| "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": [ | |||
| "[<tf.Operation 'x' type=Placeholder>,\n", | |||
| " <tf.Operation 'Pow/y' type=Const>,\n", | |||
| " <tf.Operation 'Pow' type=Pow>,\n", | |||
| " <tf.Operation 'Identity' type=Identity>]" | |||
| ] | |||
| }, | |||
| "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", | |||
| "[<tf.Tensor 'z:0' shape=(None,) dtype=int32>]\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": [ | |||
| "<tf.Operation 'z' type=Placeholder>" | |||
| ] | |||
| }, | |||
| "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": [ | |||
| "<tf.Tensor 'z:0' shape=(None,) dtype=int32>" | |||
| ] | |||
| }, | |||
| "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 | |||
| } | |||