{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "google_colab_mnist_example.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true, "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "KScAHZqbQ_Sr", "colab_type": "text" }, "source": [ "# MNIST Classification " ] }, { "cell_type": "markdown", "metadata": { "id": "eXNb7rQOQ2bW", "colab_type": "text" }, "source": [ "\n", "In this lesson we discuss in how to create a simple IPython Notebook to solve\n", "an image classification problem. MNIST contains a set of pictures\n" ] }, { "cell_type": "markdown", "metadata": { "id": "ZLpLVkFLRK-1", "colab_type": "text" }, "source": [ "## Import Libraries \n", "\n", "Note: https://python-future.org/quickstart.html" ] }, { "cell_type": "code", "metadata": { "id": "HqorYeyBkCyi", "colab_type": "code", "colab": {} }, "source": [ "from __future__ import absolute_import\n", "from __future__ import division\n", "from __future__ import print_function\n", "\n", "import numpy as np\n", "from keras.models import Sequential\n", "from keras.layers import Dense, Activation, Dropout\n", "from keras.utils import to_categorical, plot_model\n", "from keras.datasets import mnist" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "kmlJQqK42Cs2", "colab_type": "text" }, "source": [ "## Warm Up Exercise" ] }, { "cell_type": "markdown", "metadata": { "id": "YajEPjlyRkrr", "colab_type": "text" }, "source": [ "## Pre-process data" ] }, { "cell_type": "markdown", "metadata": { "id": "4yOjQ9cjRrwQ", "colab_type": "text" }, "source": [ "### Load data \n", "\n", "First we load the data from the inbuilt mnist dataset from Keras\n", "Here we have to split the data set into training and testing data. \n", "The training data or testing data has two components. \n", "Training features and training labels. \n", "For instance every sample in the dataset has a corresponding label. \n", "In Mnist the training sample contains image data represented in terms of \n", "an array. The training labels are from 0-9. \n", "\n", "Here we say x_train for training data features and y_train as the training labels. Same goes for testing data. " ] }, { "cell_type": "code", "metadata": { "id": "LN7h9FQ-kIzB", "colab_type": "code", "colab": {} }, "source": [ "(x_train, y_train), (x_test, y_test) = mnist.load_data()" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "AJJxAbKxR7kZ", "colab_type": "text" }, "source": [ "### Identify Number of Classes\n", "\n", "As this is a number classification problem. We need to know how many classes are there. \n", "So we'll count the number of unique labels. " ] }, { "cell_type": "code", "metadata": { "id": "laqnfrEBSFxZ", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 35 }, "outputId": "10b86ed2-c8f8-4f02-9f82-9cbb3f11405d" }, "source": [ "num_labels = len(np.unique(y_train))\n", "num_labels" ], "execution_count": null, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "10" ] }, "metadata": { "tags": [] }, "execution_count": 3 } ] }, { "cell_type": "markdown", "metadata": { "id": "ugx6012YSXtA", "colab_type": "text" }, "source": [ "### Convert Labels To One-Hot Vector\n", "\n", "Read more on one-hot vector. " ] }, { "cell_type": "code", "metadata": { "id": "dpSBHnBEScZN", "colab_type": "code", "colab": {} }, "source": [ "y_train = to_categorical(y_train)\n", "y_test = to_categorical(y_test)\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "vyAfgPaJU753", "colab_type": "text" }, "source": [ "## Image Reshaping\n", "\n", "The training model is designed by considering the data as a vector.\n", "This is a model dependent modification. Here we assume the image is\n", "a squared shape image." ] }, { "cell_type": "code", "metadata": { "id": "8vxzUIK8Sedn", "colab_type": "code", "colab": {} }, "source": [ "image_size = x_train.shape[1]\n", "input_size = image_size * image_size" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "gZnBo49lVWDM", "colab_type": "text" }, "source": [ "## Resize and Normalize\n", "\n", "The next step is to continue the reshaping to a fit into a vector\n", "and normalize the data. Image values are from 0 - 255, so an \n", "easy way to normalize is to divide by the maximum value. \n" ] }, { "cell_type": "code", "metadata": { "id": "b9qUX7mwSf-u", "colab_type": "code", "colab": {} }, "source": [ "x_train = np.reshape(x_train, [-1, input_size])\n", "x_train = x_train.astype('float32') / 255\n", "x_test = np.reshape(x_test, [-1, input_size])\n", "x_test = x_test.astype('float32') / 255" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "tn89L_-zVxUB", "colab_type": "text" }, "source": [ "## Create a Keras Model\n", "\n", "Keras is a neural network library. The summary function provides tabular summary on the model you created. And the plot_model function provides a grpah on the network you created. " ] }, { "cell_type": "code", "metadata": { "id": "c3o_k-adkOy4", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 676 }, "outputId": "8b2e1a0e-386a-4b43-8cb2-afd82d2bfd1a" }, "source": [ "# Create Model\n", "# network parameters\n", "batch_size = 4\n", "hidden_units = 64\n", "\n", "model = Sequential()\n", "model.add(Dense(hidden_units, input_dim=input_size))\n", "model.add(Dense(num_labels))\n", "model.add(Activation('softmax'))\n", "model.summary()\n", "plot_model(model, to_file='mlp-mnist.png', show_shapes=True)" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Model: \"sequential\"\n", "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "dense (Dense) (None, 64) 50240 \n", "_________________________________________________________________\n", "dense_1 (Dense) (None, 10) 650 \n", "_________________________________________________________________\n", "activation (Activation) (None, 10) 0 \n", "=================================================================\n", "Total params: 50,890\n", "Trainable params: 50,890\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ], "name": "stdout" }, { "output_type": "execute_result", "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "tags": [] }, "execution_count": 7 } ] }, { "cell_type": "markdown", "metadata": { "id": "nwl6dlU3aStZ", "colab_type": "text" }, "source": [ "## Compile and Train\n", "\n", "A keras model need to be compiled before it can be used to train\n", "the model. In the compile function, you can provide the optimization\n", "that you want to add, metrics you expect and the type of loss function\n", "you need to use. \n", "\n", "Here we use adam optimizer, a famous optimizer used in neural networks. \n", "\n", "The loss funtion we have used is the categorical_crossentropy. \n", "\n", "Once the model is compiled, then the fit function is called upon passing the number of epochs, traing data and batch size. \n", "\n", "The batch size determines the number of elements used per minibatch in optimizing the function. \n", "\n", "**Note: Change the number of epochs, batch size and see what happens.**\n", "\n" ] }, { "cell_type": "code", "metadata": { "id": "WkUMyJyEmsM6", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 145 }, "outputId": "0645d95f-1b56-4cb7-fde1-8f9b244178be" }, "source": [ "model.compile(loss='categorical_crossentropy',\n", " optimizer='adam',\n", " metrics=['accuracy'])\n", "\n", "model.fit(x_train, y_train, epochs=3, batch_size=batch_size)" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "Epoch 1/3\n", "15000/15000 [==============================] - 17s 1ms/step - loss: 0.3112 - accuracy: 0.9121\n", "Epoch 2/3\n", "15000/15000 [==============================] - 17s 1ms/step - loss: 0.3003 - accuracy: 0.9152\n", "Epoch 3/3\n", "15000/15000 [==============================] - 17s 1ms/step - loss: 0.2931 - accuracy: 0.9179\n" ], "name": "stdout" }, { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": { "tags": [] }, "execution_count": 10 } ] }, { "cell_type": "markdown", "metadata": { "id": "fDAY7JYmbmOq", "colab_type": "text" }, "source": [ "## Testing \n", "\n", "Now we can test the trained model. Use the evaluate function by passing\n", "test data and batch size and the accuracy and the loss value can be retrieved.\n", "\n", "**MNIST_V1.0|Exercise: Try to observe the network behavior by changing the number of epochs, batch size and record the best accuracy that you can gain. Here you can record what happens when you change these values. Describe your observations in 50-100 words.**\n" ] }, { "cell_type": "code", "metadata": { "id": "0sfTk_pcjXHD", "colab_type": "code", "colab": { "base_uri": "https://localhost:8080/", "height": 72 }, "outputId": "88fffbf5-500b-4708-9dcc-829501830d35" }, "source": [ "loss, acc = model.evaluate(x_test, y_test, batch_size=batch_size)\n", "print(\"\\nTest accuracy: %.1f%%\" % (100.0 * acc))" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "2500/2500 [==============================] - 2s 790us/step - loss: 0.3273 - accuracy: 0.9070\n", "\n", "Test accuracy: 90.7%\n" ], "name": "stdout" } ] }, { "cell_type": "markdown", "metadata": { "id": "b2fDpqnfcEmC", "colab_type": "text" }, "source": [ "## Final Note\n", "\n", "This programme can be defined as a hello world programme in deep\n", "learning. Objective of this exercise is not to teach you the depths of\n", "deep learning. But to teach you basic concepts that may need to design a\n", "simple network to solve a problem. Before running the whole code, read\n", "all the instructions before a code section. \n", "\n", "## Homework\n", "\n", "**Solve Exercise MNIST_V1.0.**" ] }, { "cell_type": "markdown", "metadata": { "id": "UufRkOsSRaUR", "colab_type": "text" }, "source": [ "\n", "### Reference: \n", "\n", "[Orignal Source to Source Code](https://github.com/PacktPublishing/Advanced-Deep-Learning-with-Keras)\n" ] } ] }