Skip to content

Instantly share code, notes, and snippets.

@AseiSugiyama
Last active April 22, 2020 02:17
Show Gist options
  • Save AseiSugiyama/9cf8d64196564ebedfd6202c37e4cf29 to your computer and use it in GitHub Desktop.
Save AseiSugiyama/9cf8d64196564ebedfd6202c37e4cf29 to your computer and use it in GitHub Desktop.
better performance with tf.function.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "better performance with tf.function.ipynb",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/AseiSugiyama/9cf8d64196564ebedfd6202c37e4cf29/better-performance-with-tf-function.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "T27jDDoBCySn",
"colab_type": "text"
},
"source": [
"# 内容\n",
"\n",
"`tf.function` を前処理に用いたコードが動かないという事象を伺ったため、まずは動作するよう修正した。次に、`tf.function` を用いてそれを高速化した。これにより最終的には当初の実装から10倍程度高速化ができた。\n",
"\n",
"## 元のコード\n",
"\n",
"元のコードは次の通り。\n",
"\n",
"```python\n",
"%%time\n",
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"import scipy.ndimage as ndimage\n",
"import numpy as np \n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"def rotate(image):\n",
" return ndimage.rotate(image, np.random.uniform(-30,30), reshape=False)\n",
"\n",
"@tf.function\n",
"def rotate_tf(image):\n",
" [image,]=tf.py_function(rotate,[image],[tf.int32])\n",
" return image\n",
"#print(tf.autograph.to_code(rotate_tf.python_function))\n",
"\n",
"\n",
"(train_x,train_y),(test_x,test_y) = keras.datasets.mnist.load_data()\n",
"train_x=train_x.reshape(-1,28,28,1)\n",
"train_ds=tf.data.Dataset.from_tensor_slices(train_x)\n",
"train_ds=train_ds.map(rotate_tf).batch(16)\n",
"for x in train_ds:\n",
" X = x.numpy().reshape((-1,28,28))\n",
" break\n",
"plt.figure(facecolor=\"white\")\n",
"for i in range(16):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(X[i,:])\n",
" plt.grid(False)\n",
"plt.show()\n",
"```\n",
"\n",
"Colab 上で動かしてみたところ確かに動作しなかった。\n",
"\n",
"## コードの修正"
]
},
{
"cell_type": "code",
"metadata": {
"id": "BVJOWc6_knL8",
"colab_type": "code",
"outputId": "866a7067-b38d-4770-de22-714b0560b2d8",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"try:\n",
" %tensorflow_version 2.x\n",
"except Exception:\n",
" pass\n",
"\n",
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"import scipy.ndimage as ndimage\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"TensorFlow 2.x selected.\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fM6YyR19HEFH",
"colab_type": "text"
},
"source": [
"tf.function を利用せずに動作する等価なコードを記述した。もとのコードに対して再代入を行わないようにリファクタリングを行っている。\n",
"\n",
"リファクタリングは [tensorflow/limitations.md](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/limitations.md#indirect-modifications-and-hidden-side-effects-in-tensorflow-control-flow) の次の記述に従い、再代入を削除した。\n",
"\n",
"> Key Point: We recommend using functional style and immutable Python collections."
]
},
{
"cell_type": "code",
"metadata": {
"id": "ZKrhzzU6IMtH",
"colab_type": "code",
"outputId": "93a47539-efed-4fa3-b2a8-21c2a3f66e7f",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
}
},
"source": [
"def rotate(image):\n",
" return ndimage.rotate(image, np.random.uniform(-30, 30), reshape=False)\n",
"\n",
"def rotate_tf(image):\n",
" rotated = tf.py_function(rotate,[image],[tf.int32])\n",
" return rotated[0]\n",
"\n",
"(train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data()\n",
"train_x = train_x.reshape(-1,28,28,1)\n",
"train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
"batched_train_ds = train_ds.map(rotate_tf).batch(16)\n",
"\n",
"# pick images in first batch\n",
"first_batch = next(iter(batched_train_ds))\n",
"sample_images = first_batch.numpy().reshape((-1,28,28))\n",
"\n",
"plt.figure(facecolor=\"white\")\n",
"for i, sample_image in enumerate(sample_images):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(sample_image)\n",
" plt.grid(False)\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LpmvmEt7Qz02",
"colab_type": "text"
},
"source": [
"再代入処理を行わないように書き換えると、`tf_rotate` に `@tf.function` を適用できる。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "EicaDqRjRIzH",
"colab_type": "code",
"outputId": "cbdd536a-0f7d-4ef4-92ca-624b82b68533",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
}
},
"source": [
"def rotate(image):\n",
" return ndimage.rotate(image, np.random.uniform(-30, 30), reshape=False)\n",
"\n",
"@tf.function\n",
"def rotate_tf(image):\n",
" rotated = tf.py_function(rotate,[image],[tf.int32])\n",
" return rotated[0]\n",
"\n",
"(train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data()\n",
"train_x = train_x.reshape(-1,28,28,1)\n",
"train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
"batched_train_ds = train_ds.map(rotate_tf).batch(16)\n",
"\n",
"# pick images in first batch\n",
"first_batch = next(iter(batched_train_ds))\n",
"sample_images = first_batch.numpy().reshape((-1,28,28))\n",
"\n",
"plt.figure(facecolor=\"white\")\n",
"for i, sample_image in enumerate(sample_images):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(sample_image)\n",
" plt.grid(False)\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\nkqpp5x8AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Ss_9LurMVRrh",
"colab_type": "text"
},
"source": [
"速度を比較する。関数の名称は筆者の趣味に従って変更した。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "-2RP3WDcngca",
"colab_type": "code",
"colab": {}
},
"source": [
"del(rotate_tf)\n",
"\n",
"def rotate_tf(image):\n",
" rotated = tf.py_function(rotate,[image],[tf.int32])\n",
" return rotated[0]\n",
"\n",
"@tf.function\n",
"def rotate_fn(image):\n",
" rotated = tf.py_function(rotate,[image],[tf.int32])\n",
" return rotated[0]\n",
"\n",
"def preprocess_without_tf_funciton(raw_data):\n",
" train_x = raw_data.reshape(-1,28,28,1)\n",
" train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
" batched_train_ds = train_ds.map(rotate_tf).batch(16)\n",
" return batched_train_ds\n",
"\n",
"def preprocess_with_tf_funciton(raw_data):\n",
" train_x = raw_data.reshape(-1,28,28,1)\n",
" train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
" batched_train_ds = train_ds.map(rotate_fn).batch(16)\n",
" return batched_train_ds\n",
"\n",
"# warm up\n",
"_ = rotate_tf(np.zeros(28*28).reshape(28, 28))\n",
"_ = rotate_fn(np.zeros(28*28).reshape(28, 28))"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "zRW-CMlvVxsg",
"colab_type": "code",
"outputId": "e928e0a7-6a94-492e-9cc0-b132a7514d6c",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"%%timeit\n",
"preprocess_without_tf_funciton(train_x)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"100 loops, best of 3: 4.31 ms per loop\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "YwPHBOrjWbZ2",
"colab_type": "code",
"outputId": "c521b68a-c208-477e-af28-f512be9ec132",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"%%timeit\n",
"preprocess_with_tf_funciton(train_x)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"100 loops, best of 3: 4.1 ms per loop\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f6UkWq7cXCIT",
"colab_type": "text"
},
"source": [
"初回の呼び出しを度外視した場合、`tf.function` を使うことにより若干高速化されたようだが、はっきりとした差は認められなかった。\n",
"\n",
"## 高速化\n",
"\n",
"`tf.function` 向きな処理に書き換えることで高速化できないか検討を行った。\n",
"\n",
"まず、ここまでのコードでは `reshape` が前処理を意図した `preprocess` に含まれていなかったので修正する。まずは `tf.function` を使わない実装を行う。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "yFWK02EgXB0C",
"colab_type": "code",
"outputId": "a6bce553-9167-4805-da8e-73c0d2ad221b",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
}
},
"source": [
"def reshape_fn(image):\n",
" return tf.reshape(image, (28, 28, 1))\n",
"\n",
"def rotate_fn(image):\n",
" return ndimage.rotate(image, np.random.uniform(-30, 30), reshape=False)\n",
"\n",
"def tf_reshape(image):\n",
" reshaped = tf.py_function(reshape_fn, [image], [tf.uint8])\n",
" return reshaped[0]\n",
"\n",
"def tf_rotate(image):\n",
" rotated = tf.py_function(rotate_fn,[image],[tf.uint8])\n",
" return rotated[0]\n",
"\n",
"def preprocess_without_tf_funciton(dataset):\n",
" return dataset.map(tf_reshape).map(tf_rotate).batch(16)\n",
"\n",
"(train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data()\n",
"train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
"\n",
"batched_train_ds = preprocess_without_tf_funciton(train_ds)\n",
"\n",
"# pick images in first batch\n",
"first_batch = next(iter(batched_train_ds))\n",
"sample_images = first_batch.numpy().reshape((-1,28,28))\n",
"\n",
"plt.figure(facecolor=\"white\")\n",
"for i, sample_image in enumerate(sample_images):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(sample_image)\n",
" plt.grid(False)\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\ndrJERAr9C020H9O4gJXlAAAAAElFTkSuQmCC\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3kzy872J2MTU",
"colab_type": "text"
},
"source": [
"実行時間の計測を行う。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "D4mVIUscfXuY",
"colab_type": "code",
"outputId": "d1794766-d26c-4275-ec4a-993b8a9cfb95",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"%%timeit\n",
"preprocess_without_tf_funciton(train_ds)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"100 loops, best of 3: 6.45 ms per loop\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vXYnGbJIpMeU",
"colab_type": "text"
},
"source": [
"次に、`tf.function` を用いた実装を行う。上記の実行結果をベースラインとして高速化が図られるかどうか検証する。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "MQs2mhOddcEB",
"colab_type": "code",
"outputId": "51642407-dc23-43d9-dfec-3c1ffa8dc5fa",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
}
},
"source": [
"@tf.function\n",
"def preprocess_with_tf_funciton(dataset):\n",
" return dataset.map(tf_reshape).map(tf_rotate).batch(16)\n",
"\n",
"batched_train_ds = preprocess_with_tf_funciton(train_ds)\n",
"\n",
"# pick images in first batch\n",
"first_batch = next(iter(batched_train_ds))\n",
"sample_images = first_batch.numpy().reshape((-1,28,28))\n",
"\n",
"plt.figure(facecolor=\"white\")\n",
"for i, sample_image in enumerate(sample_images):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(sample_image)\n",
" plt.grid(False)\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n716/dkYXhPd8pGRrL95WNZT2yW/uZjSKSJPvyd53j5nxFWyGDBnC6tWrQ/nIJhEp7fQlUtocKe30\nJZLaHEltNYmUNjelneE9xSkUCkWEowZZhUKhsBHnjBkzZoT6oYMHDw71I5tEpLTTl0hpc6S005dI\nanMktdUkUtp8vO0MuU1WoVAoWhLKXKBQKBQ2ckKD7OLFi8nKyiI9PZ1Zs2YFq00KAyVf+1CytQ8l\n2wD0JuJ2u/VevXrpW7Zs0aurq/X+/fvr69atO+L5H374oZ6Zman37t1bf+ihh5r62KCzfft2fcSI\nEXp2draek5Ojz507V9d1XX/ggQf0Ll266AMGDNAHDBigv//++yFtl5KvfSjZ2oeSbX2abJNdtmwZ\nM2bM4KOPPgLgoYceAuD3v/99vXM9Hg+ZmZns2LqTWFrVOx4JVFFOjR66ikfHK984V7ySbSNRfdc+\nlGzr0+SMr8LCQtLS0qzXXbt2ZcWKFfXOy8vLY86cOZSUlODE1XxbeJwgK/TQVntvjHzNbZXLy8uV\nbI8D1XftQ8m2Pran1U6dOpV27dqxePFi3njubbsf16Iwt1V+8803ufbSqcF/gKaBZpjtzeI7Dqct\nhXhKS0tJSkoK+n1PhGbpuzbJN9wIqWyN+sea0wkOre7/Pug1NbbVR26y4ys1NZUdO3ZYr3fu3Elq\nampQGqVoefKdNm1ayJ7V0mQbSpRs69PkQXbo0KFs2rSJ/Px8ampqWLhwIePGjWvw3EDBK47N8crX\nFnRdtCqvB0dsrNSW9XoMDdentFzg6yawcuXKY58UJJqt7wbKyeGsk6tJhGuxYTMuOHw0VaMP67U1\n6NXV6NXVeCsq/P7pbjeay1W3r2AQafIdXS4XTzzxBKNHj8bj8XDttdeSm5vb4Lmm4BWN53jlG+n0\n7ds3ZM9Sfdc+lGzrE7KMrw8++IDLL/hlRBu4g713fTBp6t71vgTO4rrbjX7aAAA2/SpGnrPRReoH\nxQB4Nsr+SpbW0EQtbIW+hJ92rSMlJaVJ19tNsPpu4O6+1ecP5eK//heAO5IKAOi98EbS71puXBCc\nnT7Cue+eqGwtmXqMvtfATh+u7uKIq+qVzMGesn/g4Z5yiru7FKWP3hxHtwe/9ruuMXJvjGxDlvE1\nduzYUD1KEYGE6wALqu/aSUuQbfhtP9MUAmceTUOLjvY7Ra+p8T9HUY9A76r2s1xK760AYOPAfwDg\n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\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZJ50qcZOpSVO",
"colab_type": "text"
},
"source": [
"概ね同じ結果が得られたので、実行速度を計算する。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "6nSaSMIMkB4r",
"colab_type": "code",
"outputId": "bc205c46-1890-4fd1-a313-3cbc1cc1a898",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 51
}
},
"source": [
"%%timeit\n",
"preprocess_with_tf_funciton(train_ds)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"The slowest run took 17.75 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"1000 loops, best of 3: 416 µs per loop\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uTyAwcSCpadx",
"colab_type": "text"
},
"source": [
"`tf_function` を使った場合には `reshape` を含めない場合よりもより高速になっている。ここまででおおよそ10倍の高速化ができた。\n",
"\n",
"もともとの実装では画像の回転処理に `scipy.ndimage` を用いているが、[tensorflow/addons](https://github.com/tensorflow/addons) の実装を用いることで更に高速化できないか検討する。 addons の利用には追加でパッケージのインストールが必要になるので、まずはそれをインストールする。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "dCwPrbLNxMs2",
"colab_type": "code",
"outputId": "b56ee8d3-b8e8-469b-b19f-e4a37423d72b",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 632
}
},
"source": [
"!pip install tensorflow-addons"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"Requirement already satisfied: tensorflow-addons in /usr/local/lib/python3.6/dist-packages (0.6.0)\n",
"Requirement already satisfied: six>=1.10.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-addons) (1.13.0)\n",
"Requirement already satisfied: tensorflow-gpu==2.0.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-addons) (2.0.0)\n",
"Requirement already satisfied: keras-applications>=1.0.8 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.0.8)\n",
"Requirement already satisfied: termcolor>=1.1.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.1.0)\n",
"Requirement already satisfied: astor>=0.6.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (0.8.0)\n",
"Requirement already satisfied: google-pasta>=0.1.6 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (0.1.8)\n",
"Requirement already satisfied: tensorflow-estimator<2.1.0,>=2.0.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (2.0.1)\n",
"Requirement already satisfied: wheel>=0.26 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (0.33.6)\n",
"Requirement already satisfied: absl-py>=0.7.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (0.8.1)\n",
"Requirement already satisfied: grpcio>=1.8.6 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.25.0)\n",
"Requirement already satisfied: keras-preprocessing>=1.0.5 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.1.0)\n",
"Requirement already satisfied: protobuf>=3.6.1 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (3.11.1)\n",
"Requirement already satisfied: tensorboard<2.1.0,>=2.0.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (2.0.2)\n",
"Requirement already satisfied: numpy<2.0,>=1.16.0 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.17.4)\n",
"Requirement already satisfied: gast==0.2.2 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (0.2.2)\n",
"Requirement already satisfied: opt-einsum>=2.3.2 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (3.1.0)\n",
"Requirement already satisfied: wrapt>=1.11.1 in /tensorflow-2.0.0/python3.6 (from tensorflow-gpu==2.0.0->tensorflow-addons) (1.11.2)\n",
"Requirement already satisfied: h5py in /tensorflow-2.0.0/python3.6 (from keras-applications>=1.0.8->tensorflow-gpu==2.0.0->tensorflow-addons) (2.10.0)\n",
"Requirement already satisfied: setuptools in /tensorflow-2.0.0/python3.6 (from protobuf>=3.6.1->tensorflow-gpu==2.0.0->tensorflow-addons) (42.0.2)\n",
"Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /tensorflow-2.0.0/python3.6 (from tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (0.4.1)\n",
"Requirement already satisfied: requests<3,>=2.21.0 in /tensorflow-2.0.0/python3.6 (from tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (2.22.0)\n",
"Requirement already satisfied: werkzeug>=0.11.15 in /tensorflow-2.0.0/python3.6 (from tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (0.16.0)\n",
"Requirement already satisfied: google-auth<2,>=1.6.3 in /tensorflow-2.0.0/python3.6 (from tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (1.7.1)\n",
"Requirement already satisfied: markdown>=2.6.8 in /tensorflow-2.0.0/python3.6 (from tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (3.1.1)\n",
"Requirement already satisfied: requests-oauthlib>=0.7.0 in /tensorflow-2.0.0/python3.6 (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (1.3.0)\n",
"Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /tensorflow-2.0.0/python3.6 (from requests<3,>=2.21.0->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (3.0.4)\n",
"Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /tensorflow-2.0.0/python3.6 (from requests<3,>=2.21.0->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (1.25.7)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /tensorflow-2.0.0/python3.6 (from requests<3,>=2.21.0->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (2019.11.28)\n",
"Requirement already satisfied: idna<2.9,>=2.5 in /tensorflow-2.0.0/python3.6 (from requests<3,>=2.21.0->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (2.8)\n",
"Requirement already satisfied: pyasn1-modules>=0.2.1 in /tensorflow-2.0.0/python3.6 (from google-auth<2,>=1.6.3->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (0.2.7)\n",
"Requirement already satisfied: cachetools<3.2,>=2.0.0 in /tensorflow-2.0.0/python3.6 (from google-auth<2,>=1.6.3->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (3.1.1)\n",
"Requirement already satisfied: rsa<4.1,>=3.1.4 in /tensorflow-2.0.0/python3.6 (from google-auth<2,>=1.6.3->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (4.0)\n",
"Requirement already satisfied: oauthlib>=3.0.0 in /tensorflow-2.0.0/python3.6 (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (3.1.0)\n",
"Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /tensorflow-2.0.0/python3.6 (from pyasn1-modules>=0.2.1->google-auth<2,>=1.6.3->tensorboard<2.1.0,>=2.0.0->tensorflow-gpu==2.0.0->tensorflow-addons) (0.4.8)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "7hz9cPMxyH0I",
"colab_type": "code",
"colab": {}
},
"source": [
"import tensorflow_addons as tfa"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "JWC2JQS4z1Qr",
"colab_type": "text"
},
"source": [
"画像の回転は `tfa.image.rotate` に実装されているのでこれを利用した。また、Pythonを用いた前処理がなくなったため、 `tf.py_function` を削除した。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "KR0ivDXcxdLJ",
"colab_type": "code",
"outputId": "94a3cdeb-5e43-4bdc-eb42-99a9bc03ad17",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 268
}
},
"source": [
"from math import pi\n",
"\n",
"def reshape_fn(image):\n",
" return tf.reshape(image, (28, 28, 1))\n",
"\n",
"def rotate_fn(image):\n",
" return tfa.image.rotate(image, np.random.uniform(-30 * pi / 180, 30 * pi / 180),)\n",
"\n",
"@tf.function\n",
"def preprocess_with_tf_only(dataset):\n",
" return dataset.map(reshape_fn).map(rotate_fn).batch(16)\n",
"\n",
"(train_x, train_y), (test_x, test_y) = keras.datasets.mnist.load_data()\n",
"train_ds = tf.data.Dataset.from_tensor_slices(train_x)\n",
"\n",
"batched_train_ds = preprocess_with_tf_only(train_ds)\n",
"\n",
"# pick images in first batch\n",
"first_batch = next(iter(batched_train_ds))\n",
"sample_images = first_batch.numpy().reshape((-1,28,28))\n",
"\n",
"plt.figure(facecolor=\"white\")\n",
"for i, sample_image in enumerate(sample_images):\n",
" plt.subplot(4,4,i+1)\n",
" plt.imshow(sample_image)\n",
" plt.grid(False)\n",
"plt.show()"
],
"execution_count": 0,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 16 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kgWZKtgAy-kc",
"colab_type": "text"
},
"source": [
"概ね同じ結果を得られたため、実行時間を計測する。"
]
},
{
"cell_type": "code",
"metadata": {
"id": "bS5tC0u8y6Iv",
"colab_type": "code",
"outputId": "45cd0c0d-abf7-4912-84db-74d9b4ecfa23",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 51
}
},
"source": [
"%%timeit\n",
"preprocess_with_tf_only(train_ds)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"The slowest run took 5.77 times longer than the fastest. This could mean that an intermediate result is being cached.\n",
"1000 loops, best of 3: 414 µs per loop\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gGG0xxcAzesR",
"colab_type": "text"
},
"source": [
"`tfa` を用いたことによる高速化は認められなかったが、こちらも当初の実装から10倍程度高速化できていることがわかる。"
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment