Skip to content

Instantly share code, notes, and snippets.

@ZohebAbai
Last active April 8, 2019 08:16
Show Gist options
  • Save ZohebAbai/cb916d544752de359d1f51b734f9e1ef to your computer and use it in GitHub Desktop.
Save ZohebAbai/cb916d544752de359d1f51b734f9e1ef to your computer and use it in GitHub Desktop.
'Hello World' of Deep Learning.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "'Hello World' of Deep Learning.ipynb",
"version": "0.3.2",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/ZohebAbai/cb916d544752de359d1f51b734f9e1ef/-hello-world-of-deep-learning.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"metadata": {
"id": "7Fr8_N543BWl",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"# 'Hello World' of Deep Learning\n",
"\n",
"#### [MNIST](http://yann.lecun.com/exdb/mnist/) dataset consists of a training set of 60,000 examples and a test set of 10,000 examples, where each example is a 28x28 grayscale image of handwritten digits, associated with a label between 0 to 9.\n",
"#### MNIST is often the dataset everyone builds their first deep learning model while entering this field. Members of the AI/ML/Data Science community love this dataset and use it as a benchmark to validate their algorithms. They say,\n",
"`\"If it doesn't work on MNIST, it won't work at all\"` "
]
},
{
"metadata": {
"id": "PspcidDf3e1D",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Here, we will build two types of deep learning models using Keras API of tensorflow and aim to achieve 99% training accuracy in less than 10 epochs. Our first approach shall be building a model using only dense layers wheras the second approach shall be building a model using only convolution layers.**\n",
"\n",
"**In addition, instead of waiting for 10 epochs to finish, we shall add a function in our models so that when it reaches 99% or greater at end of that epoch, it prints out the string \"Reached 99% accuracy so cancelling training!\".**\n",
"\n",
"**On the basis of the number of parameters, how fast it reaches 99% and test accuracy, we can infer which type of model overall performs better than the other for Image Recognition challenges.**"
]
},
{
"metadata": {
"id": "uh9XuU8H8mpc",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Import Libraries and Datasets"
]
},
{
"metadata": {
"id": "1CvBsjEO8xhT",
"colab_type": "code",
"outputId": "813d4ed8-c5e3-440d-8911-468d9dd054b5",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"cell_type": "code",
"source": [
"# import tensorflow and print its version\n",
"import tensorflow as tf\n",
"print(tf.__version__)"
],
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"text": [
"1.13.1\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "2uY9mrby2_6V",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# MNIST data is available directly in the tf.keras datasets API\n",
"mnist = tf.keras.datasets.mnist"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "XAKjN_W59k6J",
"colab_type": "code",
"outputId": "5ec96db1-5897-4d5d-e414-8395a292c4bb",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 51
}
},
"cell_type": "code",
"source": [
"# calling load_data on this object will give you two sets of two lists, \n",
"# these are training and testing datasets which contains images as x and their labels as y\n",
"(x_train, y_train),(x_test, y_test) = mnist.load_data()"
],
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"text": [
"Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n",
"11493376/11490434 [==============================] - 0s 0us/step\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "rRioQebBd4ne",
"colab_type": "code",
"outputId": "7ac948da-4f2b-49cf-d61f-1f0aff80fc50",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 85
}
},
"cell_type": "code",
"source": [
"#Lets see the shape of the dataset\n",
"print(x_train.shape)\n",
"print(y_train.shape)\n",
"print(x_test.shape)\n",
"print(y_test.shape)"
],
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"text": [
"(60000, 28, 28)\n",
"(60000,)\n",
"(10000, 28, 28)\n",
"(10000,)\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "OrOCPFrS-IJr",
"colab_type": "code",
"outputId": "c82fb9f0-fd38-4429-c41b-6e135ebddbe0",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 364
}
},
"cell_type": "code",
"source": [
"# Let's visualize the 1st image of training dataset and print its label\n",
"import matplotlib.pyplot as plt\n",
"plt.imshow(x_train[0])\n",
"print(y_train[0])"
],
"execution_count": 5,
"outputs": [
{
"output_type": "stream",
"text": [
"5\n"
],
"name": "stdout"
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x396 with 1 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"metadata": {
"id": "UxaP1WCy-oxU",
"colab_type": "code",
"outputId": "7c49bc37-a823-43c9-bf6b-87883d5c14d3",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 986
}
},
"cell_type": "code",
"source": [
"# Let's printout its pixel values and print its label\n",
"# Here 0 value represents white and 255 represent black and grey in between\n",
"print(y_train[0])\n",
"print(x_train[0])"
],
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": [
"5\n",
"[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 3 18 18 18 126 136\n",
" 175 26 166 255 247 127 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 30 36 94 154 170 253 253 253 253 253\n",
" 225 172 253 242 195 64 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 49 238 253 253 253 253 253 253 253 253 251\n",
" 93 82 82 56 39 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 18 219 253 253 253 253 253 198 182 247 241\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 80 156 107 253 253 205 11 0 43 154\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 14 1 154 253 90 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 139 253 190 2 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 11 190 253 70 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 35 241 225 160 108 1\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 81 240 253 253 119\n",
" 25 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 45 186 253 253\n",
" 150 27 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 93 252\n",
" 253 187 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 249\n",
" 253 249 64 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 46 130 183 253\n",
" 253 207 2 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 39 148 229 253 253 253\n",
" 250 182 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 24 114 221 253 253 253 253 201\n",
" 78 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 23 66 213 253 253 253 253 198 81 2\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 18 171 219 253 253 253 253 195 80 9 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 55 172 226 253 253 253 253 244 133 11 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 136 253 253 253 212 135 132 16 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]\n",
" [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
" 0 0 0 0 0 0 0 0 0 0]]\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "cQ7nErhz7d8G",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## 1. Model Building using Dense Layers Only"
]
},
{
"metadata": {
"id": "gByR4x4HAcBy",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# No we shall normalize every image in the dataset before training a neural network\n",
"# for various reasons it's easier if we treat all values between 0 and 1\n",
"x_train = x_train/255.0\n",
"x_test = x_test/255.0"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "tyBJ-VrMDRVh",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**We feed the data not as images (28x28) but as 1D arrays (784). **\n",
"\n",
"**Let's visualize the first image reshaped as 1D array before feeding: **"
]
},
{
"metadata": {
"id": "DznRqnUsDpXi",
"colab_type": "code",
"outputId": "e7ae71fd-aa14-4e8b-d7ed-b70e9fcef338",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 368
}
},
"cell_type": "code",
"source": [
"plt.imshow(x_train[0].reshape(784,1),cmap='gist_gray',aspect=0.005)"
],
"execution_count": 8,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7fdcf32e82e8>"
]
},
"metadata": {
"tags": []
},
"execution_count": 8
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x396 with 1 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"metadata": {
"id": "Ld0mCKilBui7",
"colab_type": "code",
"outputId": "47ef389f-403d-41ed-b44e-893c91a6eb29",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
}
},
"cell_type": "code",
"source": [
"# Define the model\n",
"model = tf.keras.models.Sequential([tf.keras.layers.Flatten(input_shape=(28, 28)),\n",
" tf.keras.layers.Dense(128, activation=tf.nn.relu),\n",
" tf.keras.layers.Dense(10, activation=tf.nn.softmax)])"
],
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"text": [
"WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:435: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Colocations handled automatically by placer.\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "8D_aRPlwKASm",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**For your understanding :**\n",
"\n",
"**Sequential**: That defines a SEQUENCE of layers in the neural network\n",
"\n",
"**Flatten**: It just takes the image(28x28) and turns/flattens it into a 1 dimensional (784) array\n",
"\n",
"**Dense**: Adds a layer of neurons, 10 or 128 denotes the number of neurons\n",
"\n",
"Each layer of neurons need an **activation function** to tell them what to do. There's lots of options, but for our purpose we shall use these (widely used!):\n",
"\n",
"**Relu** effectively means \"If X>0, return X, else return 0\" -- so what it does it it only passes values 0 or greater to the next layer in the network.\n",
"\n",
"**Softmax** takes a set of values, and effectively picks the biggest one, so, for example, if the output of the last layer looks like [0.1, 0.1, 0.05, 0.1, 9.5, 0.1, 0.05, 0.05, 0.05], it saves you from fishing through it looking for the biggest value, and turns it into [0,0,0,0,1,0,0,0,0] -- The goal is to save a lot of coding!"
]
},
{
"metadata": {
"id": "C7smafwrMVOP",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Before building the model, let's define a function whose job will be to stop running the model if we achieved 99% accuracy before 10 epochs. No need to wait till the end.**"
]
},
{
"metadata": {
"id": "2ZFEfdUrL038",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"class myCallback(tf.keras.callbacks.Callback):\n",
" def on_epoch_end(self, epoch, logs={}):\n",
" if(logs.get('acc')>0.99):\n",
" print(\"\\nReached 99% accuracy so cancelling training!\")\n",
" self.model.stop_training = True\n",
"\n",
"callbacks = myCallback()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "L0Y-j8AwPxJt",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Now we shall compile the model with an optimizer and loss function and then train it by calling model.fit asking it to fit our training data to our training labels. This way it figures out the relationship between the training data and its actual labels, so that in future if we have data that looks like the training data, then it will be able to make a prediction for that data.**"
]
},
{
"metadata": {
"id": "zPk3Lee1W0x0",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**For your understanding:**\n",
"\n",
"**Adam Optimizer** : Check out this [tutorial](https://www.youtube.com/watch?v=JXQT_vxqwIs) by Andrew Ng\n",
"\n",
"**Sparse categorical crossentropy loss function** : Check out this [article](https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/) by Jovian Lin\n",
"\n",
"**Accuracy metric** : For each data is defined as proportion of predicted correct labels to total number of predicted labels for that data. Overall accuracy is average across the dataset."
]
},
{
"metadata": {
"id": "ihuq2WzKFwEO",
"colab_type": "code",
"outputId": "1cbf29c0-def6-4670-8b9b-dea6ac2f72ce",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 306
}
},
"cell_type": "code",
"source": [
"# Build the model\n",
"model.compile(optimizer = 'adam',\n",
" loss = 'sparse_categorical_crossentropy',\n",
" metrics=['accuracy'])\n",
"\n",
"model.fit(x_train, y_train, epochs=10, callbacks=[callbacks])"
],
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"60000/60000 [==============================] - 8s 131us/sample - loss: 0.2605 - acc: 0.9244\n",
"Epoch 2/10\n",
"60000/60000 [==============================] - 7s 118us/sample - loss: 0.1142 - acc: 0.9665\n",
"Epoch 3/10\n",
"60000/60000 [==============================] - 8s 126us/sample - loss: 0.0780 - acc: 0.9762\n",
"Epoch 4/10\n",
"60000/60000 [==============================] - 8s 125us/sample - loss: 0.0583 - acc: 0.9824\n",
"Epoch 5/10\n",
"60000/60000 [==============================] - 8s 127us/sample - loss: 0.0456 - acc: 0.9861\n",
"Epoch 6/10\n",
"60000/60000 [==============================] - 7s 125us/sample - loss: 0.0365 - acc: 0.9885\n",
"Epoch 7/10\n",
"59680/60000 [============================>.] - ETA: 0s - loss: 0.0293 - acc: 0.9910\n",
"Reached 99% accuracy so cancelling training!\n",
"60000/60000 [==============================] - 7s 122us/sample - loss: 0.0294 - acc: 0.9910\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7fdcf2730c50>"
]
},
"metadata": {
"tags": []
},
"execution_count": 11
}
]
},
{
"metadata": {
"id": "uFDxwXmHPalJ",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**We achieved more than 99% accuracy in 7 epochs. That's good! The accuracy tells us that our neural network is about 99% accurate in classifying the training data, i.e. it figured out a pattern match between the image and the labels that worked 99% of the time.**\n",
"\n",
"**Let's check how shall our model perform on unseen data i.e. test dataset.**"
]
},
{
"metadata": {
"id": "Bv0Om4sfSvaO",
"colab_type": "code",
"outputId": "5165c20f-6aa8-4370-c8b1-3efe29e534b0",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 51
}
},
"cell_type": "code",
"source": [
"model.evaluate(x_test, y_test)"
],
"execution_count": 12,
"outputs": [
{
"output_type": "stream",
"text": [
"10000/10000 [==============================] - 1s 69us/sample - loss: 0.0736 - acc: 0.9779\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[0.07360582140479237, 0.9779]"
]
},
"metadata": {
"tags": []
},
"execution_count": 12
}
]
},
{
"metadata": {
"id": "sfjEPbNBUbUa",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Our model is 97.79% accurate on unseen image datasets. Not bad!**"
]
},
{
"metadata": {
"id": "jB0BXIqXTDhO",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"### Before ending this section, let's view architecture of our model"
]
},
{
"metadata": {
"id": "LpLlKpkCy0at",
"colab_type": "code",
"outputId": "b8da22db-739e-44cb-a58b-b8863f519c98",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 238
}
},
"cell_type": "code",
"source": [
"model.summary()"
],
"execution_count": 13,
"outputs": [
{
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"flatten (Flatten) (None, 784) 0 \n",
"_________________________________________________________________\n",
"dense (Dense) (None, 128) 100480 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 10) 1290 \n",
"=================================================================\n",
"Total params: 101,770\n",
"Trainable params: 101,770\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "s3mk--_aTOPp",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Note the number of parameters, 101k for using just two layers. That's huge. Think about adding a few more layers or increasing neurons per layers, then it would easily contain more than a million trainable parameters. That reflects it's not a good approach for sustaining larger and more complex image datasets. \n",
"In our next approach we shall build a model with nearly same number of trainable parameters.**"
]
},
{
"metadata": {
"id": "f13_ERkydVXV",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## 2. Model building using Convolution Layers only"
]
},
{
"metadata": {
"id": "EScdn3U9B0Lu",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# calling load_data on this object will give you two sets of two lists, \n",
"# these are training and testing datasets which contains images as x and their labels as y\n",
"(x_train, y_train),(x_test, y_test) = mnist.load_data()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "OG_XoECmdPRH",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# Reshape the training dataset to 4D so that last digit describes channels which is 1 for greyscale images\n",
"x_train = x_train.reshape(x_train.shape[0], 28, 28,1)\n",
"x_test = x_test.reshape(x_test.shape[0], 28, 28,1)"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "leu7KzrEzQmS",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# No we shall convert the pixel values from int to float values \n",
"# and normalize every image in the dataset before training a neural network\n",
"\n",
"x_train = x_train.astype('float32')\n",
"x_test = x_test.astype('float32')\n",
"x_train = x_train/255.0\n",
"x_test = x_test/255.0"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "KsD2HnxUgSsy",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**In this section we shall one-hot encode our labels**"
]
},
{
"metadata": {
"id": "LLz799xdgKyd",
"colab_type": "code",
"outputId": "07ca42d4-9cea-462d-fea3-2af799449a7e",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"cell_type": "code",
"source": [
"#Before one-hot encoding\n",
"y_train[0]"
],
"execution_count": 17,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"5"
]
},
"metadata": {
"tags": []
},
"execution_count": 17
}
]
},
{
"metadata": {
"id": "cLQH-7ydgdGu",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# Convert 1-dimensional class arrays to 10-dimensional class matrices\n",
"\n",
"y_train = tf.keras.utils.to_categorical(y_train, 10, dtype='float32')\n",
"y_test = tf.keras.utils.to_categorical(y_test, 10, dtype='float32')"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "Jj_0u6YogpAH",
"colab_type": "code",
"outputId": "692db172-3412-46d0-fbbe-de6fc835d314",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"cell_type": "code",
"source": [
"# After one-hot encoding\n",
"y_train[0]"
],
"execution_count": 19,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], dtype=float32)"
]
},
"metadata": {
"tags": []
},
"execution_count": 19
}
]
},
{
"metadata": {
"id": "jpwkM57riDlN",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**In contrast to earlier section here we shall feed the data as 28x28 images and not flatten them**"
]
},
{
"metadata": {
"id": "3Ly2pNX9hpHw",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"# Define the model\n",
"model = tf.keras.models.Sequential([tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n",
" tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n",
" tf.keras.layers.MaxPool2D((2,2)),\n",
" tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n",
" tf.keras.layers.MaxPool2D((2,2)),\n",
" tf.keras.layers.Conv2D(64, (3,3), activation='relu'),\n",
" tf.keras.layers.Conv2D(10, (3,3)),\n",
" tf.keras.layers.Flatten(),\n",
" tf.keras.layers.Activation('softmax')\n",
" ])"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "83rNVHZPkXEO",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**For understanding what convolution does, go through this Andrew Ng [tutorial](https://youtu.be/bXJx7y51cl0) **"
]
},
{
"metadata": {
"id": "knp8nNnHlLaa",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Let's view the architecture of this model.**"
]
},
{
"metadata": {
"id": "HTfAKj_rkWoe",
"colab_type": "code",
"outputId": "1e5be5f1-1269-413e-9d77-b60f8feaf5a5",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 442
}
},
"cell_type": "code",
"source": [
"model.summary()"
],
"execution_count": 21,
"outputs": [
{
"output_type": "stream",
"text": [
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"conv2d (Conv2D) (None, 26, 26, 32) 320 \n",
"_________________________________________________________________\n",
"conv2d_1 (Conv2D) (None, 24, 24, 64) 18496 \n",
"_________________________________________________________________\n",
"max_pooling2d (MaxPooling2D) (None, 12, 12, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_2 (Conv2D) (None, 10, 10, 64) 36928 \n",
"_________________________________________________________________\n",
"max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_3 (Conv2D) (None, 3, 3, 64) 36928 \n",
"_________________________________________________________________\n",
"conv2d_4 (Conv2D) (None, 1, 1, 10) 5770 \n",
"_________________________________________________________________\n",
"flatten_1 (Flatten) (None, 10) 0 \n",
"_________________________________________________________________\n",
"activation (Activation) (None, 10) 0 \n",
"=================================================================\n",
"Total params: 98,442\n",
"Trainable params: 98,442\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "W8WMrCaPln8R",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Even after using 7 convolution layers, we get only 98k parameters. That's mysterious! **"
]
},
{
"metadata": {
"id": "CymP4goclnnb",
"colab_type": "code",
"outputId": "3bf218aa-472d-4d3c-ce70-c84293114c4e",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 241
}
},
"cell_type": "code",
"source": [
"#Build the model\n",
"model.compile(loss='categorical_crossentropy',\n",
" optimizer='adam',\n",
" metrics=['accuracy'])\n",
"\n",
"# we are calling the earlier callback here too\n",
"model.fit(x_train, y_train, batch_size=32, epochs=10, verbose=1, callbacks= [callbacks])"
],
"execution_count": 22,
"outputs": [
{
"output_type": "stream",
"text": [
"WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
"Instructions for updating:\n",
"Use tf.cast instead.\n",
"Epoch 1/10\n",
"60000/60000 [==============================] - 23s 376us/sample - loss: 0.1242 - acc: 0.9610\n",
"Epoch 2/10\n",
"60000/60000 [==============================] - 19s 319us/sample - loss: 0.0404 - acc: 0.9872\n",
"Epoch 3/10\n",
"59808/60000 [============================>.] - ETA: 0s - loss: 0.0286 - acc: 0.9914\n",
"Reached 99% accuracy so cancelling training!\n",
"60000/60000 [==============================] - 19s 317us/sample - loss: 0.0286 - acc: 0.9914\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<tensorflow.python.keras.callbacks.History at 0x7fdce9e47470>"
]
},
"metadata": {
"tags": []
},
"execution_count": 22
}
]
},
{
"metadata": {
"id": "gI2w3MrUmtZM",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**We got more than 99% accuracy in just 3 epochs, that also with nearly same number of parameters. That's impressive!**\n",
"\n",
"**Let's check how shall our model perform on unseen data i.e. test dataset.**"
]
},
{
"metadata": {
"id": "0bx6-RsAld73",
"colab_type": "code",
"outputId": "9411b6f4-4d31-43dd-e4a9-a6cae5479914",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 51
}
},
"cell_type": "code",
"source": [
"model.evaluate(x_test, y_test)"
],
"execution_count": 23,
"outputs": [
{
"output_type": "stream",
"text": [
"10000/10000 [==============================] - 1s 121us/sample - loss: 0.0304 - acc: 0.9911\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[0.030417644272069447, 0.9911]"
]
},
"metadata": {
"tags": []
},
"execution_count": 23
}
]
},
{
"metadata": {
"id": "jIsdNX4gm4wI",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Our model is 99.11% accurate on unseen image datasets. That's very close to training accuracy.**"
]
},
{
"metadata": {
"id": "Qt7SX1Wez02k",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"**Before Conclusion, let's Visualize the Layers of Convolution Networks**\n",
"\n",
"To get a feel for what kind of features our convolution network has learned, next thing we do is to visualize how an input gets transformed as it goes through the convolution network. We plot output of 1st convolution operation on first 5 images of training dataset for top 6 layers in the network."
]
},
{
"metadata": {
"id": "QCGPetPqz7Aq",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 844
},
"outputId": "6751866c-e013-4ee6-a023-a627ed1984b6"
},
"cell_type": "code",
"source": [
"import matplotlib.pyplot as plt\n",
"fig, ax = plt.subplots(5,6,figsize=(15,15))\n",
"\n",
"CONVOLUTION_NUMBER = 1\n",
"\n",
"from tensorflow.keras import models\n",
"layer_outputs = [layer.output for layer in model.layers]\n",
"visualization_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)\n",
"\n",
"for n_layer in range(0,6):\n",
" for n_img in range (0,5):\n",
" f = visualization_model.predict(x_train[n_img].reshape(1, 28, 28, 1))[n_layer]\n",
" ax[n_img,n_layer].imshow(f[0, : , :, CONVOLUTION_NUMBER], cmap='viridis')\n",
" ax[n_img,n_layer].grid(False)"
],
"execution_count": 24,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1080x1080 with 30 Axes>"
]
},
"metadata": {
"tags": []
}
}
]
},
{
"metadata": {
"id": "zXC4QyBlz-YU",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"We can see, the layers go from the raw pixels of the images to increasingly abstract and compact representations. The representations downstream starts highlighting what the network pays attention to, and they show fewer and fewer features being \"activated\"; most are set to zero. This is called \"sparsity.\" Representation sparsity is a key feature of deep learning.\n",
"\n",
"These representations carry increasingly less information about the original pixels of the image, but increasingly refined information about the class of the image. You might argue that being the general property of a Neural Network, but the advantage convolution layers have over dense layers is that, it learns local patterns in their input feature space, in contrast to global patterns learned by dense layers."
]
},
{
"metadata": {
"id": "rPrRyjuD3y0Y",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## Conclusion"
]
},
{
"metadata": {
"id": "74Wyjz0bD8v_",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## We can see, quite distinctly our second model, containing nearly same number of trainable parameters, trained under lower epochs achieving higher test accuracy, performs better than our first model.\n",
"## Beginners, with this you get a reason behind the wide use of CNN architecture for Image Recognition. It's indeed a powerful approach."
]
},
{
"metadata": {
"id": "8Kda-nk9TtyB",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"## If you loved this article and want to dive more into this, then here is a small challenge for you. Get more than 99.25% test accuracy using convolution layers approach with NN models having less than 25k parameters. \n",
"## Now go, search everywhere, get this done ."
]
},
{
"metadata": {
"id": "0uXbyTESVJ_n",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment