From 5e5f99e902c0e0f461f252df00bff0b47371ed54 Mon Sep 17 00:00:00 2001 From: mcallara Date: Sat, 25 Jan 2020 12:09:48 +0100 Subject: [PATCH] Update 2_keras.ipynb Typo in cell --- extras/amld/notebooks/exercises/2_keras.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/amld/notebooks/exercises/2_keras.ipynb b/extras/amld/notebooks/exercises/2_keras.ipynb index 9219f588..534206f2 100644 --- a/extras/amld/notebooks/exercises/2_keras.ipynb +++ b/extras/amld/notebooks/exercises/2_keras.ipynb @@ -1 +1 @@ -{"nbformat": 4, "nbformat_minor": 0, "metadata": {"colab": {"name": "2_keras", "provenance": [], "collapsed_sections": [], "toc_visible": true}, "kernelspec": {"name": "python3", "display_name": "Python 3"}, "accelerator": "GPU"}, "cells": [{"cell_type": "markdown", "metadata": {"id": "AVOfyW__KqTM", "colab_type": "text"}, "source": ["# Using tf.keras\n", "\n", "This Colab is about how to use Keras to define and train simple models on the data generated in the last Colab [1_data.ipynb](https://github.com/tensorflow/workshops/tree/master/extras/amld/notebooks/solutions/1_data.ipynb)"]}, {"cell_type": "code", "metadata": {"id": "jHGIMZC5-JSR", "colab_type": "code", "outputId": "cd105ed5-27d7-4ca9-ce5e-0f039cbbca10", "executionInfo": {"status": "ok", "timestamp": 1579904074311, "user_tz": 480, "elapsed": 611, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# In Jupyter, you would need to install TF 2.0 via !pip.\n", "%tensorflow_version 2.x"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "YvSp5-h8-IsG", "colab_type": "code", "outputId": "d8e49fa5-4fe1-40e4-8701-30a916820d9d", "executionInfo": {"status": "ok", "timestamp": 1579904082887, "user_tz": 480, "elapsed": 9173, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["import tensorflow as tf\n", "import json, os\n", "\n", "# Tested with TensorFlow 2.1.0\n", "print('version={}, CUDA={}, GPU={}, TPU={}'.format(\n", " tf.__version__, tf.test.is_built_with_cuda(),\n", " # GPU attached?\n", " len(tf.config.list_physical_devices('GPU')) > 0,\n", " # TPU accessible? (only works on Colab)\n", " 'COLAB_TPU_ADDR' in os.environ))"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "V5bA7N788eiT", "colab_type": "text"}, "source": ["> **Attention:** Please avoid using the TPU runtime (`TPU=True`) for now. The notebook contains an optional part on TPU usage at the end if you're interested. You can change the runtime via: \"Runtime > Change runtime type > Hardware Accelerator\" in Colab."]}, {"cell_type": "markdown", "metadata": {"id": "sAz1wTwOLX4j", "colab_type": "text"}, "source": ["## Data from Protobufs"]}, {"cell_type": "code", "metadata": {"id": "vxwdPWVhEU97", "colab_type": "code", "colab": {}}, "source": ["# Load data from Drive (Colab only).\n", "data_path = '/content/gdrive/My Drive/amld_data/zoo_img'\n", "\n", "# Or, you can load data from different sources, such as:\n", "# From your local machine:\n", "# data_path = './amld_data'\n", "\n", "# Or use a prepared dataset from Cloud (Colab only).\n", "# - 50k training examples, including pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img_small'\n", "# - 1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img'\n", "# - 4.1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/animals_img'\n", "# - 29M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/all_img'\n", "\n", "# Store models on Drive (Colab only).\n", "models_path = '/content/gdrive/My Drive/amld_data/models'\n", "\n", "# Or, store models to local machine.\n", "# models_path = './amld_models'"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "IvyLtRFLfXZs", "colab_type": "code", "outputId": "c2a41f1e-f2c9-422b-fe77-ee09a22bbcb3", "executionInfo": {"status": "ok", "timestamp": 1579904112087, "user_tz": 480, "elapsed": 38361, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 730}}, "source": ["if data_path.startswith('/content/gdrive/'):\n", " from google.colab import drive\n", " drive.mount('/content/gdrive')\n", "\n", "if data_path.startswith('gs://'):\n", " from google.colab import auth\n", " auth.authenticate_user()\n", " !gsutil ls -lh \"$data_path\"\n", "else:\n", " !ls -lh \"$data_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "4oCIc1XNTQ-v", "colab_type": "code", "outputId": "78ccd9e2-16fc-480e-8f61-0b6254f714ec", "executionInfo": {"status": "ok", "timestamp": 1579904112646, "user_tz": 480, "elapsed": 38911, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 52}}, "source": ["labels = [label.strip() for label \n", " in tf.io.gfile.GFile('{}/labels.txt'.format(data_path))]\n", "print('All labels in the dataset:', ' '.join(labels))\n", "\n", "counts = json.load(tf.io.gfile.GFile('{}/counts.json'.format(data_path)))\n", "print('Splits sizes:', counts)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "E9izb-IbIAhZ", "colab_type": "code", "outputId": "ffa57a65-675e-41a4-82ef-90dd424bb23d", "executionInfo": {"status": "ok", "timestamp": 1579904114203, "user_tz": 480, "elapsed": 40460, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 52}}, "source": ["# This dictionary specifies what \"features\" we want to extract from the\n", "# tf.train.Example protos (i.e. what they look like on disk). We only\n", "# need the image data \"img_64\" and the \"label\". Both features are tensors\n", "# with a fixed length.\n", "# You need to specify the correct \"shape\" and \"dtype\" parameters for\n", "# these features.\n", "feature_spec = {\n", " # Single label per example => shape=[1] (we could also use shape=() and\n", " # then do a transformation in the input_fn).\n", " 'label': tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),\n", " # The bytes_list data is parsed into tf.string.\n", " 'img_64': tf.io.FixedLenFeature(shape=[64, 64], dtype=tf.int64),\n", "}\n", "\n", "def parse_example(serialized_example):\n", " # Convert string to tf.train.Example and then extract features/label.\n", " features = tf.io.parse_single_example(serialized_example, feature_spec)\n", "\n", " # Important step: remove \"label\" from features!\n", " # Otherwise our classifier would simply learn to predict\n", " # label=features['label'].\n", " label = features.pop('label')\n", " label = tf.one_hot(tf.squeeze(label), len(labels))\n", "\n", " features['img_64'] = tf.cast(features['img_64'], tf.float32) / 255.\n", " return features['img_64'], label\n", "\n", "batch_size = 100\n", "steps_per_epoch = counts['train'] // batch_size\n", "eval_steps_per_epoch = counts['eval'] // batch_size\n", "\n", "# Create datasets from TFRecord files.\n", "train_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/train-*'.format(data_path)))\n", "train_ds = train_ds.map(parse_example)\n", "train_ds = train_ds.batch(batch_size).repeat()\n", "\n", "eval_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/eval-*'.format(data_path)))\n", "eval_ds = eval_ds.map(parse_example)\n", "eval_ds = eval_ds.batch(batch_size)\n", "\n", "# Read a single batch of examples from the training set and display shapes.\n", "for img_feature, label in train_ds:\n", " break\n", "print('img_feature.shape (batch_size, image_height, image_width) =', \n", " img_feature.shape)\n", "print('label.shape (batch_size, number_of_labels) =', label.shape)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "lwlhvv1VM1wQ", "colab_type": "code", "outputId": "d26092d8-dfb5-4daf-a0a9-1c7c0357fa60", "executionInfo": {"status": "ok", "timestamp": 1579904121574, "user_tz": 480, "elapsed": 47824, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 381}}, "source": ["# Visualize some examples from the training set.\n", "from matplotlib import pyplot as plt\n", "\n", "def show_img(img_64, title='', ax=None):\n", " \"\"\"Displays an image.\n", " \n", " Args:\n", " img_64: Array (or Tensor) with monochrome image data.\n", " title: Optional title.\n", " ax: Optional Matplotlib axes to show the image in.\n", " \"\"\"\n", " (ax if ax else plt).matshow(img_64.reshape((64, -1)), cmap='gray')\n", " if isinstance(img_64, tf.Tensor):\n", " img_64 = img_64.numpy()\n", " ax = ax if ax else plt.gca()\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(title)\n", " \n", "rows, cols = 3, 5\n", "for img_feature, label in train_ds:\n", " break\n", "_, axs = plt.subplots(rows, cols, figsize=(2*cols, 2*rows))\n", "for i in range(rows):\n", " for j in range(cols):\n", " show_img(img_feature[i*rows+j].numpy(), \n", " title=labels[label[i*rows+j].numpy().argmax()], ax=axs[i][j])"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "gZBM6OWqzv3L", "colab_type": "text"}, "source": ["## Linear model"]}, {"cell_type": "code", "metadata": {"id": "28qPSmJMaxBh", "colab_type": "code", "outputId": "93e67728-b0d1-4109-ed96-f2fea2ba5f66", "executionInfo": {"status": "ok", "timestamp": 1579904121575, "user_tz": 480, "elapsed": 47815, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Sample linear model.\n", "linear_model = tf.keras.Sequential()\n", "linear_model.add(tf.keras.layers.Flatten(input_shape=(64, 64,)))\n", "linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "# \"adam, categorical_crossentropy, accuracy\" and other string constants can be\n", "# found at https://keras.io.\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "\n", "linear_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "_BRK6TYLa09h", "colab_type": "code", "outputId": "3e5f09ef-2feb-4f49-fe66-94dd56c2b18a", "executionInfo": {"status": "ok", "timestamp": 1579904139379, "user_tz": 480, "elapsed": 65612, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 90}}, "source": ["linear_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=1,\n", " verbose=True)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "Pr0L9sVBqCj6", "colab_type": "text"}, "source": ["## Convolutional model"]}, {"cell_type": "code", "metadata": {"id": "EXqkgNozzz5U", "colab_type": "code", "outputId": "497e79a6-3b86-4693-addb-e1f39f8581be", "executionInfo": {"status": "ok", "timestamp": 1579904139604, "user_tz": 480, "elapsed": 65830, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 550}}, "source": ["# Let's define a convolutional model:\n", "conv_model = tf.keras.Sequential([\n", " tf.keras.layers.Reshape(target_shape=(64, 64, 1), input_shape=(64, 64)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.ZeroPadding2D((1,1)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'), \n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", " tf.keras.layers.Conv2D(filters=64, \n", " kernel_size=(5, 5), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", "\n", " tf.keras.layers.Flatten(),\n", " tf.keras.layers.Dense(256, activation='relu'),\n", " tf.keras.layers.Dropout(0.3),\n", " tf.keras.layers.Dense(len(labels), activation='softmax'),\n", "])\n", "\n", "# YOUR ACTION REQUIRED:\n", "# Compile + print summary of the model (analogous to the linear model above).\n"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "DsIUYEHC17ft", "colab_type": "code", "outputId": "cbbbcdf6-9085-43f8-d9d4-e82e173b0b83", "executionInfo": {"status": "ok", "timestamp": 1579904215104, "user_tz": 480, "elapsed": 141322, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 158}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Train the model (analogous to linear model above).\n", "# Note: You might want to reduce the number of steps if if it takes too long.\n", "# Pro tip: Change the runtime type (\"Runtime\" menu) to GPU! After the change you\n", "# will need to rerun the cells above because the Python kernel's state is reset.\n"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"colab_type": "text", "id": "E6W0XkCpB8fb"}, "source": ["## Store model"]}, {"cell_type": "code", "metadata": {"id": "d5E4keWeliXm", "colab_type": "code", "colab": {}}, "source": ["tf.io.gfile.makedirs(models_path)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "V94tLWcEJDeI", "colab_type": "code", "colab": {}}, "source": ["# Save model as Keras model.\n", "keras_path = os.path.join(models_path, 'linear.h5')\n", "linear_model.save(keras_path)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "uJj4acwemWDy", "colab_type": "code", "outputId": "e3f5f375-b2fc-483e-9eeb-9b8c34bb1fde", "executionInfo": {"status": "ok", "timestamp": 1579904216898, "user_tz": 480, "elapsed": 143101, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Keras model is a single file.\n", "!ls -hl \"$keras_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "SHHez3GZJD4u", "colab_type": "code", "outputId": "c6cfe9c0-7fce-4c75-c356-4fb06f4b08de", "executionInfo": {"status": "ok", "timestamp": 1579904217244, "user_tz": 480, "elapsed": 143440, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Load Keras model.\n", "loaded_keras_model = tf.keras.models.load_model(keras_path)\n", "loaded_keras_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "6RDHdn9wlSfe", "colab_type": "code", "outputId": "6f61c1cb-3af3-4749-bbfc-c8a94d07f96e", "executionInfo": {"status": "ok", "timestamp": 1579904224930, "user_tz": 480, "elapsed": 151118, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 107}}, "source": ["# Save model as Tensorflow Saved Model.\n", "saved_model_path = os.path.join(models_path, 'saved_model/linear')\n", "linear_model.save(saved_model_path, save_format='tf')"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "vdbtIUV8lbdz", "colab_type": "code", "outputId": "0830cb9b-3fac-47c3-dd07-f8255520c0da", "executionInfo": {"status": "ok", "timestamp": 1579904227015, "user_tz": 480, "elapsed": 153196, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 158}}, "source": ["# Inspect saved model directory structure.\n", "!find \"$saved_model_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "oy1Y5yjyCCZ3", "colab_type": "code", "outputId": "e32850a7-61e2-4b42-d5ad-fa39c665c08c", "executionInfo": {"status": "ok", "timestamp": 1579904227430, "user_tz": 480, "elapsed": 153604, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["saved_model = tf.keras.models.load_model(saved_model_path)\n", "saved_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "7SNX8oL6UFLH", "colab_type": "code", "outputId": "1ff5dbda-673c-4808-fdb2-c54cd9fb258c", "executionInfo": {"status": "ok", "timestamp": 1579904228845, "user_tz": 480, "elapsed": 155012, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 105}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Store the convolutional model and any additional models that you trained\n", "# in the previous sections in Keras format so we can use them in later\n", "# notebooks for prediction.\n"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "L519Q6CpQOwK", "colab_type": "text"}, "source": ["# ----- Optional part -----"]}, {"cell_type": "markdown", "metadata": {"id": "zRjVuDn9VhNG", "colab_type": "text"}, "source": ["## Learn from errors\n", "\n", "Looking at classification mistakes is a great way to better understand how a model is performing. This section walks you through the necessary steps to load some examples from the dataset, make predictions, and plot the mistakes."]}, {"cell_type": "code", "metadata": {"id": "xYydGO1CM7VG", "colab_type": "code", "colab": {}}, "source": ["import collections\n", "Mistake = collections.namedtuple('Mistake', 'label pred img_64')\n", "mistakes = []"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "rDvDfnezM_R_", "colab_type": "code", "outputId": "d60318a7-0bda-4553-95b0-50a4e04e8970", "executionInfo": {"status": "ok", "timestamp": 1579904228847, "user_tz": 480, "elapsed": 155003, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["for img_64_batch, label_onehot_batch in eval_ds:\n", " break\n", "img_64_batch.shape, label_onehot_batch.shape"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "YHdHqTdaRBZ_", "colab_type": "code", "colab": {}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Use model.predict() to get a batch of predictions.\n", "preds =\n"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "uMGfVv3ONeyz", "colab_type": "code", "outputId": "3d8ab338-f185-4b61-b2e6-3562042760b0", "executionInfo": {"status": "ok", "timestamp": 1579904229129, "user_tz": 480, "elapsed": 155275, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Iterate through the batch:\n", "for label_onehot, pred, img_64 in zip(label_onehot_batch, preds, img_64_batch):\n", " # YOUR ACTION REQUIRED:\n", " # Both `label_onehot` and pred are vectors with length=len(labels), with every\n", " # element corresponding to a probability of the corresponding class in\n", " # `labels`. Get the value with the highest value to get the index within\n", " # `labels`.\n", " label_i = \n", " pred_i =\n", " if label_i != pred_i:\n", " mistakes.append(Mistake(label_i, pred_i, img_64.numpy()))\n", "\n", "# You can run this cell multiple times to get more mistakes. \n", "len(mistakes)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "rwq_0tTDXLbJ", "colab_type": "code", "outputId": "98675cd3-3260-461e-d4e9-817981d1a7bd", "executionInfo": {"status": "ok", "timestamp": 1579904230327, "user_tz": 480, "elapsed": 156466, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 735}}, "source": ["# Let's examine the cases when our model gets it wrong. Would you recognize\n", "# these images correctly?\n", "\n", "# YOUR ACTION REQUIRED:\n", "# Run above cell but using a different model to get a different set of\n", "# classification mistakes. Then copy over this cell to plot the mistakes for\n", "# comparison purposes. Can you spot a pattern?\n", "rows, cols = 5, 5\n", "plt.figure(figsize=(cols*2.5, rows*2.5))\n", "for i, mistake in enumerate(mistakes[:rows*cols]):\n", " ax = plt.subplot(rows, cols, i + 1)\n", " title = '{}? {}!'.format(labels[mistake.pred], labels[mistake.label])\n", " show_img(mistake.img_64, title, ax)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "eids_xB-QzYL", "colab_type": "text"}, "source": ["## Data from DataFrame\n", "\n", "For comparison, this section shows how you would load data from a `pandas.DataFrame` and then use Keras for training. Note that this approach does not scale well and can only be used for quite small datasets."]}, {"cell_type": "code", "metadata": {"id": "fKETADXa622b", "colab_type": "code", "outputId": "198f7844-9456-4865-c18a-67fa3063cf6a", "executionInfo": {"status": "ok", "timestamp": 1579904232507, "user_tz": 480, "elapsed": 158639, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory BEFORE loading the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "lVHGBT_q3-zq", "colab_type": "code", "outputId": "f468e68b-82d4-491b-d820-5719f75764a7", "executionInfo": {"status": "ok", "timestamp": 1579904273004, "user_tz": 480, "elapsed": 199128, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 87}}, "source": ["# Loading all the data in memory takes a while (~40s).\n", "import pickle\n", "df = pickle.load(tf.io.gfile.GFile('%s/dataframe.pkl' % data_path, mode='rb'))\n", "print(len(df))\n", "print(df.columns)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "GTnEjQIDfQeM", "colab_type": "code", "outputId": "ffda698c-e0bd-4e9a-825c-9fd7aad56285", "executionInfo": {"status": "ok", "timestamp": 1579904275288, "user_tz": 480, "elapsed": 201404, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["df_train = df[df.split == b'train']\n", "len(df_train)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "Aagi5RJlLz4k", "colab_type": "code", "outputId": "c3f448aa-338e-4789-9c7c-0aebc38dadb7", "executionInfo": {"status": "ok", "timestamp": 1579904277142, "user_tz": 480, "elapsed": 203249, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory AFTER loading the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"colab_type": "code", "id": "0gKHIOswcPM1", "outputId": "5208bf1d-d2e8-4fa2-800b-88ddeee3e0f4", "executionInfo": {"status": "ok", "timestamp": 1579904277845, "user_tz": 480, "elapsed": 203945, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 381}}, "source": ["# Show some images from the dataset.\n", "\n", "from matplotlib import pyplot as plt\n", "\n", "def show_img(img_64, title='', ax=None):\n", " (ax if ax else plt).matshow(img_64.reshape((64, -1)), cmap='gray')\n", " ax = ax if ax else plt.gca()\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(title)\n", "\n", "rows, cols = 3, 3\n", "_, axs = plt.subplots(rows, cols, figsize=(2*cols, 2*rows))\n", "for i in range(rows):\n", " for j in range(cols):\n", " d = df.sample(1).iloc[0]\n", " show_img(d.img_64, title=labels[d.label], ax=axs[i][j])"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "41_3dkqMPmG0", "colab_type": "code", "colab": {}}, "source": ["df_x = tf.convert_to_tensor(df_train.img_64, dtype=tf.float32)\n", "df_y = tf.one_hot(df_train.label, depth=len(labels), dtype=tf.float32)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "c7k02_QQSYs2", "colab_type": "code", "outputId": "a884ed09-6d9d-4dfc-f578-8539946c3a15", "executionInfo": {"status": "ok", "timestamp": 1579904314896, "user_tz": 480, "elapsed": 240985, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory AFTER defining the Tenors based on the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "zEwkFKFuTBu0", "colab_type": "code", "outputId": "70dd909a-cf87-435a-82ba-79c31893d506", "executionInfo": {"status": "ok", "timestamp": 1579904314897, "user_tz": 480, "elapsed": 240980, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Checkout the shape of these rather large tensors.\n", "df_x.shape, df_x.dtype, df_y.shape, df_y.dtype"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "98NBAasHXfMq", "colab_type": "code", "outputId": "d9b631c9-31fc-412d-db39-0a062acbed48", "executionInfo": {"status": "ok", "timestamp": 1579904317379, "user_tz": 480, "elapsed": 243455, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 283}}, "source": ["# Copied code from section \"Linear model\" above.\n", "linear_model = tf.keras.Sequential()\n", "linear_model.add(tf.keras.layers.Flatten(input_shape=(64 * 64,)))\n", "linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "# \"adam, categorical_crossentropy, accuracy\" and other string constants can be\n", "# found at https://keras.io.\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "linear_model.summary()\n", "\n", "# How much of a speedup do you see because the data is already in memory?\n", "# How would this compare to the convolutional model?\n", "linear_model.fit(df_x, df_y, epochs=1, batch_size=100)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "XAItlmUwv1TZ", "colab_type": "text"}, "source": ["## TPU Support\n", "\n", "For using TF with a TPU we'll need to make some adjustments. Generally, please note that several TF TPU features are experimental and might not work as smooth as it does with a CPU or GPU.\n", "\n", "> **Attention:** Please make sure to switch the runtime to TPU for this part. You can do so via: \"Runtime > Change runtime type > Hardware Accelerator\" in Colab. As this might create a new environment this section can be executed isolated from anything above."]}, {"cell_type": "code", "metadata": {"colab_type": "code", "id": "kTGjOm631BQw", "outputId": "4278689a-0721-4f63-c5e0-dc18548c2465", "executionInfo": {"status": "ok", "timestamp": 1579904388257, "user_tz": 480, "elapsed": 30360, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["%tensorflow_version 2.x"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"colab_type": "code", "outputId": "cdc179c6-5918-4f35-f4b8-dcd5fde6e34c", "executionInfo": {"status": "ok", "timestamp": 1579904408572, "user_tz": 480, "elapsed": 50666, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "id": "QgVEQxLo1BQ3", "colab": {"base_uri": "https://localhost:8080/", "height": 425}}, "source": ["import json, os\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "import tensorflow as tf\n", "\n", "# Disable duplicate logging output in TF.\n", "logger = tf.get_logger()\n", "logger.propagate = False\n", "\n", "# This will fail if no TPU is connected...\n", "tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n", "# Set up distribution strategy.\n", "tf.config.experimental_connect_to_cluster(tpu)\n", "tf.tpu.experimental.initialize_tpu_system(tpu);\n", "strategy = tf.distribute.experimental.TPUStrategy(tpu)\n", "\n", "# Tested with TensorFlow 2.1.0\n", "print('\\n\\nTF version={} TPUs={} accelerators={}'.format(\n", " tf.__version__, tpu.cluster_spec().as_dict()['worker'],\n", " strategy.num_replicas_in_sync))"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "liv2SeFnXerM", "colab_type": "text"}, "source": ["> **Attention:** TPUs require all files (input and models) to be stored in cloud storage buckets (`gs://bucket-name/...`). If you plan to use TPUs please choose the `data_path` below accordingly. Otherwise, you might run into `File system scheme '[local]' not implemented` errors."]}, {"cell_type": "code", "metadata": {"id": "9kWkMWjHxn09", "colab_type": "code", "colab": {}}, "source": ["from google.colab import auth\n", "auth.authenticate_user()\n", "\n", "# Browse datasets:\n", "# https://console.cloud.google.com/storage/browser/amld-datasets\n", "\n", "# - 50k training examples, including pickled DataFrame.\n", "data_path = 'gs://amld-datasets/zoo_img_small'\n", "# - 1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img'\n", "# - 4.1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/animals_img'\n", "# - 29M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/all_img'"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "nZLuuaY72RxT", "colab_type": "code", "cellView": "form", "outputId": "ac23d955-18f1-4900-b9ee-82dca2aea836", "executionInfo": {"status": "ok", "timestamp": 1579904479930, "user_tz": 480, "elapsed": 122010, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 87}}, "source": ["#@markdown **Copied and adjusted data definition code from above**\n", "#@markdown\n", "#@markdown    Note: You can double-click this cell to see its code.\n", "#@markdown\n", "#@markdown The changes have been highlighted with `!` in the contained code\n", "#@markdown (things like the `batch_size` and added `drop_remainder=True`).\n", "#@markdown\n", "#@markdown Feel free to just **click \"execute\"** and ignore the details for now.\n", "\n", "labels = [label.strip() for label \n", " in tf.io.gfile.GFile('{}/labels.txt'.format(data_path))]\n", "print('All labels in the dataset:', ' '.join(labels))\n", "\n", "counts = json.load(tf.io.gfile.GFile('{}/counts.json'.format(data_path)))\n", "print('Splits sizes:', counts)\n", "\n", "# This dictionary specifies what \"features\" we want to extract from the\n", "# tf.train.Example protos (i.e. what they look like on disk). We only\n", "# need the image data \"img_64\" and the \"label\". Both features are tensors\n", "# with a fixed length.\n", "# You need to specify the correct \"shape\" and \"dtype\" parameters for\n", "# these features.\n", "feature_spec = {\n", " # Single label per example => shape=[1] (we could also use shape=() and\n", " # then do a transformation in the input_fn).\n", " 'label': tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),\n", " # The bytes_list data is parsed into tf.string.\n", " 'img_64': tf.io.FixedLenFeature(shape=[64, 64], dtype=tf.int64),\n", "}\n", "\n", "def parse_example(serialized_example):\n", " # Convert string to tf.train.Example and then extract features/label.\n", " features = tf.io.parse_single_example(serialized_example, feature_spec)\n", "\n", " # Important step: remove \"label\" from features!\n", " # Otherwise our classifier would simply learn to predict\n", " # label=features['label'].\n", " label = features.pop('label')\n", " label = tf.one_hot(tf.squeeze(label), len(labels))\n", "\n", " features['img_64'] = tf.cast(features['img_64'], tf.float32)\n", " return features['img_64'], label\n", "\n", "# Adjust the batch size to the given hardware (#accelerators).\n", "batch_size = 64 * strategy.num_replicas_in_sync\n", "# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", "steps_per_epoch = counts['train'] // batch_size\n", "eval_steps_per_epoch = counts['eval'] // batch_size\n", "\n", "# Create datasets from TFRecord files.\n", "train_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/train-*'.format(data_path)))\n", "train_ds = train_ds.map(parse_example)\n", "train_ds = train_ds.batch(batch_size, drop_remainder=True).repeat()\n", "# !!!!!!!!!!!!!!!!!!!\n", "\n", "eval_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/eval-*'.format(data_path)))\n", "eval_ds = eval_ds.map(parse_example)\n", "eval_ds = eval_ds.batch(batch_size, drop_remainder=True)\n", "# !!!!!!!!!!!!!!!!!!!\n", "# Read a single example and display shapes.\n", "for img_feature, label in train_ds:\n", " break\n", "print('img_feature.shape (batch_size, image_height, image_width) =', \n", " img_feature.shape)\n", "print('label.shape (batch_size, number_of_labels) =', label.shape)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "nF5wDYvjyk1K", "colab_type": "code", "outputId": "f73c2530-fb42-49c7-a690-aa37c5c5acc1", "executionInfo": {"status": "ok", "timestamp": 1579904479930, "user_tz": 480, "elapsed": 122004, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Model definition code needs to be wrapped in scope.\n", "with strategy.scope():\n", " linear_model = tf.keras.Sequential()\n", " linear_model.add(tf.keras.layers.Flatten(input_shape=(64, 64,)))\n", " linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "linear_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "CAHTLSQs7hRd", "colab_type": "code", "outputId": "1ed70722-c850-410d-fdc0-16472b16576c", "executionInfo": {"status": "ok", "timestamp": 1579904507182, "user_tz": 480, "elapsed": 149250, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 90}}, "source": ["linear_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=1,\n", " verbose=True)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "NVaTmhROzHE-", "colab_type": "code", "outputId": "4ba9ebd6-1441-4075-a269-e8b212d2e5ac", "executionInfo": {"status": "ok", "timestamp": 1579904508096, "user_tz": 480, "elapsed": 150158, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 550}}, "source": ["# Model definition code needs to be wrapped in scope.\n", "with strategy.scope():\n", " conv_model = tf.keras.Sequential([\n", " tf.keras.layers.Reshape(target_shape=(64, 64, 1), input_shape=(64, 64)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.ZeroPadding2D((1,1)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'), \n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", " tf.keras.layers.Conv2D(filters=64, \n", " kernel_size=(5, 5), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", "\n", " tf.keras.layers.Flatten(),\n", " tf.keras.layers.Dense(256, activation='relu'),\n", " tf.keras.layers.Dropout(0.3),\n", " tf.keras.layers.Dense(len(labels), activation='softmax'),\n", " ])\n", "\n", "conv_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy'])\n", "conv_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "Ye5y9nIt7p1m", "colab_type": "code", "outputId": "02b99428-8865-488c-c023-33acd58cca8b", "executionInfo": {"status": "ok", "timestamp": 1579904592275, "user_tz": 480, "elapsed": 234331, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 176}}, "source": ["conv_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=3,\n", " verbose=True)\n", "conv_model.evaluate(eval_ds, steps=eval_steps_per_epoch)"], "execution_count": null, "outputs": []}]} \ No newline at end of file +{"nbformat": 4, "nbformat_minor": 0, "metadata": {"colab": {"name": "2_keras", "provenance": [], "collapsed_sections": [], "toc_visible": true}, "kernelspec": {"name": "python3", "display_name": "Python 3"}, "accelerator": "GPU"}, "cells": [{"cell_type": "markdown", "metadata": {"id": "AVOfyW__KqTM", "colab_type": "text"}, "source": ["# Using tf.keras\n", "\n", "This Colab is about how to use Keras to define and train simple models on the data generated in the last Colab [1_data.ipynb](https://github.com/tensorflow/workshops/tree/master/extras/amld/notebooks/solutions/1_data.ipynb)"]}, {"cell_type": "code", "metadata": {"id": "jHGIMZC5-JSR", "colab_type": "code", "outputId": "cd105ed5-27d7-4ca9-ce5e-0f039cbbca10", "executionInfo": {"status": "ok", "timestamp": 1579904074311, "user_tz": 480, "elapsed": 611, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# In Jupyter, you would need to install TF 2.0 via !pip.\n", "%tensorflow_version 2.x"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "YvSp5-h8-IsG", "colab_type": "code", "outputId": "d8e49fa5-4fe1-40e4-8701-30a916820d9d", "executionInfo": {"status": "ok", "timestamp": 1579904082887, "user_tz": 480, "elapsed": 9173, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["import tensorflow as tf\n", "import json, os\n", "\n", "# Tested with TensorFlow 2.1.0\n", "print('version={}, CUDA={}, GPU={}, TPU={}'.format(\n", " tf.__version__, tf.test.is_built_with_cuda(),\n", " # GPU attached?\n", " len(tf.config.list_physical_devices('GPU')) > 0,\n", " # TPU accessible? (only works on Colab)\n", " 'COLAB_TPU_ADDR' in os.environ))"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "V5bA7N788eiT", "colab_type": "text"}, "source": ["> **Attention:** Please avoid using the TPU runtime (`TPU=True`) for now. The notebook contains an optional part on TPU usage at the end if you're interested. You can change the runtime via: \"Runtime > Change runtime type > Hardware Accelerator\" in Colab."]}, {"cell_type": "markdown", "metadata": {"id": "sAz1wTwOLX4j", "colab_type": "text"}, "source": ["## Data from Protobufs"]}, {"cell_type": "code", "metadata": {"id": "vxwdPWVhEU97", "colab_type": "code", "colab": {}}, "source": ["# Load data from Drive (Colab only).\n", "data_path = '/content/gdrive/My Drive/amld_data/zoo_img'\n", "\n", "# Or, you can load data from different sources, such as:\n", "# From your local machine:\n", "# data_path = './amld_data'\n", "\n", "# Or use a prepared dataset from Cloud (Colab only).\n", "# - 50k training examples, including pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img_small'\n", "# - 1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img'\n", "# - 4.1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/animals_img'\n", "# - 29M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/all_img'\n", "\n", "# Store models on Drive (Colab only).\n", "models_path = '/content/gdrive/My Drive/amld_data/models'\n", "\n", "# Or, store models to local machine.\n", "# models_path = './amld_models'"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "IvyLtRFLfXZs", "colab_type": "code", "outputId": "c2a41f1e-f2c9-422b-fe77-ee09a22bbcb3", "executionInfo": {"status": "ok", "timestamp": 1579904112087, "user_tz": 480, "elapsed": 38361, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 730}}, "source": ["if data_path.startswith('/content/gdrive/'):\n", " from google.colab import drive\n", " drive.mount('/content/gdrive')\n", "\n", "if data_path.startswith('gs://'):\n", " from google.colab import auth\n", " auth.authenticate_user()\n", " !gsutil ls -lh \"$data_path\"\n", "else:\n", " !ls -lh \"$data_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "4oCIc1XNTQ-v", "colab_type": "code", "outputId": "78ccd9e2-16fc-480e-8f61-0b6254f714ec", "executionInfo": {"status": "ok", "timestamp": 1579904112646, "user_tz": 480, "elapsed": 38911, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 52}}, "source": ["labels = [label.strip() for label \n", " in tf.io.gfile.GFile('{}/labels.txt'.format(data_path))]\n", "print('All labels in the dataset:', ' '.join(labels))\n", "\n", "counts = json.load(tf.io.gfile.GFile('{}/counts.json'.format(data_path)))\n", "print('Splits sizes:', counts)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "E9izb-IbIAhZ", "colab_type": "code", "outputId": "ffa57a65-675e-41a4-82ef-90dd424bb23d", "executionInfo": {"status": "ok", "timestamp": 1579904114203, "user_tz": 480, "elapsed": 40460, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 52}}, "source": ["# This dictionary specifies what \"features\" we want to extract from the\n", "# tf.train.Example protos (i.e. what they look like on disk). We only\n", "# need the image data \"img_64\" and the \"label\". Both features are tensors\n", "# with a fixed length.\n", "# You need to specify the correct \"shape\" and \"dtype\" parameters for\n", "# these features.\n", "feature_spec = {\n", " # Single label per example => shape=[1] (we could also use shape=() and\n", " # then do a transformation in the input_fn).\n", " 'label': tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),\n", " # The bytes_list data is parsed into tf.string.\n", " 'img_64': tf.io.FixedLenFeature(shape=[64, 64], dtype=tf.int64),\n", "}\n", "\n", "def parse_example(serialized_example):\n", " # Convert string to tf.train.Example and then extract features/label.\n", " features = tf.io.parse_single_example(serialized_example, feature_spec)\n", "\n", " # Important step: remove \"label\" from features!\n", " # Otherwise our classifier would simply learn to predict\n", " # label=features['label'].\n", " label = features.pop('label')\n", " label = tf.one_hot(tf.squeeze(label), len(labels))\n", "\n", " features['img_64'] = tf.cast(features['img_64'], tf.float32) / 255.\n", " return features['img_64'], label\n", "\n", "batch_size = 100\n", "steps_per_epoch = counts['train'] // batch_size\n", "eval_steps_per_epoch = counts['eval'] // batch_size\n", "\n", "# Create datasets from TFRecord files.\n", "train_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/train-*'.format(data_path)))\n", "train_ds = train_ds.map(parse_example)\n", "train_ds = train_ds.batch(batch_size).repeat()\n", "\n", "eval_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/eval-*'.format(data_path)))\n", "eval_ds = eval_ds.map(parse_example)\n", "eval_ds = eval_ds.batch(batch_size)\n", "\n", "# Read a single batch of examples from the training set and display shapes.\n", "for img_feature, label in train_ds:\n", " break\n", "print('img_feature.shape (batch_size, image_height, image_width) =', \n", " img_feature.shape)\n", "print('label.shape (batch_size, number_of_labels) =', label.shape)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "lwlhvv1VM1wQ", "colab_type": "code", "outputId": "d26092d8-dfb5-4daf-a0a9-1c7c0357fa60", "executionInfo": {"status": "ok", "timestamp": 1579904121574, "user_tz": 480, "elapsed": 47824, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 381}}, "source": ["# Visualize some examples from the training set.\n", "from matplotlib import pyplot as plt\n", "\n", "def show_img(img_64, title='', ax=None):\n", " \"\"\"Displays an image.\n", " \n", " Args:\n", " img_64: Array (or Tensor) with monochrome image data.\n", " title: Optional title.\n", " ax: Optional Matplotlib axes to show the image in.\n", " \"\"\"\n", " (ax if ax else plt).matshow(img_64.reshape((64, -1)), cmap='gray')\n", " if isinstance(img_64, tf.Tensor):\n", " img_64 = img_64.numpy()\n", " ax = ax if ax else plt.gca()\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(title)\n", " \n", "rows, cols = 3, 5\n", "for img_feature, label in train_ds:\n", " break\n", "_, axs = plt.subplots(rows, cols, figsize=(2*cols, 2*rows))\n", "for i in range(rows):\n", " for j in range(cols):\n", " show_img(img_feature[i*rows+j].numpy(), \n", " title=labels[label[i*rows+j].numpy().argmax()], ax=axs[i][j])"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "gZBM6OWqzv3L", "colab_type": "text"}, "source": ["## Linear model"]}, {"cell_type": "code", "metadata": {"id": "28qPSmJMaxBh", "colab_type": "code", "outputId": "93e67728-b0d1-4109-ed96-f2fea2ba5f66", "executionInfo": {"status": "ok", "timestamp": 1579904121575, "user_tz": 480, "elapsed": 47815, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Sample linear model.\n", "linear_model = tf.keras.Sequential()\n", "linear_model.add(tf.keras.layers.Flatten(input_shape=(64, 64,)))\n", "linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "# \"adam, categorical_crossentropy, accuracy\" and other string constants can be\n", "# found at https://keras.io.\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "\n", "linear_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "_BRK6TYLa09h", "colab_type": "code", "outputId": "3e5f09ef-2feb-4f49-fe66-94dd56c2b18a", "executionInfo": {"status": "ok", "timestamp": 1579904139379, "user_tz": 480, "elapsed": 65612, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 90}}, "source": ["linear_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=1,\n", " verbose=True)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "Pr0L9sVBqCj6", "colab_type": "text"}, "source": ["## Convolutional model"]}, {"cell_type": "code", "metadata": {"id": "EXqkgNozzz5U", "colab_type": "code", "outputId": "497e79a6-3b86-4693-addb-e1f39f8581be", "executionInfo": {"status": "ok", "timestamp": 1579904139604, "user_tz": 480, "elapsed": 65830, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 550}}, "source": ["# Let's define a convolutional model:\n", "conv_model = tf.keras.Sequential([\n", " tf.keras.layers.Reshape(target_shape=(64, 64, 1), input_shape=(64, 64)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.ZeroPadding2D((1,1)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'), \n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", " tf.keras.layers.Conv2D(filters=64, \n", " kernel_size=(5, 5), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", "\n", " tf.keras.layers.Flatten(),\n", " tf.keras.layers.Dense(256, activation='relu'),\n", " tf.keras.layers.Dropout(0.3),\n", " tf.keras.layers.Dense(len(labels), activation='softmax'),\n", "])\n", "\n", "# YOUR ACTION REQUIRED:\n", "# Compile + print summary of the model (analogous to the linear model above).\n"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "DsIUYEHC17ft", "colab_type": "code", "outputId": "cbbbcdf6-9085-43f8-d9d4-e82e173b0b83", "executionInfo": {"status": "ok", "timestamp": 1579904215104, "user_tz": 480, "elapsed": 141322, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 158}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Train the model (analogous to linear model above).\n", "# Note: You might want to reduce the number of steps if if it takes too long.\n", "# Pro tip: Change the runtime type (\"Runtime\" menu) to GPU! After the change you\n", "# will need to rerun the cells above because the Python kernel's state is reset.\n"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"colab_type": "text", "id": "E6W0XkCpB8fb"}, "source": ["## Store model"]}, {"cell_type": "code", "metadata": {"id": "d5E4keWeliXm", "colab_type": "code", "colab": {}}, "source": ["tf.io.gfile.makedirs(models_path)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "V94tLWcEJDeI", "colab_type": "code", "colab": {}}, "source": ["# Save model as Keras model.\n", "keras_path = os.path.join(models_path, 'linear.h5')\n", "linear_model.save(keras_path)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "uJj4acwemWDy", "colab_type": "code", "outputId": "e3f5f375-b2fc-483e-9eeb-9b8c34bb1fde", "executionInfo": {"status": "ok", "timestamp": 1579904216898, "user_tz": 480, "elapsed": 143101, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Keras model is a single file.\n", "!ls -hl \"$keras_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "SHHez3GZJD4u", "colab_type": "code", "outputId": "c6cfe9c0-7fce-4c75-c356-4fb06f4b08de", "executionInfo": {"status": "ok", "timestamp": 1579904217244, "user_tz": 480, "elapsed": 143440, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Load Keras model.\n", "loaded_keras_model = tf.keras.models.load_model(keras_path)\n", "loaded_keras_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "6RDHdn9wlSfe", "colab_type": "code", "outputId": "6f61c1cb-3af3-4749-bbfc-c8a94d07f96e", "executionInfo": {"status": "ok", "timestamp": 1579904224930, "user_tz": 480, "elapsed": 151118, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 107}}, "source": ["# Save model as Tensorflow Saved Model.\n", "saved_model_path = os.path.join(models_path, 'saved_model/linear')\n", "linear_model.save(saved_model_path, save_format='tf')"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "vdbtIUV8lbdz", "colab_type": "code", "outputId": "0830cb9b-3fac-47c3-dd07-f8255520c0da", "executionInfo": {"status": "ok", "timestamp": 1579904227015, "user_tz": 480, "elapsed": 153196, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 158}}, "source": ["# Inspect saved model directory structure.\n", "!find \"$saved_model_path\""], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "oy1Y5yjyCCZ3", "colab_type": "code", "outputId": "e32850a7-61e2-4b42-d5ad-fa39c665c08c", "executionInfo": {"status": "ok", "timestamp": 1579904227430, "user_tz": 480, "elapsed": 153604, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["saved_model = tf.keras.models.load_model(saved_model_path)\n", "saved_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "7SNX8oL6UFLH", "colab_type": "code", "outputId": "1ff5dbda-673c-4808-fdb2-c54cd9fb258c", "executionInfo": {"status": "ok", "timestamp": 1579904228845, "user_tz": 480, "elapsed": 155012, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 105}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Store the convolutional model and any additional models that you trained\n", "# in the previous sections in Keras format so we can use them in later\n", "# notebooks for prediction.\n"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "L519Q6CpQOwK", "colab_type": "text"}, "source": ["# ----- Optional part -----"]}, {"cell_type": "markdown", "metadata": {"id": "zRjVuDn9VhNG", "colab_type": "text"}, "source": ["## Learn from errors\n", "\n", "Looking at classification mistakes is a great way to better understand how a model is performing. This section walks you through the necessary steps to load some examples from the dataset, make predictions, and plot the mistakes."]}, {"cell_type": "code", "metadata": {"id": "xYydGO1CM7VG", "colab_type": "code", "colab": {}}, "source": ["import collections\n", "Mistake = collections.namedtuple('Mistake', 'label pred img_64')\n", "mistakes = []"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "rDvDfnezM_R_", "colab_type": "code", "outputId": "d60318a7-0bda-4553-95b0-50a4e04e8970", "executionInfo": {"status": "ok", "timestamp": 1579904228847, "user_tz": 480, "elapsed": 155003, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["for img_64_batch, label_onehot_batch in eval_ds:\n", " break\n", "img_64_batch.shape, label_onehot_batch.shape"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "YHdHqTdaRBZ_", "colab_type": "code", "colab": {}}, "source": ["# YOUR ACTION REQUIRED:\n", "# Use model.predict() to get a batch of predictions.\n", "preds =\n"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "uMGfVv3ONeyz", "colab_type": "code", "outputId": "3d8ab338-f185-4b61-b2e6-3562042760b0", "executionInfo": {"status": "ok", "timestamp": 1579904229129, "user_tz": 480, "elapsed": 155275, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Iterate through the batch:\n", "for label_onehot, pred, img_64 in zip(label_onehot_batch, preds, img_64_batch):\n", " # YOUR ACTION REQUIRED:\n", " # Both `label_onehot` and pred are vectors with length=len(labels), with every\n", " # element corresponding to a probability of the corresponding class in\n", " # `labels`. Get the value with the highest value to get the index within\n", " # `labels`.\n", " label_i = \n", " pred_i =\n", " if label_i != pred_i:\n", " mistakes.append(Mistake(label_i, pred_i, img_64.numpy()))\n", "\n", "# You can run this cell multiple times to get more mistakes. \n", "len(mistakes)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "rwq_0tTDXLbJ", "colab_type": "code", "outputId": "98675cd3-3260-461e-d4e9-817981d1a7bd", "executionInfo": {"status": "ok", "timestamp": 1579904230327, "user_tz": 480, "elapsed": 156466, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 735}}, "source": ["# Let's examine the cases when our model gets it wrong. Would you recognize\n", "# these images correctly?\n", "\n", "# YOUR ACTION REQUIRED:\n", "# Run above cell but using a different model to get a different set of\n", "# classification mistakes. Then copy over this cell to plot the mistakes for\n", "# comparison purposes. Can you spot a pattern?\n", "rows, cols = 5, 5\n", "plt.figure(figsize=(cols*2.5, rows*2.5))\n", "for i, mistake in enumerate(mistakes[:rows*cols]):\n", " ax = plt.subplot(rows, cols, i + 1)\n", " title = '{}? {}!'.format(labels[mistake.pred], labels[mistake.label])\n", " show_img(mistake.img_64, title, ax)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "eids_xB-QzYL", "colab_type": "text"}, "source": ["## Data from DataFrame\n", "\n", "For comparison, this section shows how you would load data from a `pandas.DataFrame` and then use Keras for training. Note that this approach does not scale well and can only be used for quite small datasets."]}, {"cell_type": "code", "metadata": {"id": "fKETADXa622b", "colab_type": "code", "outputId": "198f7844-9456-4865-c18a-67fa3063cf6a", "executionInfo": {"status": "ok", "timestamp": 1579904232507, "user_tz": 480, "elapsed": 158639, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory BEFORE loading the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "lVHGBT_q3-zq", "colab_type": "code", "outputId": "f468e68b-82d4-491b-d820-5719f75764a7", "executionInfo": {"status": "ok", "timestamp": 1579904273004, "user_tz": 480, "elapsed": 199128, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 87}}, "source": ["# Loading all the data in memory takes a while (~40s).\n", "import pickle\n", "df = pickle.load(tf.io.gfile.GFile('%s/dataframe.pkl' % data_path, mode='rb'))\n", "print(len(df))\n", "print(df.columns)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "GTnEjQIDfQeM", "colab_type": "code", "outputId": "ffda698c-e0bd-4e9a-825c-9fd7aad56285", "executionInfo": {"status": "ok", "timestamp": 1579904275288, "user_tz": 480, "elapsed": 201404, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["df_train = df[df.split == b'train']\n", "len(df_train)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "Aagi5RJlLz4k", "colab_type": "code", "outputId": "c3f448aa-338e-4789-9c7c-0aebc38dadb7", "executionInfo": {"status": "ok", "timestamp": 1579904277142, "user_tz": 480, "elapsed": 203249, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory AFTER loading the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"colab_type": "code", "id": "0gKHIOswcPM1", "outputId": "5208bf1d-d2e8-4fa2-800b-88ddeee3e0f4", "executionInfo": {"status": "ok", "timestamp": 1579904277845, "user_tz": 480, "elapsed": 203945, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 381}}, "source": ["# Show some images from the dataset.\n", "\n", "from matplotlib import pyplot as plt\n", "\n", "def show_img(img_64, title='', ax=None):\n", " (ax if ax else plt).matshow(img_64.reshape((64, -1)), cmap='gray')\n", " ax = ax if ax else plt.gca()\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", " ax.set_title(title)\n", "\n", "rows, cols = 3, 3\n", "_, axs = plt.subplots(rows, cols, figsize=(2*cols, 2*rows))\n", "for i in range(rows):\n", " for j in range(cols):\n", " d = df.sample(1).iloc[0]\n", " show_img(d.img_64, title=labels[d.label], ax=axs[i][j])"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "41_3dkqMPmG0", "colab_type": "code", "colab": {}}, "source": ["df_x = tf.convert_to_tensor(df_train.img_64, dtype=tf.float32)\n", "df_y = tf.one_hot(df_train.label, depth=len(labels), dtype=tf.float32)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "c7k02_QQSYs2", "colab_type": "code", "outputId": "a884ed09-6d9d-4dfc-f578-8539946c3a15", "executionInfo": {"status": "ok", "timestamp": 1579904314896, "user_tz": 480, "elapsed": 240985, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 70}}, "source": ["# Note: used memory AFTER defining the Tensors based on the DataFrame.\n", "!free -h"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "zEwkFKFuTBu0", "colab_type": "code", "outputId": "70dd909a-cf87-435a-82ba-79c31893d506", "executionInfo": {"status": "ok", "timestamp": 1579904314897, "user_tz": 480, "elapsed": 240980, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["# Checkout the shape of these rather large tensors.\n", "df_x.shape, df_x.dtype, df_y.shape, df_y.dtype"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "98NBAasHXfMq", "colab_type": "code", "outputId": "d9b631c9-31fc-412d-db39-0a062acbed48", "executionInfo": {"status": "ok", "timestamp": 1579904317379, "user_tz": 480, "elapsed": 243455, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 283}}, "source": ["# Copied code from section \"Linear model\" above.\n", "linear_model = tf.keras.Sequential()\n", "linear_model.add(tf.keras.layers.Flatten(input_shape=(64 * 64,)))\n", "linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "# \"adam, categorical_crossentropy, accuracy\" and other string constants can be\n", "# found at https://keras.io.\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "linear_model.summary()\n", "\n", "# How much of a speedup do you see because the data is already in memory?\n", "# How would this compare to the convolutional model?\n", "linear_model.fit(df_x, df_y, epochs=1, batch_size=100)"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "XAItlmUwv1TZ", "colab_type": "text"}, "source": ["## TPU Support\n", "\n", "For using TF with a TPU we'll need to make some adjustments. Generally, please note that several TF TPU features are experimental and might not work as smooth as it does with a CPU or GPU.\n", "\n", "> **Attention:** Please make sure to switch the runtime to TPU for this part. You can do so via: \"Runtime > Change runtime type > Hardware Accelerator\" in Colab. As this might create a new environment this section can be executed isolated from anything above."]}, {"cell_type": "code", "metadata": {"colab_type": "code", "id": "kTGjOm631BQw", "outputId": "4278689a-0721-4f63-c5e0-dc18548c2465", "executionInfo": {"status": "ok", "timestamp": 1579904388257, "user_tz": 480, "elapsed": 30360, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 34}}, "source": ["%tensorflow_version 2.x"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"colab_type": "code", "outputId": "cdc179c6-5918-4f35-f4b8-dcd5fde6e34c", "executionInfo": {"status": "ok", "timestamp": 1579904408572, "user_tz": 480, "elapsed": 50666, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "id": "QgVEQxLo1BQ3", "colab": {"base_uri": "https://localhost:8080/", "height": 425}}, "source": ["import json, os\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "import tensorflow as tf\n", "\n", "# Disable duplicate logging output in TF.\n", "logger = tf.get_logger()\n", "logger.propagate = False\n", "\n", "# This will fail if no TPU is connected...\n", "tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n", "# Set up distribution strategy.\n", "tf.config.experimental_connect_to_cluster(tpu)\n", "tf.tpu.experimental.initialize_tpu_system(tpu);\n", "strategy = tf.distribute.experimental.TPUStrategy(tpu)\n", "\n", "# Tested with TensorFlow 2.1.0\n", "print('\\n\\nTF version={} TPUs={} accelerators={}'.format(\n", " tf.__version__, tpu.cluster_spec().as_dict()['worker'],\n", " strategy.num_replicas_in_sync))"], "execution_count": null, "outputs": []}, {"cell_type": "markdown", "metadata": {"id": "liv2SeFnXerM", "colab_type": "text"}, "source": ["> **Attention:** TPUs require all files (input and models) to be stored in cloud storage buckets (`gs://bucket-name/...`). If you plan to use TPUs please choose the `data_path` below accordingly. Otherwise, you might run into `File system scheme '[local]' not implemented` errors."]}, {"cell_type": "code", "metadata": {"id": "9kWkMWjHxn09", "colab_type": "code", "colab": {}}, "source": ["from google.colab import auth\n", "auth.authenticate_user()\n", "\n", "# Browse datasets:\n", "# https://console.cloud.google.com/storage/browser/amld-datasets\n", "\n", "# - 50k training examples, including pickled DataFrame.\n", "data_path = 'gs://amld-datasets/zoo_img_small'\n", "# - 1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/zoo_img'\n", "# - 4.1M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/animals_img'\n", "# - 29M training examples, without pickled DataFrame.\n", "# data_path = 'gs://amld-datasets/all_img'"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "nZLuuaY72RxT", "colab_type": "code", "cellView": "form", "outputId": "ac23d955-18f1-4900-b9ee-82dca2aea836", "executionInfo": {"status": "ok", "timestamp": 1579904479930, "user_tz": 480, "elapsed": 122010, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 87}}, "source": ["#@markdown **Copied and adjusted data definition code from above**\n", "#@markdown\n", "#@markdown    Note: You can double-click this cell to see its code.\n", "#@markdown\n", "#@markdown The changes have been highlighted with `!` in the contained code\n", "#@markdown (things like the `batch_size` and added `drop_remainder=True`).\n", "#@markdown\n", "#@markdown Feel free to just **click \"execute\"** and ignore the details for now.\n", "\n", "labels = [label.strip() for label \n", " in tf.io.gfile.GFile('{}/labels.txt'.format(data_path))]\n", "print('All labels in the dataset:', ' '.join(labels))\n", "\n", "counts = json.load(tf.io.gfile.GFile('{}/counts.json'.format(data_path)))\n", "print('Splits sizes:', counts)\n", "\n", "# This dictionary specifies what \"features\" we want to extract from the\n", "# tf.train.Example protos (i.e. what they look like on disk). We only\n", "# need the image data \"img_64\" and the \"label\". Both features are tensors\n", "# with a fixed length.\n", "# You need to specify the correct \"shape\" and \"dtype\" parameters for\n", "# these features.\n", "feature_spec = {\n", " # Single label per example => shape=[1] (we could also use shape=() and\n", " # then do a transformation in the input_fn).\n", " 'label': tf.io.FixedLenFeature(shape=[1], dtype=tf.int64),\n", " # The bytes_list data is parsed into tf.string.\n", " 'img_64': tf.io.FixedLenFeature(shape=[64, 64], dtype=tf.int64),\n", "}\n", "\n", "def parse_example(serialized_example):\n", " # Convert string to tf.train.Example and then extract features/label.\n", " features = tf.io.parse_single_example(serialized_example, feature_spec)\n", "\n", " # Important step: remove \"label\" from features!\n", " # Otherwise our classifier would simply learn to predict\n", " # label=features['label'].\n", " label = features.pop('label')\n", " label = tf.one_hot(tf.squeeze(label), len(labels))\n", "\n", " features['img_64'] = tf.cast(features['img_64'], tf.float32)\n", " return features['img_64'], label\n", "\n", "# Adjust the batch size to the given hardware (#accelerators).\n", "batch_size = 64 * strategy.num_replicas_in_sync\n", "# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", "steps_per_epoch = counts['train'] // batch_size\n", "eval_steps_per_epoch = counts['eval'] // batch_size\n", "\n", "# Create datasets from TFRecord files.\n", "train_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/train-*'.format(data_path)))\n", "train_ds = train_ds.map(parse_example)\n", "train_ds = train_ds.batch(batch_size, drop_remainder=True).repeat()\n", "# !!!!!!!!!!!!!!!!!!!\n", "\n", "eval_ds = tf.data.TFRecordDataset(tf.io.gfile.glob(\n", " '{}/eval-*'.format(data_path)))\n", "eval_ds = eval_ds.map(parse_example)\n", "eval_ds = eval_ds.batch(batch_size, drop_remainder=True)\n", "# !!!!!!!!!!!!!!!!!!!\n", "# Read a single example and display shapes.\n", "for img_feature, label in train_ds:\n", " break\n", "print('img_feature.shape (batch_size, image_height, image_width) =', \n", " img_feature.shape)\n", "print('label.shape (batch_size, number_of_labels) =', label.shape)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "nF5wDYvjyk1K", "colab_type": "code", "outputId": "f73c2530-fb42-49c7-a690-aa37c5c5acc1", "executionInfo": {"status": "ok", "timestamp": 1579904479930, "user_tz": 480, "elapsed": 122004, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 230}}, "source": ["# Model definition code needs to be wrapped in scope.\n", "with strategy.scope():\n", " linear_model = tf.keras.Sequential()\n", " linear_model.add(tf.keras.layers.Flatten(input_shape=(64, 64,)))\n", " linear_model.add(tf.keras.layers.Dense(len(labels), activation='softmax'))\n", "\n", "linear_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy', tf.keras.metrics.categorical_accuracy])\n", "linear_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "CAHTLSQs7hRd", "colab_type": "code", "outputId": "1ed70722-c850-410d-fdc0-16472b16576c", "executionInfo": {"status": "ok", "timestamp": 1579904507182, "user_tz": 480, "elapsed": 149250, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 90}}, "source": ["linear_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=1,\n", " verbose=True)"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "NVaTmhROzHE-", "colab_type": "code", "outputId": "4ba9ebd6-1441-4075-a269-e8b212d2e5ac", "executionInfo": {"status": "ok", "timestamp": 1579904508096, "user_tz": 480, "elapsed": 150158, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 550}}, "source": ["# Model definition code needs to be wrapped in scope.\n", "with strategy.scope():\n", " conv_model = tf.keras.Sequential([\n", " tf.keras.layers.Reshape(target_shape=(64, 64, 1), input_shape=(64, 64)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.ZeroPadding2D((1,1)),\n", " tf.keras.layers.Conv2D(filters=32, \n", " kernel_size=(10, 10), \n", " padding='same', \n", " activation='relu'), \n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", " tf.keras.layers.Conv2D(filters=64, \n", " kernel_size=(5, 5), \n", " padding='same', \n", " activation='relu'),\n", " tf.keras.layers.MaxPooling2D(pool_size=(4, 4), strides=(4,4)),\n", "\n", " tf.keras.layers.Flatten(),\n", " tf.keras.layers.Dense(256, activation='relu'),\n", " tf.keras.layers.Dropout(0.3),\n", " tf.keras.layers.Dense(len(labels), activation='softmax'),\n", " ])\n", "\n", "conv_model.compile(\n", " optimizer='adam',\n", " loss='categorical_crossentropy',\n", " metrics=['accuracy'])\n", "conv_model.summary()"], "execution_count": null, "outputs": []}, {"cell_type": "code", "metadata": {"id": "Ye5y9nIt7p1m", "colab_type": "code", "outputId": "02b99428-8865-488c-c023-33acd58cca8b", "executionInfo": {"status": "ok", "timestamp": 1579904592275, "user_tz": 480, "elapsed": 234331, "user": {"displayName": "Andreas Steiner", "photoUrl": "https://lh3.googleusercontent.com/a-/AAuE7mAYx167H2vNmFSKlsQkQY-bjbJ-3sPGymaG0kXO=s64", "userId": "08860260976100898876"}}, "colab": {"base_uri": "https://localhost:8080/", "height": 176}}, "source": ["conv_model.fit(train_ds,\n", " validation_data=eval_ds,\n", " steps_per_epoch=steps_per_epoch,\n", " validation_steps=eval_steps_per_epoch,\n", " epochs=3,\n", " verbose=True)\n", "conv_model.evaluate(eval_ds, steps=eval_steps_per_epoch)"], "execution_count": null, "outputs": []}]}