From 002d221146f8b4c45e53883e54e08b3c80885c5c Mon Sep 17 00:00:00 2001 From: chie8842 Date: Fri, 5 Jul 2019 20:32:53 +0900 Subject: [PATCH 1/4] add ja/r2/guide/eager.ipynb --- site/ja/r2/guide/eager.ipynb | 1253 ++++++++++++++++++++++++++++++++++ 1 file changed, 1253 insertions(+) create mode 100644 site/ja/r2/guide/eager.ipynb diff --git a/site/ja/r2/guide/eager.ipynb b/site/ja/r2/guide/eager.ipynb new file mode 100644 index 00000000000..1def1348998 --- /dev/null +++ b/site/ja/r2/guide/eager.ipynb @@ -0,0 +1,1253 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "CCQY7jpBfMur" + }, + "source": [ + "##### Copyright 2018 The TensorFlow Authors." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "colab": {}, + "colab_type": "code", + "id": "z6X9omPnfO_h" + }, + "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": { + "colab_type": "text", + "id": "2QQJJyDzqGRb" + }, + "source": [ + "# Eager Execution の基本" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "B1xdylywqUSX" + }, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " View on TensorFlow.org\n", + " \n", + " Run in Google Colab\n", + " \n", + " View source on GitHub\n", + " \n", + " Download notebook\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "EGjDcGxIqEfX" + }, + "source": [ + "\n", + "\n", + "Tensorflow の Eager Execution は、計算グラフの作成と評価を同時におこなう命令的なプログラミングを行うための環境です:\n", + "オペレーションはあとで実行するための計算グラフでなく、具体的な計算結果の値を返します。\n", + "この方法を用いることにより、初心者にとって TensorFlow を始めやすくなり、またモデルのデバッグも行いやすくなります。\n", + "さらにコードの記述量も削減されます。\n", + "このガイドの内容を実行するためには、対話的インタープリタ `python` を起動し、以下のコードサンプルを実行してください。\n", + "\n", + "Eager Execution は研究や実験のための柔軟な機械学習環境として、以下を提供します。\n", + "\n", + "* *直感的なインタフェース*— Python のデータ構造を使用して、コードをナチュラルに記述することができます。スモールなモデルとデータに対してすばやく実験を繰り返すことができます。\n", + "* *より簡単なデバッグ*— ops を直接呼び出すことで、実行中のモデルを調査したり、変更をテストすることができます。 Python 標準のデバッグツールを用いて即座にエラーのレポーティングができます。\n", + "* *自然な制御フロー*— TensorFlow のグラフ制御フローの代わりに Python の制御フローを利用するため、動的なモデルのパラメータ変更をシンプルに行うことができます。\n", + " \n", + "Eager Execution は Tensorflow のほとんどのオペレーションとGPUアクセラレーションをサポートします。\n", + "\n", + "Note: いくつかのモデルは Eager Execution を有効化することでオーバヘッドが増える可能性があります。\n", + "パフォーマンス改善を行っていますが、もしも問題を発見したら、バグ報告してベンチマークを共有してください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RBAeIwOMrYk8" + }, + "source": [ + "## セットアップと基本的な使い方" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "ByNsp4VqqEfa" + }, + "outputs": [], + "source": [ + "from __future__ import absolute_import, division, print_function, unicode_literals\n", + "\n", + "!pip install tensorflow==2.0.0-beta1\n", + "import tensorflow as tf\n", + "\n", + "import cProfile" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "48P3-8q4qEfe" + }, + "source": [ + "TensorFlow 2.0 では、 Eager Execution はデフォルトで有効化されます。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "7aFsD8csqEff" + }, + "outputs": [], + "source": [ + "tf.executing_eagerly()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "x_G1zZT5qEfh" + }, + "source": [ + "これで TensorFlow のオペレーションを実行してみましょう。結果はすぐに返されます。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "9gsI54pbqEfj" + }, + "outputs": [], + "source": [ + "x = [[2.]]\n", + "m = tf.matmul(x, x)\n", + "print(\"hello, {}\".format(m))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ajFn6qsdqEfl" + }, + "source": [ + "Eager Execution を有効化することで、 TensorFlow の挙動は変わります—TensorFlowは即座に式を評価して結果をPythonに返すようになります。\n", + "`tf.Tensor` オブジェクトは計算グラフのノードへのシンボリックハンドルの代わりに具体的な値を参照します。\n", + "セッションの中で構築して実行する計算グラフが存在しないため、`print()`やデバッガを使って容易に結果を調べることができます。\n", + "勾配計算を終了することなくテンソル値を評価、出力、およびチェックすることができます。\n", + "\n", + "Eager Execution は、[NumPy](http://www.numpy.org/)と一緒に使うことができます。\n", + "NumPy のオペレーションは、`tf.Tensor`を引数として受け取ることができます。\n", + "TensorFlow [math operations](https://www.tensorflow.org/api_guides/python/math_ops) はPython オブジェクトと Numpy array を `tf.Tensor` にコンバートします。\n", + "`tf.Tensor.numpy` メソッドはオブジェクトの値を NumPy の `ndarray` 形式で返します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "sTO0_5TYqz1n" + }, + "outputs": [], + "source": [ + "a = tf.constant([[1, 2],\n", + " [3, 4]])\n", + "print(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "Dp14YT8Gq4r1" + }, + "outputs": [], + "source": [ + "# Broadcasting support\n", + "b = tf.add(a, 1)\n", + "print(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "69p3waMfq8cQ" + }, + "outputs": [], + "source": [ + "# Operator overloading is supported\n", + "print(a * b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "Ui025t1qqEfm" + }, + "outputs": [], + "source": [ + "# Use NumPy values\n", + "import numpy as np\n", + "\n", + "c = np.multiply(a, b)\n", + "print(c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "Tq_aFRzWrCua" + }, + "outputs": [], + "source": [ + "# Obtain numpy value from a tensor:\n", + "print(a.numpy())\n", + "# => [[1 2]\n", + "# [3 4]]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "H08f9ss9qEft" + }, + "source": [ + "## 動的な制御フロー\n", + "\n", + "Eager Execution の主要なメリットは、モデルを実行する際にホスト言語のすべての機能性が利用できることです。\n", + "たとえば、[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz)が簡単に書けます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "0fudRMeUqEfu" + }, + "outputs": [], + "source": [ + "def fizzbuzz(max_num):\n", + " counter = tf.constant(0)\n", + " max_num = tf.convert_to_tensor(max_num)\n", + " for num in range(1, max_num.numpy()+1):\n", + " num = tf.constant(num)\n", + " if int(num % 3) == 0 and int(num % 5) == 0:\n", + " print('FizzBuzz')\n", + " elif int(num % 3) == 0:\n", + " print('Fizz')\n", + " elif int(num % 5) == 0:\n", + " print('Buzz')\n", + " else:\n", + " print(num.numpy())\n", + " counter += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "P2cKknQWrJLB" + }, + "outputs": [], + "source": [ + "fizzbuzz(15)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "7kA-aC3BqEfy" + }, + "source": [ + "この関数はテンソル値に依存する条件式を持ち、実行時にこれらの値を表示します。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8huKpuuAwICq" + }, + "source": [ + "## Eager Execution による学習" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "mp2lCCZYrxHd" + }, + "source": [ + "### 勾配の計算\n", + "\n", + "[自動微分](https://en.wikipedia.org/wiki/Automatic_differentiation)はニューラルネットワークの学習で利用される[バックプロパゲーション](https://en.wikipedia.org/wiki/Backpropagation)などの機械学習アルゴリズムの実装を行う上で便利です。\n", + "Eager Executionでは、勾配計算をあとで行うためのオペレーションをトレースするために`tf.GradientTape` を利用します。\n", + "\n", + "Eager Execution では、学習や購買計算に, `tf.GradientTape` を利用できます。これは複雑な学習ループを実行するときに特に役立ちます。\n", + "\n", + "各呼び出し中に異なるオペレーションが発生する可能性があるため、すべての forward-pass オペレーションは一つの「テープ」に記録されます。勾配を計算するには、テープを逆方向に再生してから破棄します。特定の `tf.GradientTape`は一つのグラデーションしか計算できません。後続の呼び出しは実行時エラーをスローします。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "7g1yWiSXqEf-" + }, + "outputs": [], + "source": [ + "w = tf.Variable([[1.0]])\n", + "with tf.GradientTape() as tape:\n", + " loss = w * w\n", + "\n", + "grad = tape.gradient(loss, w)\n", + "print(grad) # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vkHs32GqweYS" + }, + "source": [ + "### モデル学習\n", + "\n", + "以下の example は MNIST という手書き数字分類を行うマルチレイヤーモデルを作成します。\n", + "Eager Execution 環境における学習可能なグラフを構築するためのオプティマイザーとレイヤーAPIを提示します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "38kymXZowhhz" + }, + "outputs": [], + "source": [ + "# Fetch and format the mnist data\n", + "(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()\n", + "\n", + "dataset = tf.data.Dataset.from_tensor_slices(\n", + " (tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),\n", + " tf.cast(mnist_labels,tf.int64)))\n", + "dataset = dataset.shuffle(1000).batch(32)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "rl1K8rOowmwT" + }, + "outputs": [], + "source": [ + "# Build the model\n", + "mnist_model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu',\n", + " input_shape=(None, None, 1)),\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", + " tf.keras.layers.GlobalAveragePooling2D(),\n", + " tf.keras.layers.Dense(10)\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fvyk-HgGwxwl" + }, + "source": [ + "\n", + "学習を行わずとも、モデルを呼び出して、 Eager Execution により、出力を検査することができます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "BsxystjBwxLS" + }, + "outputs": [], + "source": [ + "for images,labels in dataset.take(1):\n", + " print(\"Logits: \", mnist_model(images[0:1]).numpy())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Y3PGa8G7qEgB" + }, + "source": [ + "keras モデルは組み込みで学習のループを回すメソッド `fit` がありますが、よりカスタマイズが必要な場合もあるでしょう。 Eager Executionを用いて実装された学習ループのサンプルを以下に示します:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "bzRhM7JDnaEG" + }, + "outputs": [], + "source": [ + "optimizer = tf.keras.optimizers.Adam()\n", + "loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)\n", + "\n", + "loss_history = []" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "tXaupYXRI2YM" + }, + "source": [ + "Note: モデルの状況を確認したいときは、 `tf.debugging` にある assert 機能を利用してください。この機能は Eager Execution と Graph Execution のどちらでも利用できます。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "DDHrigtiCIA4" + }, + "outputs": [], + "source": [ + "def train_step(images, labels):\n", + " with tf.GradientTape() as tape:\n", + " logits = mnist_model(images, training=True)\n", + " \n", + " # Add asserts to check the shape of the output.\n", + " tf.debugging.assert_equal(logits.shape, (32, 10))\n", + " \n", + " loss_value = loss_object(labels, logits)\n", + "\n", + " loss_history.append(loss_value.numpy().mean())\n", + " grads = tape.gradient(loss_value, mnist_model.trainable_variables)\n", + " optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "0m1xAXrmqEgJ" + }, + "outputs": [], + "source": [ + "def train():\n", + " for epoch in range(3):\n", + " for (batch, (images, labels)) in enumerate(dataset):\n", + " train_step(images, labels)\n", + " print ('Epoch {} finished'.format(epoch))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "C5dGz0p_nf4W" + }, + "outputs": [], + "source": [ + "train()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "5vG5ql_2vYB5" + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.plot(loss_history)\n", + "plt.xlabel('Batch #')\n", + "plt.ylabel('Loss [entropy]')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "kKpOlHPLqEgl" + }, + "source": [ + "### 値とオプティマイザ\n", + "\n", + "`tf.Variable` オブジェクトは、学習中にアクセスされるミュータブルな `tf.Tensor` 値を格納し、自動微分を容易にします。\n", + "モデルのパラメータは、変数としてクラスにカプセル化できます。\n", + "\n", + "`tf.GradientTape` と共に `tf.Variable` を使うことでモデルパラメータはよりカプセル化されます。たとえば、上の\n", + "の自動微分の例は以下のように書き換えることができます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "nnQLBYmEqEgm" + }, + "outputs": [], + "source": [ + "class Model(tf.keras.Model):\n", + " def __init__(self):\n", + " super(Model, self).__init__()\n", + " self.W = tf.Variable(5., name='weight')\n", + " self.B = tf.Variable(10., name='bias')\n", + " def call(self, inputs):\n", + " return inputs * self.W + self.B\n", + "\n", + "# A toy dataset of points around 3 * x + 2\n", + "NUM_EXAMPLES = 2000\n", + "training_inputs = tf.random.normal([NUM_EXAMPLES])\n", + "noise = tf.random.normal([NUM_EXAMPLES])\n", + "training_outputs = training_inputs * 3 + 2 + noise\n", + "\n", + "# The loss function to be optimized\n", + "def loss(model, inputs, targets):\n", + " error = model(inputs) - targets\n", + " return tf.reduce_mean(tf.square(error))\n", + "\n", + "def grad(model, inputs, targets):\n", + " with tf.GradientTape() as tape:\n", + " loss_value = loss(model, inputs, targets)\n", + " return tape.gradient(loss_value, [model.W, model.B])\n", + "\n", + "# Define:\n", + "# 1. A model.\n", + "# 2. Derivatives of a loss function with respect to model parameters.\n", + "# 3. A strategy for updating the variables based on the derivatives.\n", + "model = Model()\n", + "optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)\n", + "\n", + "print(\"Initial loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", + "\n", + "# Training loop\n", + "for i in range(300):\n", + " grads = grad(model, training_inputs, training_outputs)\n", + " optimizer.apply_gradients(zip(grads, [model.W, model.B]))\n", + " if i % 20 == 0:\n", + " print(\"Loss at step {:03d}: {:.3f}\".format(i, loss(model, training_inputs, training_outputs)))\n", + "\n", + "print(\"Final loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", + "print(\"W = {}, B = {}\".format(model.W.numpy(), model.B.numpy()))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rPjb8nRWqEgr" + }, + "source": [ + "## Eager Execution の途中でオブジェクトのステータスを使用する\n", + "\n", + "TF 1.x の Graph Execution では、プログラムの状態(変数など)は global collection に格納され、それらの存続期間は `tf.Session` オブジェクトによって管理されます。\n", + "対照的に、 Eager Execution の間、状態オブジェクトの存続期間は、対応する Python オブジェクトの存続期間によって決定されます。\n", + "\n", + "### 変数とオブジェクト\n", + "\n", + "Eager Execution の間、変数はオブジェクトへの最後の参照が削除され、その後削除されるまで存続します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "A2boS674qEgs" + }, + "outputs": [], + "source": [ + "if tf.test.is_gpu_available():\n", + " with tf.device(\"gpu:0\"):\n", + " v = tf.Variable(tf.random.normal([1000, 1000]))\n", + " v = None # v no longer takes up GPU memory" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "scMjg6L6qEgv" + }, + "source": [ + "### オブジェクトベースの保存\n", + "\n", + "このセクションは、[チェックポイントのトレーニングの手引き](./ checkpoints.ipynb) の省略版です。\n", + "\n", + "`tf.train.Checkpoint` はチェックポイントを用いて `tf.Variable` を保存および復元することができます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "7z5xRfdHzZOQ" + }, + "outputs": [], + "source": [ + "x = tf.Variable(10.)\n", + "checkpoint = tf.train.Checkpoint(x=x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "IffrUVG7zyVb" + }, + "outputs": [], + "source": [ + "x.assign(2.) # Assign a new value to the variables and save.\n", + "checkpoint_path = './ckpt/'\n", + "checkpoint.save('./ckpt/')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "eMT9koCoqEgw" + }, + "outputs": [], + "source": [ + "x.assign(11.) # Change the variable after saving.\n", + "\n", + "# Restore values from the checkpoint\n", + "checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))\n", + "\n", + "print(x) # => 2.0" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vbFnP-yLqEgx" + }, + "source": [ + "モデルを保存して読み込むために、 `tf.train.Checkpoint` は隠れ変数なしにオブジェクトの内部状態を保存します。 `モデル`、 `オプティマイザ` 、そしてグローバルステップの状態を記録するには、それらを `tf.train.Checkpoint` に渡します。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "hWZHyAXMqEg0" + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", + " tf.keras.layers.GlobalAveragePooling2D(),\n", + " tf.keras.layers.Dense(10)\n", + "])\n", + "optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n", + "checkpoint_dir = 'path/to/model_dir'\n", + "if not os.path.exists(checkpoint_dir):\n", + " os.makedirs(checkpoint_dir)\n", + "checkpoint_prefix = os.path.join(checkpoint_dir, \"ckpt\")\n", + "root = tf.train.Checkpoint(optimizer=optimizer,\n", + " model=model)\n", + "\n", + "root.save(checkpoint_prefix)\n", + "root.restore(tf.train.latest_checkpoint(checkpoint_dir))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "R-ITwkBCF6GJ" + }, + "source": [ + "多くの学習ループでは、変数は `tf.train..Checkpoint.restore` が呼ばれたあとに作成されます。これらの変数は作成されてすぐにリストアされ、チェックポイントが全てロードされたことを確認するためのアサーションが利用可能になります。詳しくは、 [guide to training checkpoints](./checkpoints.ipynb) を見てください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "3yoD0VJ7qEg3" + }, + "source": [ + "### オブジェクト指向メトリクス\n", + "\n", + "`tfe.keras.metrics`はオブジェクトとして保存されます。新しいデータを呼び出し可能オブジェクトに渡してメトリクスを更新し、 `tfe.keras.metrics.result`メソッドを使って結果を取得します。次に例を示します:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "9ccu0iAaqEg5" + }, + "outputs": [], + "source": [ + "m = tf.keras.metrics.Mean(\"loss\")\n", + "m(0)\n", + "m(5)\n", + "m.result() # => 2.5\n", + "m([8, 9])\n", + "m.result() # => 5.5" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "xEL4yJe5qEhD" + }, + "source": [ + "## 高度な自動分類トピック\n", + "\n", + "### 動的なモデル\n", + "\n", + "`tf.GradientTape`は動的モデルでも使うことができます。 \n", + "以下の[バックトラックライン検索](https://wikipedia.org/wiki/Backtracking_line_search)\n", + "アルゴリズムの例は、複雑な制御フローにも関わらず\n", + "勾配があり、微分可能であることを除いて、通常のNumPyコードのように見えます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "L518n5dkqEhE" + }, + "outputs": [], + "source": [ + "def line_search_step(fn, init_x, rate=1.0):\n", + " with tf.GradientTape() as tape:\n", + " # Variables are automatically recorded, but manually watch a tensor\n", + " tape.watch(init_x)\n", + " value = fn(init_x)\n", + " grad = tape.gradient(value, init_x)\n", + " grad_norm = tf.reduce_sum(grad * grad)\n", + " init_value = value\n", + " while value > init_value - rate * grad_norm:\n", + " x = init_x - rate * grad\n", + " value = fn(x)\n", + " rate /= 2.0\n", + " return x, value" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "gieGOf_DqEhK" + }, + "source": [ + "### カスタム勾配\n", + "\n", + "カスタム勾配は、勾配を上書きする簡単な方法です。 フォワード関数では、\n", + "入力、出力、または中間結果に関する勾配を定義します。たとえば、逆方向パスにおいて勾配のノルムを切り取る簡単な方法は次のとおりです:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "-OwwsWUAqEhK" + }, + "outputs": [], + "source": [ + "@tf.custom_gradient\n", + "def clip_gradient_by_norm(x, norm):\n", + " y = tf.identity(x)\n", + " def grad_fn(dresult):\n", + " return [tf.clip_by_norm(dresult, norm), None]\n", + " return y, grad_fn" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "JPLDHkF_qEhN" + }, + "source": [ + "カスタム勾配は、一連の演算に対して数値的に安定した勾配を提供するために共通的に使用されます。:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "24WiLROnqEhO" + }, + "outputs": [], + "source": [ + "def log1pexp(x):\n", + " return tf.math.log(1 + tf.exp(x))\n", + "\n", + "def grad_log1pexp(x):\n", + " with tf.GradientTape() as tape:\n", + " tape.watch(x)\n", + " value = log1pexp(x)\n", + " return tape.gradient(value, x)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "n8fq69r9-B-c" + }, + "outputs": [], + "source": [ + "# The gradient computation works fine at x = 0.\n", + "grad_log1pexp(tf.constant(0.)).numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "_VFSU0mG-FSp" + }, + "outputs": [], + "source": [ + "# However, x = 100 fails because of numerical instability.\n", + "grad_log1pexp(tf.constant(100.)).numpy()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "-VcTR34rqEhQ" + }, + "source": [ + "ここで、 `log1pexp`関数はカスタム勾配を用いて解析的に単純化することができます。\n", + "以下の実装は、フォワードパスの間に計算された `tf.exp(x)`の値を\n", + "再利用します—冗長な計算を排除することでより効率的になります:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "Q7nvfx_-qEhS" + }, + "outputs": [], + "source": [ + "@tf.custom_gradient\n", + "def log1pexp(x):\n", + " e = tf.exp(x)\n", + " def grad(dy):\n", + " return dy * (1 - 1 / (1 + e))\n", + " return tf.math.log(1 + e), grad\n", + "\n", + "def grad_log1pexp(x):\n", + " with tf.GradientTape() as tape:\n", + " tape.watch(x)\n", + " value = log1pexp(x)\n", + " return tape.gradient(value, x)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "5gHPKMfl-Kge" + }, + "outputs": [], + "source": [ + "# As before, the gradient computation works fine at x = 0.\n", + "grad_log1pexp(tf.constant(0.)).numpy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": {}, + "colab_type": "code", + "id": "u38MOfz3-MDE" + }, + "outputs": [], + "source": [ + "# And the gradient computation also works at x = 100.\n", + "grad_log1pexp(tf.constant(100.)).numpy()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rnZXjfQzqEhV" + }, + "source": [ + "## パフォーマンス\n", + "\n", + "Eager Executionの間、計算は自動的にGPUにオフロードされます。計算を実行するデバイスを指定したい場合は、\n", + "`tf.device( '/ gpu:0')`ブロック(もしくはCPUを指定するブロック)で囲むことで指定できます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "Ac9Y64H-qEhX" + }, + "outputs": [], + "source": [ + "import time\n", + "\n", + "def measure(x, steps):\n", + " # TensorFlow initializes a GPU the first time it's used, exclude from timing.\n", + " tf.matmul(x, x)\n", + " start = time.time()\n", + " for i in range(steps):\n", + " x = tf.matmul(x, x)\n", + " # tf.matmul can return before completing the matrix multiplication\n", + " # (e.g., can return after enqueing the operation on a CUDA stream).\n", + " # The x.numpy() call below will ensure that all enqueued operations\n", + " # have completed (and will also copy the result to host memory,\n", + " # so we're including a little more than just the matmul operation\n", + " # time).\n", + " _ = x.numpy()\n", + " end = time.time()\n", + " return end - start\n", + "\n", + "shape = (1000, 1000)\n", + "steps = 200\n", + "print(\"Time to multiply a {} matrix by itself {} times:\".format(shape, steps))\n", + "\n", + "# Run on CPU:\n", + "with tf.device(\"/cpu:0\"):\n", + " print(\"CPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", + "\n", + "# Run on GPU, if available:\n", + "if tf.test.is_gpu_available():\n", + " with tf.device(\"/gpu:0\"):\n", + " print(\"GPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", + "else:\n", + " print(\"GPU: not found\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RLw3IS7UqEhe" + }, + "source": [ + "`tf.Tensor`オブジェクトはそのオブジェクトに対するオペレーションを実行するために別のデバイスにコピーすることができます:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab": {}, + "colab_type": "code", + "id": "ny6LX2BVqEhf" + }, + "outputs": [], + "source": [ + "if tf.test.is_gpu_available():\n", + " x = tf.random.normal([10, 10])\n", + "\n", + " x_gpu0 = x.gpu()\n", + " x_cpu = x.cpu()\n", + "\n", + " _ = tf.matmul(x_cpu, x_cpu) # Runs on CPU\n", + " _ = tf.matmul(x_gpu0, x_gpu0) # Runs on GPU:0" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "oA_qaII3-p6c" + }, + "source": [ + "### Benchmarks\n", + "\n", + "For compute-heavy models, such as\n", + "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", + "training on a GPU, eager execution performance is comparable to `tf.function` execution.\n", + "But this gap grows larger for models with less computation and there is work to\n", + "be done for optimizing hot code paths for models with lots of small operations.\n", + "\n", + "For compute-heavy models, such as\n", + "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", + "training on a GPU, eager execution performance is comparable to graph execution.\n", + "But this gap grows larger for models with less computation and there is work to\n", + "be done for optimizing hot code paths for models with lots of small operations.\n", + "\n", + "### ベンチマーク\n", + "\n", + "GPUでの\n", + "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", + "の学習のような、計算量の多いモデルの場合は、Eager Executionのパフォーマンスは `tf.function` のパフォーマンスに匹敵します。\n", + "しかし、この2つの環境下のパフォーマンスの違いは計算量の少ないモデルではより大きくなり、小さなたくさんのオペレーションからなるモデルでホットコードパスを最適化するためにやるべきことがあります。\n", + "\n", + "## functionsの利用\n", + "\n", + "Eager Executionは開発とデバッグをより対話的にしますが、\n", + "TensorFlow 1.x スタイルのGraph Executionは分散学習、パフォーマンスの最適化、そしてプロダクション環境へのデプロイの観点で利点があります。\n", + "\n", + "2つの手法のギャップを埋めるために、 TensorFlow 2.0 は `tf.function` API に似た `function` を紹介します。\n", + "詳しくは、 [Autograph](./autograph.ipynb) のガイドを見てください。\n" + ] + } + ], + "metadata": { + "colab": { + "collapsed_sections": [], + "name": "Eager.ipynb", + "private_outputs": true, + "provenance": [], + "toc_visible": true, + "version": "0.3.2" + }, + "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.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 6ac776a37fa726407acf185f7590e57fe968b0aa Mon Sep 17 00:00:00 2001 From: chie8842 Date: Fri, 5 Jul 2019 20:53:14 +0900 Subject: [PATCH 2/4] fixed bugs --- site/ja/r2/guide/eager.ipynb | 111 ++++++++++++++++------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/site/ja/r2/guide/eager.ipynb b/site/ja/r2/guide/eager.ipynb index 1def1348998..058c75d2de5 100644 --- a/site/ja/r2/guide/eager.ipynb +++ b/site/ja/r2/guide/eager.ipynb @@ -67,6 +67,13 @@ "" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳は**ベストエフォート**であるため、この翻訳が正確であることや[英語の公式ドキュメント](https://www.tensorflow.org/?hl=en)の 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリ[tensorflow/docs](https://github.com/tensorflow/docs)にプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [docs-ja@tensorflow.org メーリングリスト](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ja)にご連絡ください。" + ] + }, { "cell_type": "markdown", "metadata": { @@ -225,7 +232,7 @@ }, "outputs": [], "source": [ - "# Broadcasting support\n", + "# ブロードキャストのサポート\n", "b = tf.add(a, 1)\n", "print(b)" ] @@ -240,7 +247,7 @@ }, "outputs": [], "source": [ - "# Operator overloading is supported\n", + "# オペレータのオーバーロードがサポートされている\n", "print(a * b)" ] }, @@ -260,7 +267,7 @@ }, "outputs": [], "source": [ - "# Use NumPy values\n", + "# NumPy valueの使用\n", "import numpy as np\n", "\n", "c = np.multiply(a, b)\n", @@ -277,7 +284,7 @@ }, "outputs": [], "source": [ - "# Obtain numpy value from a tensor:\n", + "# Tensor から numpy の値を得る\n", "print(a.numpy())\n", "# => [[1 2]\n", "# [3 4]]" @@ -425,7 +432,7 @@ }, "outputs": [], "source": [ - "# Fetch and format the mnist data\n", + "# mnist データのを取得し、フォーマットする\n", "(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()\n", "\n", "dataset = tf.data.Dataset.from_tensor_slices(\n", @@ -444,7 +451,7 @@ }, "outputs": [], "source": [ - "# Build the model\n", + "# モデルを構築する\n", "mnist_model = tf.keras.Sequential([\n", " tf.keras.layers.Conv2D(16,[3,3], activation='relu',\n", " input_shape=(None, None, 1)),\n", @@ -529,7 +536,7 @@ " with tf.GradientTape() as tape:\n", " logits = mnist_model(images, training=True)\n", " \n", - " # Add asserts to check the shape of the output.\n", + " # assertを入れて出力の型をチェックする。\n", " tf.debugging.assert_equal(logits.shape, (32, 10))\n", " \n", " loss_value = loss_object(labels, logits)\n", @@ -632,13 +639,13 @@ " def call(self, inputs):\n", " return inputs * self.W + self.B\n", "\n", - "# A toy dataset of points around 3 * x + 2\n", + "# 3 * 2 + 2を近似するトイデータセット\n", "NUM_EXAMPLES = 2000\n", "training_inputs = tf.random.normal([NUM_EXAMPLES])\n", "noise = tf.random.normal([NUM_EXAMPLES])\n", "training_outputs = training_inputs * 3 + 2 + noise\n", "\n", - "# The loss function to be optimized\n", + "# オプティマイズ対象のloss関数\n", "def loss(model, inputs, targets):\n", " error = model(inputs) - targets\n", " return tf.reduce_mean(tf.square(error))\n", @@ -648,10 +655,10 @@ " loss_value = loss(model, inputs, targets)\n", " return tape.gradient(loss_value, [model.W, model.B])\n", "\n", - "# Define:\n", - "# 1. A model.\n", - "# 2. Derivatives of a loss function with respect to model parameters.\n", - "# 3. A strategy for updating the variables based on the derivatives.\n", + "# 定義:\n", + "# 1. モデル\n", + "# 2. モデルパラメータに関する損失関数の導関数\n", + "# 3. 導関数に基づいて変数を更新するストラテジ。\n", "model = Model()\n", "optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)\n", "\n", @@ -704,7 +711,7 @@ "if tf.test.is_gpu_available():\n", " with tf.device(\"gpu:0\"):\n", " v = tf.Variable(tf.random.normal([1000, 1000]))\n", - " v = None # v no longer takes up GPU memory" + " v = None # v は GPU メモリを利用しなくなる" ] }, { @@ -716,7 +723,7 @@ "source": [ "### オブジェクトベースの保存\n", "\n", - "このセクションは、[チェックポイントのトレーニングの手引き](./ checkpoints.ipynb) の省略版です。\n", + "このセクションは、[チェックポイントの学習の手引き](./ checkpoints.ipynb) の省略版です。\n", "\n", "`tf.train.Checkpoint` はチェックポイントを用いて `tf.Variable` を保存および復元することができます:" ] @@ -745,7 +752,7 @@ }, "outputs": [], "source": [ - "x.assign(2.) # Assign a new value to the variables and save.\n", + "x.assign(2.) # 新しい値を変数に代入して保存する。\n", "checkpoint_path = './ckpt/'\n", "checkpoint.save('./ckpt/')" ] @@ -766,9 +773,9 @@ }, "outputs": [], "source": [ - "x.assign(11.) # Change the variable after saving.\n", + "x.assign(11.) # 保存後に変数の値を変える。\n", "\n", - "# Restore values from the checkpoint\n", + "# チェックポイントから変数を復元する\n", "checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))\n", "\n", "print(x) # => 2.0" @@ -826,7 +833,7 @@ "id": "R-ITwkBCF6GJ" }, "source": [ - "多くの学習ループでは、変数は `tf.train..Checkpoint.restore` が呼ばれたあとに作成されます。これらの変数は作成されてすぐにリストアされ、チェックポイントが全てロードされたことを確認するためのアサーションが利用可能になります。詳しくは、 [guide to training checkpoints](./checkpoints.ipynb) を見てください。" + "多くの学習ループでは、変数は `tf.train..Checkpoint.restore` が呼ばれたあとに作成されます。これらの変数は作成されてすぐに復元され、チェックポイントがすべてロードされたことを確認するためのアサーションが利用可能になります。詳しくは、 [guide to training checkpoints](./checkpoints.ipynb) を見てください。" ] }, { @@ -876,10 +883,10 @@ "\n", "### 動的なモデル\n", "\n", - "`tf.GradientTape`は動的モデルでも使うことができます。 \n", - "以下の[バックトラックライン検索](https://wikipedia.org/wiki/Backtracking_line_search)\n", - "アルゴリズムの例は、複雑な制御フローにも関わらず\n", - "勾配があり、微分可能であることを除いて、通常のNumPyコードのように見えます:" + "`tf.GradientTape` は動的モデルでも使うことができます。 \n", + "以下の [バックトラックライン検索](https://wikipedia.org/wiki/Backtracking_line_search)\n", + "アルゴリズムの例は、複雑な制御フローにもかかわらず\n", + "勾配があり、微分可能であることを除いて、通常の NumPy コードのように見えます:" ] }, { @@ -900,7 +907,7 @@ "source": [ "def line_search_step(fn, init_x, rate=1.0):\n", " with tf.GradientTape() as tape:\n", - " # Variables are automatically recorded, but manually watch a tensor\n", + " # 変数は自動的に記録されるが、Tensorは手動でウォッチする\n", " tape.watch(init_x)\n", " value = fn(init_x)\n", " grad = tape.gradient(value, init_x)\n", @@ -996,7 +1003,7 @@ }, "outputs": [], "source": [ - "# The gradient computation works fine at x = 0.\n", + "# 購買計算は x = 0 のときはうまくいく。\n", "grad_log1pexp(tf.constant(0.)).numpy()" ] }, @@ -1010,7 +1017,7 @@ }, "outputs": [], "source": [ - "# However, x = 100 fails because of numerical instability.\n", + "# しかし、x = 100のときは数値的不安定により失敗する。\n", "grad_log1pexp(tf.constant(100.)).numpy()" ] }, @@ -1021,8 +1028,8 @@ "id": "-VcTR34rqEhQ" }, "source": [ - "ここで、 `log1pexp`関数はカスタム勾配を用いて解析的に単純化することができます。\n", - "以下の実装は、フォワードパスの間に計算された `tf.exp(x)`の値を\n", + "ここで、 `log1pexp` 関数はカスタム勾配を用いて解析的に単純化することができます。\n", + "以下の実装は、フォワードパスの間に計算された `tf.exp(x)` の値を\n", "再利用します—冗長な計算を排除することでより効率的になります:" ] }, @@ -1066,7 +1073,7 @@ }, "outputs": [], "source": [ - "# As before, the gradient computation works fine at x = 0.\n", + "# 上と同様に、勾配計算はx = 0のときにはうまくいきます。\n", "grad_log1pexp(tf.constant(0.)).numpy()" ] }, @@ -1080,7 +1087,7 @@ }, "outputs": [], "source": [ - "# And the gradient computation also works at x = 100.\n", + "# また、勾配計算はx = 100でも機能します。\n", "grad_log1pexp(tf.constant(100.)).numpy()" ] }, @@ -1094,7 +1101,7 @@ "## パフォーマンス\n", "\n", "Eager Executionの間、計算は自動的にGPUにオフロードされます。計算を実行するデバイスを指定したい場合は、\n", - "`tf.device( '/ gpu:0')`ブロック(もしくはCPUを指定するブロック)で囲むことで指定できます:" + "`tf.device( '/ gpu:0')` ブロック(もしくはCPUを指定するブロック)で囲むことで指定できます:" ] }, { @@ -1116,17 +1123,15 @@ "import time\n", "\n", "def measure(x, steps):\n", - " # TensorFlow initializes a GPU the first time it's used, exclude from timing.\n", + " # TensorFlowはGPUを初めて使用するときに初期化するため、時間計測対象からは除外する。\n", " tf.matmul(x, x)\n", " start = time.time()\n", " for i in range(steps):\n", " x = tf.matmul(x, x)\n", - " # tf.matmul can return before completing the matrix multiplication\n", - " # (e.g., can return after enqueing the operation on a CUDA stream).\n", - " # The x.numpy() call below will ensure that all enqueued operations\n", - " # have completed (and will also copy the result to host memory,\n", - " # so we're including a little more than just the matmul operation\n", - " # time).\n", + " # tf.matmulは、行列乗算が完了する前に戻ることができる。\n", + " # (たとえば、CUDAストリームにオペレーションをエンキューした後に戻すことができる)。\n", + " # 以下のx.numpy()呼び出しは、すべてのキューに入れられたオペレーションが完了したことを確認する。\n", + " # (そして結果をホストメモリにコピーするため、計算時間は単純なmatmulオペレーションよりも多くのことを含む時間になる。)\n", " _ = x.numpy()\n", " end = time.time()\n", " return end - start\n", @@ -1135,11 +1140,11 @@ "steps = 200\n", "print(\"Time to multiply a {} matrix by itself {} times:\".format(shape, steps))\n", "\n", - "# Run on CPU:\n", + "# CPU上で実行するとき:\n", "with tf.device(\"/cpu:0\"):\n", - " print(\"CPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", + " print(\"CPU: {} secs\".format(measure(tf.random_normal(shape), steps)))\n", "\n", - "# Run on GPU, if available:\n", + "# GPU上で実行するとき(GPUが利用できれば):\n", "if tf.test.is_gpu_available():\n", " with tf.device(\"/gpu:0\"):\n", " print(\"GPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", @@ -1154,7 +1159,7 @@ "id": "RLw3IS7UqEhe" }, "source": [ - "`tf.Tensor`オブジェクトはそのオブジェクトに対するオペレーションを実行するために別のデバイスにコピーすることができます:" + "`tf.Tensor` オブジェクトはそのオブジェクトに対するオペレーションを実行するために別のデバイスにコピーすることができます:" ] }, { @@ -1179,8 +1184,8 @@ " x_gpu0 = x.gpu()\n", " x_cpu = x.cpu()\n", "\n", - " _ = tf.matmul(x_cpu, x_cpu) # Runs on CPU\n", - " _ = tf.matmul(x_gpu0, x_gpu0) # Runs on GPU:0" + " _ = tf.matmul(x_cpu, x_cpu) # CPU上で実行するとき\n", + " _ = tf.matmul(x_gpu0, x_gpu0) # GPU:0上で実行するとき" ] }, { @@ -1190,20 +1195,6 @@ "id": "oA_qaII3-p6c" }, "source": [ - "### Benchmarks\n", - "\n", - "For compute-heavy models, such as\n", - "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", - "training on a GPU, eager execution performance is comparable to `tf.function` execution.\n", - "But this gap grows larger for models with less computation and there is work to\n", - "be done for optimizing hot code paths for models with lots of small operations.\n", - "\n", - "For compute-heavy models, such as\n", - "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", - "training on a GPU, eager execution performance is comparable to graph execution.\n", - "But this gap grows larger for models with less computation and there is work to\n", - "be done for optimizing hot code paths for models with lots of small operations.\n", - "\n", "### ベンチマーク\n", "\n", "GPUでの\n", @@ -1213,8 +1204,8 @@ "\n", "## functionsの利用\n", "\n", - "Eager Executionは開発とデバッグをより対話的にしますが、\n", - "TensorFlow 1.x スタイルのGraph Executionは分散学習、パフォーマンスの最適化、そしてプロダクション環境へのデプロイの観点で利点があります。\n", + "Eager Execution は開発とデバッグをより対話的にしますが、\n", + "TensorFlow 1.x スタイルの Graph Execution は分散学習、パフォーマンスの最適化、そしてプロダクション環境へのデプロイの観点で利点があります。\n", "\n", "2つの手法のギャップを埋めるために、 TensorFlow 2.0 は `tf.function` API に似た `function` を紹介します。\n", "詳しくは、 [Autograph](./autograph.ipynb) のガイドを見てください。\n" From a51fabf75385960c859c9d4fe002805773065463 Mon Sep 17 00:00:00 2001 From: Billy Lamberta Date: Wed, 10 Jul 2019 15:39:14 -0700 Subject: [PATCH 3/4] Fix file path --- site/ja/{r2 => beta}/guide/eager.ipynb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename site/ja/{r2 => beta}/guide/eager.ipynb (100%) diff --git a/site/ja/r2/guide/eager.ipynb b/site/ja/beta/guide/eager.ipynb similarity index 100% rename from site/ja/r2/guide/eager.ipynb rename to site/ja/beta/guide/eager.ipynb From f83980581b902e4397f2f5f7a842513d81252e64 Mon Sep 17 00:00:00 2001 From: Billy Lamberta Date: Wed, 10 Jul 2019 15:40:03 -0700 Subject: [PATCH 4/4] Fix notebook and switch to GPU --- site/ja/beta/guide/eager.ipynb | 2490 ++++++++++++++++---------------- 1 file changed, 1247 insertions(+), 1243 deletions(-) diff --git a/site/ja/beta/guide/eager.ipynb b/site/ja/beta/guide/eager.ipynb index 058c75d2de5..fd2fa09146f 100644 --- a/site/ja/beta/guide/eager.ipynb +++ b/site/ja/beta/guide/eager.ipynb @@ -1,1244 +1,1248 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "CCQY7jpBfMur" - }, - "source": [ - "##### Copyright 2018 The TensorFlow Authors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "cellView": "form", - "colab": {}, - "colab_type": "code", - "id": "z6X9omPnfO_h" - }, - "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": { - "colab_type": "text", - "id": "2QQJJyDzqGRb" - }, - "source": [ - "# Eager Execution の基本" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "B1xdylywqUSX" - }, - "source": [ - "\n", - " \n", - " \n", - " \n", - " \n", - "
\n", - " View on TensorFlow.org\n", - " \n", - " Run in Google Colab\n", - " \n", - " View source on GitHub\n", - " \n", - " Download notebook\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳は**ベストエフォート**であるため、この翻訳が正確であることや[英語の公式ドキュメント](https://www.tensorflow.org/?hl=en)の 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリ[tensorflow/docs](https://github.com/tensorflow/docs)にプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [docs-ja@tensorflow.org メーリングリスト](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ja)にご連絡ください。" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "EGjDcGxIqEfX" - }, - "source": [ - "\n", - "\n", - "Tensorflow の Eager Execution は、計算グラフの作成と評価を同時におこなう命令的なプログラミングを行うための環境です:\n", - "オペレーションはあとで実行するための計算グラフでなく、具体的な計算結果の値を返します。\n", - "この方法を用いることにより、初心者にとって TensorFlow を始めやすくなり、またモデルのデバッグも行いやすくなります。\n", - "さらにコードの記述量も削減されます。\n", - "このガイドの内容を実行するためには、対話的インタープリタ `python` を起動し、以下のコードサンプルを実行してください。\n", - "\n", - "Eager Execution は研究や実験のための柔軟な機械学習環境として、以下を提供します。\n", - "\n", - "* *直感的なインタフェース*— Python のデータ構造を使用して、コードをナチュラルに記述することができます。スモールなモデルとデータに対してすばやく実験を繰り返すことができます。\n", - "* *より簡単なデバッグ*— ops を直接呼び出すことで、実行中のモデルを調査したり、変更をテストすることができます。 Python 標準のデバッグツールを用いて即座にエラーのレポーティングができます。\n", - "* *自然な制御フロー*— TensorFlow のグラフ制御フローの代わりに Python の制御フローを利用するため、動的なモデルのパラメータ変更をシンプルに行うことができます。\n", - " \n", - "Eager Execution は Tensorflow のほとんどのオペレーションとGPUアクセラレーションをサポートします。\n", - "\n", - "Note: いくつかのモデルは Eager Execution を有効化することでオーバヘッドが増える可能性があります。\n", - "パフォーマンス改善を行っていますが、もしも問題を発見したら、バグ報告してベンチマークを共有してください。" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "RBAeIwOMrYk8" - }, - "source": [ - "## セットアップと基本的な使い方" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "ByNsp4VqqEfa" - }, - "outputs": [], - "source": [ - "from __future__ import absolute_import, division, print_function, unicode_literals\n", - "\n", - "!pip install tensorflow==2.0.0-beta1\n", - "import tensorflow as tf\n", - "\n", - "import cProfile" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "48P3-8q4qEfe" - }, - "source": [ - "TensorFlow 2.0 では、 Eager Execution はデフォルトで有効化されます。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "7aFsD8csqEff" - }, - "outputs": [], - "source": [ - "tf.executing_eagerly()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "x_G1zZT5qEfh" - }, - "source": [ - "これで TensorFlow のオペレーションを実行してみましょう。結果はすぐに返されます。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "9gsI54pbqEfj" - }, - "outputs": [], - "source": [ - "x = [[2.]]\n", - "m = tf.matmul(x, x)\n", - "print(\"hello, {}\".format(m))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "ajFn6qsdqEfl" - }, - "source": [ - "Eager Execution を有効化することで、 TensorFlow の挙動は変わります—TensorFlowは即座に式を評価して結果をPythonに返すようになります。\n", - "`tf.Tensor` オブジェクトは計算グラフのノードへのシンボリックハンドルの代わりに具体的な値を参照します。\n", - "セッションの中で構築して実行する計算グラフが存在しないため、`print()`やデバッガを使って容易に結果を調べることができます。\n", - "勾配計算を終了することなくテンソル値を評価、出力、およびチェックすることができます。\n", - "\n", - "Eager Execution は、[NumPy](http://www.numpy.org/)と一緒に使うことができます。\n", - "NumPy のオペレーションは、`tf.Tensor`を引数として受け取ることができます。\n", - "TensorFlow [math operations](https://www.tensorflow.org/api_guides/python/math_ops) はPython オブジェクトと Numpy array を `tf.Tensor` にコンバートします。\n", - "`tf.Tensor.numpy` メソッドはオブジェクトの値を NumPy の `ndarray` 形式で返します。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "sTO0_5TYqz1n" - }, - "outputs": [], - "source": [ - "a = tf.constant([[1, 2],\n", - " [3, 4]])\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "Dp14YT8Gq4r1" - }, - "outputs": [], - "source": [ - "# ブロードキャストのサポート\n", - "b = tf.add(a, 1)\n", - "print(b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "69p3waMfq8cQ" - }, - "outputs": [], - "source": [ - "# オペレータのオーバーロードがサポートされている\n", - "print(a * b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "Ui025t1qqEfm" - }, - "outputs": [], - "source": [ - "# NumPy valueの使用\n", - "import numpy as np\n", - "\n", - "c = np.multiply(a, b)\n", - "print(c)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "Tq_aFRzWrCua" - }, - "outputs": [], - "source": [ - "# Tensor から numpy の値を得る\n", - "print(a.numpy())\n", - "# => [[1 2]\n", - "# [3 4]]" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "H08f9ss9qEft" - }, - "source": [ - "## 動的な制御フロー\n", - "\n", - "Eager Execution の主要なメリットは、モデルを実行する際にホスト言語のすべての機能性が利用できることです。\n", - "たとえば、[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz)が簡単に書けます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "0fudRMeUqEfu" - }, - "outputs": [], - "source": [ - "def fizzbuzz(max_num):\n", - " counter = tf.constant(0)\n", - " max_num = tf.convert_to_tensor(max_num)\n", - " for num in range(1, max_num.numpy()+1):\n", - " num = tf.constant(num)\n", - " if int(num % 3) == 0 and int(num % 5) == 0:\n", - " print('FizzBuzz')\n", - " elif int(num % 3) == 0:\n", - " print('Fizz')\n", - " elif int(num % 5) == 0:\n", - " print('Buzz')\n", - " else:\n", - " print(num.numpy())\n", - " counter += 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "P2cKknQWrJLB" - }, - "outputs": [], - "source": [ - "fizzbuzz(15)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "7kA-aC3BqEfy" - }, - "source": [ - "この関数はテンソル値に依存する条件式を持ち、実行時にこれらの値を表示します。" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "8huKpuuAwICq" - }, - "source": [ - "## Eager Execution による学習" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "mp2lCCZYrxHd" - }, - "source": [ - "### 勾配の計算\n", - "\n", - "[自動微分](https://en.wikipedia.org/wiki/Automatic_differentiation)はニューラルネットワークの学習で利用される[バックプロパゲーション](https://en.wikipedia.org/wiki/Backpropagation)などの機械学習アルゴリズムの実装を行う上で便利です。\n", - "Eager Executionでは、勾配計算をあとで行うためのオペレーションをトレースするために`tf.GradientTape` を利用します。\n", - "\n", - "Eager Execution では、学習や購買計算に, `tf.GradientTape` を利用できます。これは複雑な学習ループを実行するときに特に役立ちます。\n", - "\n", - "各呼び出し中に異なるオペレーションが発生する可能性があるため、すべての forward-pass オペレーションは一つの「テープ」に記録されます。勾配を計算するには、テープを逆方向に再生してから破棄します。特定の `tf.GradientTape`は一つのグラデーションしか計算できません。後続の呼び出しは実行時エラーをスローします。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "7g1yWiSXqEf-" - }, - "outputs": [], - "source": [ - "w = tf.Variable([[1.0]])\n", - "with tf.GradientTape() as tape:\n", - " loss = w * w\n", - "\n", - "grad = tape.gradient(loss, w)\n", - "print(grad) # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "vkHs32GqweYS" - }, - "source": [ - "### モデル学習\n", - "\n", - "以下の example は MNIST という手書き数字分類を行うマルチレイヤーモデルを作成します。\n", - "Eager Execution 環境における学習可能なグラフを構築するためのオプティマイザーとレイヤーAPIを提示します。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "38kymXZowhhz" - }, - "outputs": [], - "source": [ - "# mnist データのを取得し、フォーマットする\n", - "(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()\n", - "\n", - "dataset = tf.data.Dataset.from_tensor_slices(\n", - " (tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),\n", - " tf.cast(mnist_labels,tf.int64)))\n", - "dataset = dataset.shuffle(1000).batch(32)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "rl1K8rOowmwT" - }, - "outputs": [], - "source": [ - "# モデルを構築する\n", - "mnist_model = tf.keras.Sequential([\n", - " tf.keras.layers.Conv2D(16,[3,3], activation='relu',\n", - " input_shape=(None, None, 1)),\n", - " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", - " tf.keras.layers.GlobalAveragePooling2D(),\n", - " tf.keras.layers.Dense(10)\n", - "])" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "fvyk-HgGwxwl" - }, - "source": [ - "\n", - "学習を行わずとも、モデルを呼び出して、 Eager Execution により、出力を検査することができます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "BsxystjBwxLS" - }, - "outputs": [], - "source": [ - "for images,labels in dataset.take(1):\n", - " print(\"Logits: \", mnist_model(images[0:1]).numpy())" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "Y3PGa8G7qEgB" - }, - "source": [ - "keras モデルは組み込みで学習のループを回すメソッド `fit` がありますが、よりカスタマイズが必要な場合もあるでしょう。 Eager Executionを用いて実装された学習ループのサンプルを以下に示します:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "bzRhM7JDnaEG" - }, - "outputs": [], - "source": [ - "optimizer = tf.keras.optimizers.Adam()\n", - "loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)\n", - "\n", - "loss_history = []" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "tXaupYXRI2YM" - }, - "source": [ - "Note: モデルの状況を確認したいときは、 `tf.debugging` にある assert 機能を利用してください。この機能は Eager Execution と Graph Execution のどちらでも利用できます。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "DDHrigtiCIA4" - }, - "outputs": [], - "source": [ - "def train_step(images, labels):\n", - " with tf.GradientTape() as tape:\n", - " logits = mnist_model(images, training=True)\n", - " \n", - " # assertを入れて出力の型をチェックする。\n", - " tf.debugging.assert_equal(logits.shape, (32, 10))\n", - " \n", - " loss_value = loss_object(labels, logits)\n", - "\n", - " loss_history.append(loss_value.numpy().mean())\n", - " grads = tape.gradient(loss_value, mnist_model.trainable_variables)\n", - " optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "0m1xAXrmqEgJ" - }, - "outputs": [], - "source": [ - "def train():\n", - " for epoch in range(3):\n", - " for (batch, (images, labels)) in enumerate(dataset):\n", - " train_step(images, labels)\n", - " print ('Epoch {} finished'.format(epoch))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "C5dGz0p_nf4W" - }, - "outputs": [], - "source": [ - "train()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "5vG5ql_2vYB5" - }, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "plt.plot(loss_history)\n", - "plt.xlabel('Batch #')\n", - "plt.ylabel('Loss [entropy]')" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "kKpOlHPLqEgl" - }, - "source": [ - "### 値とオプティマイザ\n", - "\n", - "`tf.Variable` オブジェクトは、学習中にアクセスされるミュータブルな `tf.Tensor` 値を格納し、自動微分を容易にします。\n", - "モデルのパラメータは、変数としてクラスにカプセル化できます。\n", - "\n", - "`tf.GradientTape` と共に `tf.Variable` を使うことでモデルパラメータはよりカプセル化されます。たとえば、上の\n", - "の自動微分の例は以下のように書き換えることができます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "nnQLBYmEqEgm" - }, - "outputs": [], - "source": [ - "class Model(tf.keras.Model):\n", - " def __init__(self):\n", - " super(Model, self).__init__()\n", - " self.W = tf.Variable(5., name='weight')\n", - " self.B = tf.Variable(10., name='bias')\n", - " def call(self, inputs):\n", - " return inputs * self.W + self.B\n", - "\n", - "# 3 * 2 + 2を近似するトイデータセット\n", - "NUM_EXAMPLES = 2000\n", - "training_inputs = tf.random.normal([NUM_EXAMPLES])\n", - "noise = tf.random.normal([NUM_EXAMPLES])\n", - "training_outputs = training_inputs * 3 + 2 + noise\n", - "\n", - "# オプティマイズ対象のloss関数\n", - "def loss(model, inputs, targets):\n", - " error = model(inputs) - targets\n", - " return tf.reduce_mean(tf.square(error))\n", - "\n", - "def grad(model, inputs, targets):\n", - " with tf.GradientTape() as tape:\n", - " loss_value = loss(model, inputs, targets)\n", - " return tape.gradient(loss_value, [model.W, model.B])\n", - "\n", - "# 定義:\n", - "# 1. モデル\n", - "# 2. モデルパラメータに関する損失関数の導関数\n", - "# 3. 導関数に基づいて変数を更新するストラテジ。\n", - "model = Model()\n", - "optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)\n", - "\n", - "print(\"Initial loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", - "\n", - "# Training loop\n", - "for i in range(300):\n", - " grads = grad(model, training_inputs, training_outputs)\n", - " optimizer.apply_gradients(zip(grads, [model.W, model.B]))\n", - " if i % 20 == 0:\n", - " print(\"Loss at step {:03d}: {:.3f}\".format(i, loss(model, training_inputs, training_outputs)))\n", - "\n", - "print(\"Final loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", - "print(\"W = {}, B = {}\".format(model.W.numpy(), model.B.numpy()))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "rPjb8nRWqEgr" - }, - "source": [ - "## Eager Execution の途中でオブジェクトのステータスを使用する\n", - "\n", - "TF 1.x の Graph Execution では、プログラムの状態(変数など)は global collection に格納され、それらの存続期間は `tf.Session` オブジェクトによって管理されます。\n", - "対照的に、 Eager Execution の間、状態オブジェクトの存続期間は、対応する Python オブジェクトの存続期間によって決定されます。\n", - "\n", - "### 変数とオブジェクト\n", - "\n", - "Eager Execution の間、変数はオブジェクトへの最後の参照が削除され、その後削除されるまで存続します。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "A2boS674qEgs" - }, - "outputs": [], - "source": [ - "if tf.test.is_gpu_available():\n", - " with tf.device(\"gpu:0\"):\n", - " v = tf.Variable(tf.random.normal([1000, 1000]))\n", - " v = None # v は GPU メモリを利用しなくなる" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "scMjg6L6qEgv" - }, - "source": [ - "### オブジェクトベースの保存\n", - "\n", - "このセクションは、[チェックポイントの学習の手引き](./ checkpoints.ipynb) の省略版です。\n", - "\n", - "`tf.train.Checkpoint` はチェックポイントを用いて `tf.Variable` を保存および復元することができます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "7z5xRfdHzZOQ" - }, - "outputs": [], - "source": [ - "x = tf.Variable(10.)\n", - "checkpoint = tf.train.Checkpoint(x=x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "IffrUVG7zyVb" - }, - "outputs": [], - "source": [ - "x.assign(2.) # 新しい値を変数に代入して保存する。\n", - "checkpoint_path = './ckpt/'\n", - "checkpoint.save('./ckpt/')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "eMT9koCoqEgw" - }, - "outputs": [], - "source": [ - "x.assign(11.) # 保存後に変数の値を変える。\n", - "\n", - "# チェックポイントから変数を復元する\n", - "checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))\n", - "\n", - "print(x) # => 2.0" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "vbFnP-yLqEgx" - }, - "source": [ - "モデルを保存して読み込むために、 `tf.train.Checkpoint` は隠れ変数なしにオブジェクトの内部状態を保存します。 `モデル`、 `オプティマイザ` 、そしてグローバルステップの状態を記録するには、それらを `tf.train.Checkpoint` に渡します。" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "hWZHyAXMqEg0" - }, - "outputs": [], - "source": [ - "import os\n", - "\n", - "model = tf.keras.Sequential([\n", - " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", - " tf.keras.layers.GlobalAveragePooling2D(),\n", - " tf.keras.layers.Dense(10)\n", - "])\n", - "optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n", - "checkpoint_dir = 'path/to/model_dir'\n", - "if not os.path.exists(checkpoint_dir):\n", - " os.makedirs(checkpoint_dir)\n", - "checkpoint_prefix = os.path.join(checkpoint_dir, \"ckpt\")\n", - "root = tf.train.Checkpoint(optimizer=optimizer,\n", - " model=model)\n", - "\n", - "root.save(checkpoint_prefix)\n", - "root.restore(tf.train.latest_checkpoint(checkpoint_dir))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "R-ITwkBCF6GJ" - }, - "source": [ - "多くの学習ループでは、変数は `tf.train..Checkpoint.restore` が呼ばれたあとに作成されます。これらの変数は作成されてすぐに復元され、チェックポイントがすべてロードされたことを確認するためのアサーションが利用可能になります。詳しくは、 [guide to training checkpoints](./checkpoints.ipynb) を見てください。" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "3yoD0VJ7qEg3" - }, - "source": [ - "### オブジェクト指向メトリクス\n", - "\n", - "`tfe.keras.metrics`はオブジェクトとして保存されます。新しいデータを呼び出し可能オブジェクトに渡してメトリクスを更新し、 `tfe.keras.metrics.result`メソッドを使って結果を取得します。次に例を示します:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "9ccu0iAaqEg5" - }, - "outputs": [], - "source": [ - "m = tf.keras.metrics.Mean(\"loss\")\n", - "m(0)\n", - "m(5)\n", - "m.result() # => 2.5\n", - "m([8, 9])\n", - "m.result() # => 5.5" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "xEL4yJe5qEhD" - }, - "source": [ - "## 高度な自動分類トピック\n", - "\n", - "### 動的なモデル\n", - "\n", - "`tf.GradientTape` は動的モデルでも使うことができます。 \n", - "以下の [バックトラックライン検索](https://wikipedia.org/wiki/Backtracking_line_search)\n", - "アルゴリズムの例は、複雑な制御フローにもかかわらず\n", - "勾配があり、微分可能であることを除いて、通常の NumPy コードのように見えます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "L518n5dkqEhE" - }, - "outputs": [], - "source": [ - "def line_search_step(fn, init_x, rate=1.0):\n", - " with tf.GradientTape() as tape:\n", - " # 変数は自動的に記録されるが、Tensorは手動でウォッチする\n", - " tape.watch(init_x)\n", - " value = fn(init_x)\n", - " grad = tape.gradient(value, init_x)\n", - " grad_norm = tf.reduce_sum(grad * grad)\n", - " init_value = value\n", - " while value > init_value - rate * grad_norm:\n", - " x = init_x - rate * grad\n", - " value = fn(x)\n", - " rate /= 2.0\n", - " return x, value" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "gieGOf_DqEhK" - }, - "source": [ - "### カスタム勾配\n", - "\n", - "カスタム勾配は、勾配を上書きする簡単な方法です。 フォワード関数では、\n", - "入力、出力、または中間結果に関する勾配を定義します。たとえば、逆方向パスにおいて勾配のノルムを切り取る簡単な方法は次のとおりです:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "-OwwsWUAqEhK" - }, - "outputs": [], - "source": [ - "@tf.custom_gradient\n", - "def clip_gradient_by_norm(x, norm):\n", - " y = tf.identity(x)\n", - " def grad_fn(dresult):\n", - " return [tf.clip_by_norm(dresult, norm), None]\n", - " return y, grad_fn" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "JPLDHkF_qEhN" - }, - "source": [ - "カスタム勾配は、一連の演算に対して数値的に安定した勾配を提供するために共通的に使用されます。:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "24WiLROnqEhO" - }, - "outputs": [], - "source": [ - "def log1pexp(x):\n", - " return tf.math.log(1 + tf.exp(x))\n", - "\n", - "def grad_log1pexp(x):\n", - " with tf.GradientTape() as tape:\n", - " tape.watch(x)\n", - " value = log1pexp(x)\n", - " return tape.gradient(value, x)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "n8fq69r9-B-c" - }, - "outputs": [], - "source": [ - "# 購買計算は x = 0 のときはうまくいく。\n", - "grad_log1pexp(tf.constant(0.)).numpy()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "_VFSU0mG-FSp" - }, - "outputs": [], - "source": [ - "# しかし、x = 100のときは数値的不安定により失敗する。\n", - "grad_log1pexp(tf.constant(100.)).numpy()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "-VcTR34rqEhQ" - }, - "source": [ - "ここで、 `log1pexp` 関数はカスタム勾配を用いて解析的に単純化することができます。\n", - "以下の実装は、フォワードパスの間に計算された `tf.exp(x)` の値を\n", - "再利用します—冗長な計算を排除することでより効率的になります:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "Q7nvfx_-qEhS" - }, - "outputs": [], - "source": [ - "@tf.custom_gradient\n", - "def log1pexp(x):\n", - " e = tf.exp(x)\n", - " def grad(dy):\n", - " return dy * (1 - 1 / (1 + e))\n", - " return tf.math.log(1 + e), grad\n", - "\n", - "def grad_log1pexp(x):\n", - " with tf.GradientTape() as tape:\n", - " tape.watch(x)\n", - " value = log1pexp(x)\n", - " return tape.gradient(value, x)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "5gHPKMfl-Kge" - }, - "outputs": [], - "source": [ - "# 上と同様に、勾配計算はx = 0のときにはうまくいきます。\n", - "grad_log1pexp(tf.constant(0.)).numpy()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "u38MOfz3-MDE" - }, - "outputs": [], - "source": [ - "# また、勾配計算はx = 100でも機能します。\n", - "grad_log1pexp(tf.constant(100.)).numpy()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "rnZXjfQzqEhV" - }, - "source": [ - "## パフォーマンス\n", - "\n", - "Eager Executionの間、計算は自動的にGPUにオフロードされます。計算を実行するデバイスを指定したい場合は、\n", - "`tf.device( '/ gpu:0')` ブロック(もしくはCPUを指定するブロック)で囲むことで指定できます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "Ac9Y64H-qEhX" - }, - "outputs": [], - "source": [ - "import time\n", - "\n", - "def measure(x, steps):\n", - " # TensorFlowはGPUを初めて使用するときに初期化するため、時間計測対象からは除外する。\n", - " tf.matmul(x, x)\n", - " start = time.time()\n", - " for i in range(steps):\n", - " x = tf.matmul(x, x)\n", - " # tf.matmulは、行列乗算が完了する前に戻ることができる。\n", - " # (たとえば、CUDAストリームにオペレーションをエンキューした後に戻すことができる)。\n", - " # 以下のx.numpy()呼び出しは、すべてのキューに入れられたオペレーションが完了したことを確認する。\n", - " # (そして結果をホストメモリにコピーするため、計算時間は単純なmatmulオペレーションよりも多くのことを含む時間になる。)\n", - " _ = x.numpy()\n", - " end = time.time()\n", - " return end - start\n", - "\n", - "shape = (1000, 1000)\n", - "steps = 200\n", - "print(\"Time to multiply a {} matrix by itself {} times:\".format(shape, steps))\n", - "\n", - "# CPU上で実行するとき:\n", - "with tf.device(\"/cpu:0\"):\n", - " print(\"CPU: {} secs\".format(measure(tf.random_normal(shape), steps)))\n", - "\n", - "# GPU上で実行するとき(GPUが利用できれば):\n", - "if tf.test.is_gpu_available():\n", - " with tf.device(\"/gpu:0\"):\n", - " print(\"GPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", - "else:\n", - " print(\"GPU: not found\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "RLw3IS7UqEhe" - }, - "source": [ - "`tf.Tensor` オブジェクトはそのオブジェクトに対するオペレーションを実行するために別のデバイスにコピーすることができます:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "attributes": { - "classes": [ - "py" - ], - "id": "" - }, - "colab": {}, - "colab_type": "code", - "id": "ny6LX2BVqEhf" - }, - "outputs": [], - "source": [ - "if tf.test.is_gpu_available():\n", - " x = tf.random.normal([10, 10])\n", - "\n", - " x_gpu0 = x.gpu()\n", - " x_cpu = x.cpu()\n", - "\n", - " _ = tf.matmul(x_cpu, x_cpu) # CPU上で実行するとき\n", - " _ = tf.matmul(x_gpu0, x_gpu0) # GPU:0上で実行するとき" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "oA_qaII3-p6c" - }, - "source": [ - "### ベンチマーク\n", - "\n", - "GPUでの\n", - "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", - "の学習のような、計算量の多いモデルの場合は、Eager Executionのパフォーマンスは `tf.function` のパフォーマンスに匹敵します。\n", - "しかし、この2つの環境下のパフォーマンスの違いは計算量の少ないモデルではより大きくなり、小さなたくさんのオペレーションからなるモデルでホットコードパスを最適化するためにやるべきことがあります。\n", - "\n", - "## functionsの利用\n", - "\n", - "Eager Execution は開発とデバッグをより対話的にしますが、\n", - "TensorFlow 1.x スタイルの Graph Execution は分散学習、パフォーマンスの最適化、そしてプロダクション環境へのデプロイの観点で利点があります。\n", - "\n", - "2つの手法のギャップを埋めるために、 TensorFlow 2.0 は `tf.function` API に似た `function` を紹介します。\n", - "詳しくは、 [Autograph](./autograph.ipynb) のガイドを見てください。\n" - ] - } - ], - "metadata": { - "colab": { - "collapsed_sections": [], - "name": "Eager.ipynb", - "private_outputs": true, - "provenance": [], - "toc_visible": true, - "version": "0.3.2" - }, - "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.7.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "eager.ipynb", + "version": "0.3.2", + "provenance": [], + "private_outputs": true, + "collapsed_sections": [], + "toc_visible": true + }, + "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.7.3" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "CCQY7jpBfMur" + }, + "source": [ + "##### Copyright 2018 The TensorFlow Authors." + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "colab_type": "code", + "id": "z6X9omPnfO_h", + "colab": {} + }, + "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." + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "2QQJJyDzqGRb" + }, + "source": [ + "# Eager Execution の基本" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "B1xdylywqUSX" + }, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " View on TensorFlow.org\n", + " \n", + " Run in Google Colab\n", + " \n", + " View source on GitHub\n", + " \n", + " Download notebook\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MpAwFqFL5Scf", + "colab_type": "text" + }, + "source": [ + "Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳は**ベストエフォート**であるため、この翻訳が正確であることや[英語の公式ドキュメント](https://www.tensorflow.org/?hl=en)の 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリ[tensorflow/docs](https://github.com/tensorflow/docs)にプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [docs-ja@tensorflow.org メーリングリスト](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ja)にご連絡ください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "EGjDcGxIqEfX" + }, + "source": [ + "\n", + "\n", + "Tensorflow の Eager Execution は、計算グラフの作成と評価を同時におこなう命令的なプログラミングを行うための環境です:\n", + "オペレーションはあとで実行するための計算グラフでなく、具体的な計算結果の値を返します。\n", + "この方法を用いることにより、初心者にとって TensorFlow を始めやすくなり、またモデルのデバッグも行いやすくなります。\n", + "さらにコードの記述量も削減されます。\n", + "このガイドの内容を実行するためには、対話的インタープリタ `python` を起動し、以下のコードサンプルを実行してください。\n", + "\n", + "Eager Execution は研究や実験のための柔軟な機械学習環境として、以下を提供します。\n", + "\n", + "* *直感的なインタフェース*— Python のデータ構造を使用して、コードをナチュラルに記述することができます。スモールなモデルとデータに対してすばやく実験を繰り返すことができます。\n", + "* *より簡単なデバッグ*— ops を直接呼び出すことで、実行中のモデルを調査したり、変更をテストすることができます。 Python 標準のデバッグツールを用いて即座にエラーのレポーティングができます。\n", + "* *自然な制御フロー*— TensorFlow のグラフ制御フローの代わりに Python の制御フローを利用するため、動的なモデルのパラメータ変更をシンプルに行うことができます。\n", + " \n", + "Eager Execution は Tensorflow のほとんどのオペレーションとGPUアクセラレーションをサポートします。\n", + "\n", + "Note: いくつかのモデルは Eager Execution を有効化することでオーバヘッドが増える可能性があります。\n", + "パフォーマンス改善を行っていますが、もしも問題を発見したら、バグ報告してベンチマークを共有してください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RBAeIwOMrYk8" + }, + "source": [ + "## セットアップと基本的な使い方" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "ByNsp4VqqEfa", + "colab": {} + }, + "source": [ + "from __future__ import absolute_import, division, print_function, unicode_literals\n", + "\n", + "!pip install tensorflow-gpu==2.0.0-beta1\n", + "import tensorflow as tf\n", + "\n", + "import cProfile" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "48P3-8q4qEfe" + }, + "source": [ + "TensorFlow 2.0 では、 Eager Execution はデフォルトで有効化されます。" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "7aFsD8csqEff", + "colab": {} + }, + "source": [ + "tf.executing_eagerly()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "x_G1zZT5qEfh" + }, + "source": [ + "これで TensorFlow のオペレーションを実行してみましょう。結果はすぐに返されます。" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "9gsI54pbqEfj", + "colab": {} + }, + "source": [ + "x = [[2.]]\n", + "m = tf.matmul(x, x)\n", + "print(\"hello, {}\".format(m))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "ajFn6qsdqEfl" + }, + "source": [ + "Eager Execution を有効化することで、 TensorFlow の挙動は変わります—TensorFlowは即座に式を評価して結果をPythonに返すようになります。\n", + "`tf.Tensor` オブジェクトは計算グラフのノードへのシンボリックハンドルの代わりに具体的な値を参照します。\n", + "セッションの中で構築して実行する計算グラフが存在しないため、`print()`やデバッガを使って容易に結果を調べることができます。\n", + "勾配計算を終了することなくテンソル値を評価、出力、およびチェックすることができます。\n", + "\n", + "Eager Execution は、[NumPy](http://www.numpy.org/)と一緒に使うことができます。\n", + "NumPy のオペレーションは、`tf.Tensor`を引数として受け取ることができます。\n", + "TensorFlow [math operations](https://www.tensorflow.org/api_guides/python/math_ops) はPython オブジェクトと Numpy array を `tf.Tensor` にコンバートします。\n", + "`tf.Tensor.numpy` メソッドはオブジェクトの値を NumPy の `ndarray` 形式で返します。" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "sTO0_5TYqz1n", + "colab": {} + }, + "source": [ + "a = tf.constant([[1, 2],\n", + " [3, 4]])\n", + "print(a)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "Dp14YT8Gq4r1", + "colab": {} + }, + "source": [ + "# ブロードキャストのサポート\n", + "b = tf.add(a, 1)\n", + "print(b)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "69p3waMfq8cQ", + "colab": {} + }, + "source": [ + "# オペレータのオーバーロードがサポートされている\n", + "print(a * b)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "Ui025t1qqEfm", + "colab": {} + }, + "source": [ + "# NumPy valueの使用\n", + "import numpy as np\n", + "\n", + "c = np.multiply(a, b)\n", + "print(c)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "Tq_aFRzWrCua", + "colab": {} + }, + "source": [ + "# Tensor から numpy の値を得る\n", + "print(a.numpy())\n", + "# => [[1 2]\n", + "# [3 4]]" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "H08f9ss9qEft" + }, + "source": [ + "## 動的な制御フロー\n", + "\n", + "Eager Execution の主要なメリットは、モデルを実行する際にホスト言語のすべての機能性が利用できることです。\n", + "たとえば、[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz)が簡単に書けます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "0fudRMeUqEfu", + "colab": {} + }, + "source": [ + "def fizzbuzz(max_num):\n", + " counter = tf.constant(0)\n", + " max_num = tf.convert_to_tensor(max_num)\n", + " for num in range(1, max_num.numpy()+1):\n", + " num = tf.constant(num)\n", + " if int(num % 3) == 0 and int(num % 5) == 0:\n", + " print('FizzBuzz')\n", + " elif int(num % 3) == 0:\n", + " print('Fizz')\n", + " elif int(num % 5) == 0:\n", + " print('Buzz')\n", + " else:\n", + " print(num.numpy())\n", + " counter += 1" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "P2cKknQWrJLB", + "colab": {} + }, + "source": [ + "fizzbuzz(15)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "7kA-aC3BqEfy" + }, + "source": [ + "この関数はテンソル値に依存する条件式を持ち、実行時にこれらの値を表示します。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8huKpuuAwICq" + }, + "source": [ + "## Eager Execution による学習" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "mp2lCCZYrxHd" + }, + "source": [ + "### 勾配の計算\n", + "\n", + "[自動微分](https://en.wikipedia.org/wiki/Automatic_differentiation)はニューラルネットワークの学習で利用される[バックプロパゲーション](https://en.wikipedia.org/wiki/Backpropagation)などの機械学習アルゴリズムの実装を行う上で便利です。\n", + "Eager Executionでは、勾配計算をあとで行うためのオペレーションをトレースするために`tf.GradientTape` を利用します。\n", + "\n", + "Eager Execution では、学習や購買計算に, `tf.GradientTape` を利用できます。これは複雑な学習ループを実行するときに特に役立ちます。\n", + "\n", + "各呼び出し中に異なるオペレーションが発生する可能性があるため、すべての forward-pass オペレーションは一つの「テープ」に記録されます。勾配を計算するには、テープを逆方向に再生してから破棄します。特定の `tf.GradientTape`は一つのグラデーションしか計算できません。後続の呼び出しは実行時エラーをスローします。" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "7g1yWiSXqEf-", + "colab": {} + }, + "source": [ + "w = tf.Variable([[1.0]])\n", + "with tf.GradientTape() as tape:\n", + " loss = w * w\n", + "\n", + "grad = tape.gradient(loss, w)\n", + "print(grad) # => tf.Tensor([[ 2.]], shape=(1, 1), dtype=float32)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vkHs32GqweYS" + }, + "source": [ + "### モデル学習\n", + "\n", + "以下の example は MNIST という手書き数字分類を行うマルチレイヤーモデルを作成します。\n", + "Eager Execution 環境における学習可能なグラフを構築するためのオプティマイザーとレイヤーAPIを提示します。" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "38kymXZowhhz", + "colab": {} + }, + "source": [ + "# mnist データのを取得し、フォーマットする\n", + "(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data()\n", + "\n", + "dataset = tf.data.Dataset.from_tensor_slices(\n", + " (tf.cast(mnist_images[...,tf.newaxis]/255, tf.float32),\n", + " tf.cast(mnist_labels,tf.int64)))\n", + "dataset = dataset.shuffle(1000).batch(32)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "rl1K8rOowmwT", + "colab": {} + }, + "source": [ + "# モデルを構築する\n", + "mnist_model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu',\n", + " input_shape=(None, None, 1)),\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", + " tf.keras.layers.GlobalAveragePooling2D(),\n", + " tf.keras.layers.Dense(10)\n", + "])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fvyk-HgGwxwl" + }, + "source": [ + "\n", + "学習を行わずとも、モデルを呼び出して、 Eager Execution により、出力を検査することができます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "BsxystjBwxLS", + "colab": {} + }, + "source": [ + "for images,labels in dataset.take(1):\n", + " print(\"Logits: \", mnist_model(images[0:1]).numpy())" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Y3PGa8G7qEgB" + }, + "source": [ + "keras モデルは組み込みで学習のループを回すメソッド `fit` がありますが、よりカスタマイズが必要な場合もあるでしょう。 Eager Executionを用いて実装された学習ループのサンプルを以下に示します:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "bzRhM7JDnaEG", + "colab": {} + }, + "source": [ + "optimizer = tf.keras.optimizers.Adam()\n", + "loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)\n", + "\n", + "loss_history = []" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "tXaupYXRI2YM" + }, + "source": [ + "Note: モデルの状況を確認したいときは、 `tf.debugging` にある assert 機能を利用してください。この機能は Eager Execution と Graph Execution のどちらでも利用できます。" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "DDHrigtiCIA4", + "colab": {} + }, + "source": [ + "def train_step(images, labels):\n", + " with tf.GradientTape() as tape:\n", + " logits = mnist_model(images, training=True)\n", + " \n", + " # assertを入れて出力の型をチェックする。\n", + " tf.debugging.assert_equal(logits.shape, (32, 10))\n", + " \n", + " loss_value = loss_object(labels, logits)\n", + "\n", + " loss_history.append(loss_value.numpy().mean())\n", + " grads = tape.gradient(loss_value, mnist_model.trainable_variables)\n", + " optimizer.apply_gradients(zip(grads, mnist_model.trainable_variables))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "0m1xAXrmqEgJ", + "colab": {} + }, + "source": [ + "def train():\n", + " for epoch in range(3):\n", + " for (batch, (images, labels)) in enumerate(dataset):\n", + " train_step(images, labels)\n", + " print ('Epoch {} finished'.format(epoch))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "C5dGz0p_nf4W", + "colab": {} + }, + "source": [ + "train()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "5vG5ql_2vYB5", + "colab": {} + }, + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.plot(loss_history)\n", + "plt.xlabel('Batch #')\n", + "plt.ylabel('Loss [entropy]')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "kKpOlHPLqEgl" + }, + "source": [ + "### 値とオプティマイザ\n", + "\n", + "`tf.Variable` オブジェクトは、学習中にアクセスされるミュータブルな `tf.Tensor` 値を格納し、自動微分を容易にします。\n", + "モデルのパラメータは、変数としてクラスにカプセル化できます。\n", + "\n", + "`tf.GradientTape` と共に `tf.Variable` を使うことでモデルパラメータはよりカプセル化されます。たとえば、上の\n", + "の自動微分の例は以下のように書き換えることができます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "nnQLBYmEqEgm", + "colab": {} + }, + "source": [ + "class Model(tf.keras.Model):\n", + " def __init__(self):\n", + " super(Model, self).__init__()\n", + " self.W = tf.Variable(5., name='weight')\n", + " self.B = tf.Variable(10., name='bias')\n", + " def call(self, inputs):\n", + " return inputs * self.W + self.B\n", + "\n", + "# 3 * 2 + 2を近似するトイデータセット\n", + "NUM_EXAMPLES = 2000\n", + "training_inputs = tf.random.normal([NUM_EXAMPLES])\n", + "noise = tf.random.normal([NUM_EXAMPLES])\n", + "training_outputs = training_inputs * 3 + 2 + noise\n", + "\n", + "# オプティマイズ対象のloss関数\n", + "def loss(model, inputs, targets):\n", + " error = model(inputs) - targets\n", + " return tf.reduce_mean(tf.square(error))\n", + "\n", + "def grad(model, inputs, targets):\n", + " with tf.GradientTape() as tape:\n", + " loss_value = loss(model, inputs, targets)\n", + " return tape.gradient(loss_value, [model.W, model.B])\n", + "\n", + "# 定義:\n", + "# 1. モデル\n", + "# 2. モデルパラメータに関する損失関数の導関数\n", + "# 3. 導関数に基づいて変数を更新するストラテジ。\n", + "model = Model()\n", + "optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)\n", + "\n", + "print(\"Initial loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", + "\n", + "# Training loop\n", + "for i in range(300):\n", + " grads = grad(model, training_inputs, training_outputs)\n", + " optimizer.apply_gradients(zip(grads, [model.W, model.B]))\n", + " if i % 20 == 0:\n", + " print(\"Loss at step {:03d}: {:.3f}\".format(i, loss(model, training_inputs, training_outputs)))\n", + "\n", + "print(\"Final loss: {:.3f}\".format(loss(model, training_inputs, training_outputs)))\n", + "print(\"W = {}, B = {}\".format(model.W.numpy(), model.B.numpy()))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rPjb8nRWqEgr" + }, + "source": [ + "## Eager Execution の途中でオブジェクトのステータスを使用する\n", + "\n", + "TF 1.x の Graph Execution では、プログラムの状態(変数など)は global collection に格納され、それらの存続期間は `tf.Session` オブジェクトによって管理されます。\n", + "対照的に、 Eager Execution の間、状態オブジェクトの存続期間は、対応する Python オブジェクトの存続期間によって決定されます。\n", + "\n", + "### 変数とオブジェクト\n", + "\n", + "Eager Execution の間、変数はオブジェクトへの最後の参照が削除され、その後削除されるまで存続します。" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "A2boS674qEgs", + "colab": {} + }, + "source": [ + "if tf.test.is_gpu_available():\n", + " with tf.device(\"gpu:0\"):\n", + " print(\"GPU enabled\")\n", + " v = tf.Variable(tf.random.normal([1000, 1000]))\n", + " v = None # v は GPU メモリを利用しなくなる" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "scMjg6L6qEgv" + }, + "source": [ + "### オブジェクトベースの保存\n", + "\n", + "このセクションは、[チェックポイントの学習の手引き](./ checkpoints.ipynb) の省略版です。\n", + "\n", + "`tf.train.Checkpoint` はチェックポイントを用いて `tf.Variable` を保存および復元することができます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "7z5xRfdHzZOQ", + "colab": {} + }, + "source": [ + "x = tf.Variable(10.)\n", + "checkpoint = tf.train.Checkpoint(x=x)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "IffrUVG7zyVb", + "colab": {} + }, + "source": [ + "x.assign(2.) # 新しい値を変数に代入して保存する。\n", + "checkpoint_path = './ckpt/'\n", + "checkpoint.save('./ckpt/')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "eMT9koCoqEgw", + "colab": {} + }, + "source": [ + "x.assign(11.) # 保存後に変数の値を変える。\n", + "\n", + "# チェックポイントから変数を復元する\n", + "checkpoint.restore(tf.train.latest_checkpoint(checkpoint_path))\n", + "\n", + "print(x) # => 2.0" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vbFnP-yLqEgx" + }, + "source": [ + "モデルを保存して読み込むために、 `tf.train.Checkpoint` は隠れ変数なしにオブジェクトの内部状態を保存します。 `モデル`、 `オプティマイザ` 、そしてグローバルステップの状態を記録するには、それらを `tf.train.Checkpoint` に渡します。" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "hWZHyAXMqEg0", + "colab": {} + }, + "source": [ + "import os\n", + "\n", + "model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(16,[3,3], activation='relu'),\n", + " tf.keras.layers.GlobalAveragePooling2D(),\n", + " tf.keras.layers.Dense(10)\n", + "])\n", + "optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)\n", + "checkpoint_dir = 'path/to/model_dir'\n", + "if not os.path.exists(checkpoint_dir):\n", + " os.makedirs(checkpoint_dir)\n", + "checkpoint_prefix = os.path.join(checkpoint_dir, \"ckpt\")\n", + "root = tf.train.Checkpoint(optimizer=optimizer,\n", + " model=model)\n", + "\n", + "root.save(checkpoint_prefix)\n", + "root.restore(tf.train.latest_checkpoint(checkpoint_dir))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "R-ITwkBCF6GJ" + }, + "source": [ + "多くの学習ループでは、変数は `tf.train..Checkpoint.restore` が呼ばれたあとに作成されます。これらの変数は作成されてすぐに復元され、チェックポイントがすべてロードされたことを確認するためのアサーションが利用可能になります。詳しくは、 [guide to training checkpoints](./checkpoints.ipynb) を見てください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "3yoD0VJ7qEg3" + }, + "source": [ + "### オブジェクト指向メトリクス\n", + "\n", + "`tfe.keras.metrics`はオブジェクトとして保存されます。新しいデータを呼び出し可能オブジェクトに渡してメトリクスを更新し、 `tfe.keras.metrics.result`メソッドを使って結果を取得します。次に例を示します:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "9ccu0iAaqEg5", + "colab": {} + }, + "source": [ + "m = tf.keras.metrics.Mean(\"loss\")\n", + "m(0)\n", + "m(5)\n", + "m.result() # => 2.5\n", + "m([8, 9])\n", + "m.result() # => 5.5" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "xEL4yJe5qEhD" + }, + "source": [ + "## 高度な自動分類トピック\n", + "\n", + "### 動的なモデル\n", + "\n", + "`tf.GradientTape` は動的モデルでも使うことができます。 \n", + "以下の [バックトラックライン検索](https://wikipedia.org/wiki/Backtracking_line_search)\n", + "アルゴリズムの例は、複雑な制御フローにもかかわらず\n", + "勾配があり、微分可能であることを除いて、通常の NumPy コードのように見えます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "L518n5dkqEhE", + "colab": {} + }, + "source": [ + "def line_search_step(fn, init_x, rate=1.0):\n", + " with tf.GradientTape() as tape:\n", + " # 変数は自動的に記録されるが、Tensorは手動でウォッチする\n", + " tape.watch(init_x)\n", + " value = fn(init_x)\n", + " grad = tape.gradient(value, init_x)\n", + " grad_norm = tf.reduce_sum(grad * grad)\n", + " init_value = value\n", + " while value > init_value - rate * grad_norm:\n", + " x = init_x - rate * grad\n", + " value = fn(x)\n", + " rate /= 2.0\n", + " return x, value" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "gieGOf_DqEhK" + }, + "source": [ + "### カスタム勾配\n", + "\n", + "カスタム勾配は、勾配を上書きする簡単な方法です。 フォワード関数では、\n", + "入力、出力、または中間結果に関する勾配を定義します。たとえば、逆方向パスにおいて勾配のノルムを切り取る簡単な方法は次のとおりです:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "-OwwsWUAqEhK", + "colab": {} + }, + "source": [ + "@tf.custom_gradient\n", + "def clip_gradient_by_norm(x, norm):\n", + " y = tf.identity(x)\n", + " def grad_fn(dresult):\n", + " return [tf.clip_by_norm(dresult, norm), None]\n", + " return y, grad_fn" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "JPLDHkF_qEhN" + }, + "source": [ + "カスタム勾配は、一連の演算に対して数値的に安定した勾配を提供するために共通的に使用されます。:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "24WiLROnqEhO", + "colab": {} + }, + "source": [ + "def log1pexp(x):\n", + " return tf.math.log(1 + tf.exp(x))\n", + "\n", + "def grad_log1pexp(x):\n", + " with tf.GradientTape() as tape:\n", + " tape.watch(x)\n", + " value = log1pexp(x)\n", + " return tape.gradient(value, x)\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "n8fq69r9-B-c", + "colab": {} + }, + "source": [ + "# 購買計算は x = 0 のときはうまくいく。\n", + "grad_log1pexp(tf.constant(0.)).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "_VFSU0mG-FSp", + "colab": {} + }, + "source": [ + "# しかし、x = 100のときは数値的不安定により失敗する。\n", + "grad_log1pexp(tf.constant(100.)).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "-VcTR34rqEhQ" + }, + "source": [ + "ここで、 `log1pexp` 関数はカスタム勾配を用いて解析的に単純化することができます。\n", + "以下の実装は、フォワードパスの間に計算された `tf.exp(x)` の値を\n", + "再利用します—冗長な計算を排除することでより効率的になります:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "Q7nvfx_-qEhS", + "colab": {} + }, + "source": [ + "@tf.custom_gradient\n", + "def log1pexp(x):\n", + " e = tf.exp(x)\n", + " def grad(dy):\n", + " return dy * (1 - 1 / (1 + e))\n", + " return tf.math.log(1 + e), grad\n", + "\n", + "def grad_log1pexp(x):\n", + " with tf.GradientTape() as tape:\n", + " tape.watch(x)\n", + " value = log1pexp(x)\n", + " return tape.gradient(value, x)\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "5gHPKMfl-Kge", + "colab": {} + }, + "source": [ + "# 上と同様に、勾配計算はx = 0のときにはうまくいきます。\n", + "grad_log1pexp(tf.constant(0.)).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "u38MOfz3-MDE", + "colab": {} + }, + "source": [ + "# また、勾配計算はx = 100でも機能します。\n", + "grad_log1pexp(tf.constant(100.)).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rnZXjfQzqEhV" + }, + "source": [ + "## パフォーマンス\n", + "\n", + "Eager Executionの間、計算は自動的にGPUにオフロードされます。計算を実行するデバイスを指定したい場合は、\n", + "`tf.device( '/ gpu:0')` ブロック(もしくはCPUを指定するブロック)で囲むことで指定できます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "Ac9Y64H-qEhX", + "colab": {} + }, + "source": [ + "import time\n", + "\n", + "def measure(x, steps):\n", + " # TensorFlowはGPUを初めて使用するときに初期化するため、時間計測対象からは除外する。\n", + " tf.matmul(x, x)\n", + " start = time.time()\n", + " for i in range(steps):\n", + " x = tf.matmul(x, x)\n", + " # tf.matmulは、行列乗算が完了する前に戻ることができる。\n", + " # (たとえば、CUDAストリームにオペレーションをエンキューした後に戻すことができる)。\n", + " # 以下のx.numpy()呼び出しは、すべてのキューに入れられたオペレーションが完了したことを確認する。\n", + " # (そして結果をホストメモリにコピーするため、計算時間は単純なmatmulオペレーションよりも多くのことを含む時間になる。)\n", + " _ = x.numpy()\n", + " end = time.time()\n", + " return end - start\n", + "\n", + "shape = (1000, 1000)\n", + "steps = 200\n", + "print(\"Time to multiply a {} matrix by itself {} times:\".format(shape, steps))\n", + "\n", + "# CPU上で実行するとき:\n", + "with tf.device(\"/cpu:0\"):\n", + " print(\"CPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", + "\n", + "# GPU上で実行するとき(GPUが利用できれば):\n", + "if tf.test.is_gpu_available():\n", + " with tf.device(\"/gpu:0\"):\n", + " print(\"GPU: {} secs\".format(measure(tf.random.normal(shape), steps)))\n", + "else:\n", + " print(\"GPU: not found\")" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RLw3IS7UqEhe" + }, + "source": [ + "`tf.Tensor` オブジェクトはそのオブジェクトに対するオペレーションを実行するために別のデバイスにコピーすることができます:" + ] + }, + { + "cell_type": "code", + "metadata": { + "attributes": { + "classes": [ + "py" + ], + "id": "" + }, + "colab_type": "code", + "id": "ny6LX2BVqEhf", + "colab": {} + }, + "source": [ + "if tf.test.is_gpu_available():\n", + " x = tf.random.normal([10, 10])\n", + "\n", + " x_gpu0 = x.gpu()\n", + " x_cpu = x.cpu()\n", + "\n", + " _ = tf.matmul(x_cpu, x_cpu) # CPU上で実行するとき\n", + " _ = tf.matmul(x_gpu0, x_gpu0) # GPU:0上で実行するとき" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "oA_qaII3-p6c" + }, + "source": [ + "### ベンチマーク\n", + "\n", + "GPUでの\n", + "[ResNet50](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/eager/python/examples/resnet50)\n", + "の学習のような、計算量の多いモデルの場合は、Eager Executionのパフォーマンスは `tf.function` のパフォーマンスに匹敵します。\n", + "しかし、この2つの環境下のパフォーマンスの違いは計算量の少ないモデルではより大きくなり、小さなたくさんのオペレーションからなるモデルでホットコードパスを最適化するためにやるべきことがあります。\n", + "\n", + "## functionsの利用\n", + "\n", + "Eager Execution は開発とデバッグをより対話的にしますが、\n", + "TensorFlow 1.x スタイルの Graph Execution は分散学習、パフォーマンスの最適化、そしてプロダクション環境へのデプロイの観点で利点があります。\n", + "\n", + "2つの手法のギャップを埋めるために、 TensorFlow 2.0 は `tf.function` API に似た `function` を紹介します。\n", + "詳しくは、 [Autograph](./autograph.ipynb) のガイドを見てください。\n" + ] + } + ] +} \ No newline at end of file