{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "kernelspec": { "name": "python3", "display_name": "Python 3" }, "colab": { "name": "MLP_from_scratch_in_TF.ipynb", "provenance": [], "collapsed_sections": [] }, "accelerator": "GPU" }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "sMslI4wgPKYC" }, "source": [ "# Multi Layer Perceptron from Scratch in TensorFlow" ] }, { "cell_type": "code", "metadata": { "id": "vlFgPQQcPKYD" }, "source": [ "import tensorflow as tf\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "%matplotlib inline" ], "execution_count": 1, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "_fjfb6DqPKYE" }, "source": [ "## Creating MLP class" ] }, { "cell_type": "code", "metadata": { "id": "cG0syZGkPKYE" }, "source": [ "class MLP:\n", " def __init__(self, layers):\n", " self.layers = layers\n", " self.L = len(layers)\n", " self.num_features = layers[0]\n", " self.num_classes = layers[-1]\n", " \n", " self.W = {}\n", " self.b = {}\n", " \n", " self.dW = {}\n", " self.db = {}\n", " \n", " self.setup()\n", " \n", " def setup(self):\n", " for i in range(1, self.L):\n", " self.W[i] = tf.Variable(tf.random.normal(shape=(self.layers[i], self.layers[i-1])))\n", " self.b[i] = tf.Variable(tf.random.normal(shape=(self.layers[i], 1)))\n", " \n", " \n", " def forward_pass(self, A):\n", " A = tf.convert_to_tensor(A, dtype=tf.float32)\n", " for i in range(1, self.L):\n", " Z = tf.matmul(A, tf.transpose(self.W[i])) + tf.transpose(self.b[i])\n", " if i != self.L-1:\n", " A = tf.nn.relu(Z)\n", " else:\n", " A = Z\n", " return A\n", " \n", " \n", " def compute_loss(self, A, Y):\n", " return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(Y, A))\n", " \n", " \n", " def update_params(self, lr):\n", " for i in range(1, self.L):\n", " self.W[i].assign_sub(lr * self.dW[i])\n", " self.b[i].assign_sub(lr * self.db[i])\n", " \n", " def predict(self, X):\n", " A = self.forward_pass(X)\n", " return tf.argmax(tf.nn.softmax(A), axis=1)\n", " \n", " def summary(self):\n", " num_params = 0\n", " for i in range(1, self.L):\n", " num_params += self.W[i].shape[0] * self.W[i].shape[1]\n", " num_params += self.b[i].shape[0]\n", " print('Input Features:\\t', self.num_features)\n", " print('Number of Classes:\\t', self.num_classes)\n", " print('Hidden Layers:')\n", " print('===================')\n", " for i in range(1, self.L-1):\n", " print('Layer {}, Units {}'.format(i, self.layers[i]))\n", " print('===================')\n", " print('Number of parameters:', num_params)\n", " \n", " \n", " def train_on_batch(self, X, Y, lr):\n", " X = tf.convert_to_tensor(X, dtype=tf.float32)\n", " Y = tf.convert_to_tensor(Y, dtype=tf.float32)\n", " \n", " with tf.GradientTape(persistent=True) as tape:\n", " A = self.forward_pass(X)\n", " loss = self.compute_loss(A, Y)\n", " for key in self.W.keys():\n", " self.dW[key] = tape.gradient(loss, self.W[key])\n", " self.db[key] = tape.gradient(loss, self.b[key])\n", " del tape\n", " self.update_params(lr)\n", " \n", " return loss.numpy()\n", " \n", " \n", " def train(self, x_train, y_train, x_test, y_test, epochs, batch_size, lr): # , steps_per_epoch, \n", " history = {\n", " 'val_loss': [],\n", " 'train_loss': [],\n", " 'val_acc': [],\n", " 'train_acc': []\n", " }\n", " steps_per_epoch = int(x_train.shape[0]/batch_size)\n", "\n", " for e in range(0, epochs):\n", " epoch_train_loss = 0.\n", " print('Epoch {0}/{1}\\t['.format(e+1, epochs), end='')\n", " for i in range(0, steps_per_epoch):\n", " x_batch = x_train[i*batch_size:(i+1)*batch_size]\n", " y_batch = y_train[i*batch_size:(i+1)*batch_size]\n", " batch_loss = self.train_on_batch(x_batch, y_batch, lr)\n", " epoch_train_loss += batch_loss\n", " \n", " if i%int(steps_per_epoch/5) == 0:\n", " print(end='=')\n", " print(']', end='') \n", " history['train_loss'].append(epoch_train_loss/steps_per_epoch)\n", " \n", " val_A = self.forward_pass(x_test)\n", " history['val_loss'].append(self.compute_loss(val_A, y_test).numpy())\n", " \n", " train_preds = self.predict(x_batch)\n", " history['train_acc'].append(np.mean(np.argmax(y_batch, axis=1) == train_preds.numpy()))\n", " val_preds = self.predict(x_test)\n", " history['val_acc'].append(np.mean(np.argmax(y_test, axis=1) == val_preds.numpy()))\n", " print('\\tTrain Acc:', history['train_acc'][-1], end='\\t')\n", " print('Val Acc:', history['val_acc'][-1])\n", " return history\n", "\n", " def evaluate(self, X, Y):\n", " preds = self.predict(X)\n", " return np.mean(np.argmax(Y, axis=1) == preds.numpy())\n", " # Since we are predicting label as int and in dataset it's OneHotEncoded" ], "execution_count": 2, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "NP9kVVumPKYE" }, "source": [ "## Testing out the MLP class" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "ab2_fuGAPKYE", "outputId": "90b5b386-94c3-4153-b18d-d9db1a141c1f" }, "source": [ "# Importing Dataset\n", "\n", "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()\n", "x_train = np.reshape(x_train, (x_train.shape[0], 784))/255. # scaling, so tha value lies between (0,1)\n", "x_test = np.reshape(x_test, (x_test.shape[0], 784))/255.\n", "y_train = tf.keras.utils.to_categorical(y_train)\n", "y_test = tf.keras.utils.to_categorical(y_test)\n", "\n", "x_val = x_train[55000:]\n", "x_train = x_train[:55000]\n", "y_val = y_train[55000:]\n", "y_train = y_train[:55000]\n", "\n", "print((x_train.shape), (x_val.shape), (x_test.shape))" ], "execution_count": 3, "outputs": [ { "output_type": "stream", "text": [ "(55000, 784) (5000, 784) (10000, 784)\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 295 }, "id": "m5zrvURAPKYE", "outputId": "ff4748d9-114a-4482-cb77-973adbdb2743" }, "source": [ "plt.figure(figsize=(10, 5))\n", "\n", "for i, index in enumerate(range(10)):\n", " plt.subplot(2, 5, i+1)\n", " plt.imshow(x_train[index].reshape((28, 28)), cmap='binary')" ], "execution_count": 4, "outputs": [ { "output_type": "display_data", "data": { "image/png": "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hgR9I0aMqP//QBVxBwoAACAlBlAAAAApMYACAABIKeo1UB9++KGL//znPwd9X/3qV1385ptvBn177rmni/31S8cdd1zwud/97ncuTm5x4Pvoo4+C9iOPPOLikSNHBn2tWrXKexygOWjKjvFN3WU+uev1k08+6eLkNgaojhkzZlQ7hahNmTIlaA8bNszFDa3t7dGjR9BeuHBhvXGyfm+88YaLk//27rvvvi6+9957G0o7E7gDBQAAkBIDKAAAgJSimsJLviTUn2I7++yz834v+WLhL33pSy4+4YQTXOw/filJp5xyiouTO7b6Nm3aFG9NDCIAAApuSURBVLRHjx7t4gMPPDDoGzRokItbt26d95hIr9Bpnnnz5gXtSy+9tBzpNGuHHXaYi+fMmRP0+TuRDxgwIOjbY489Up/rnnvuCdr+2wWQDf7fubxMuPymTp3q4osuuijo85eR+C98lqSHHnrIxe3btw/6/BcBz50718X+dJ7U8FYImzdvdnG3bt2CPv/vic9+9rPKAu5AAQAApMQACgAAICUGUAAAACnV/Boof6uC66+/PugbN25c3u+dccYZLr7sssuCPn/e13/jdPKx5pdeesnFyfVKV155pYuT66OmT5/u4n//938P+vr161fvMaR/nnP29e7dO28fdvHn2xt6PPfhhx8O2suXL3dxr169Sp9YM9e9e/egfe2115b0+Mk1jqyByp7kWlCfv7Z1zZo1QV/yzw4K88tf/tLFybVG/vWXfJVLQ+644w4X+69E8l/x0pidO3e62F8XJ2Vn3ZOPO1AAAAApMYACAABIqeam8JK7el933XUu/slPfhL0tW3b1sX//d//HfSdd955Lk4+quk/dulP773wwgvB5z73uc+5+H//93+DPv/249atW4O+Z555xsUPPvhg0Ofv2upP5yUlb3m//vrreT+LXb7zne+42L+F3Zjx48e7+Gc/+1lJc0L5zZw5s9opoBG7757/nyL/sfd//OMflUgnegMHDnTx4MGDg77klF6h/C0Ili1blvdz/s7nhx56aN7Pde3atUl5VBJ3oAAAAFJiAAUAAJASAygAAICUam4NlL8eRQrXPe21115Bn7/OpX///kHfs88+6+IJEyYEff4b2T/44AMXJ7dJ8LfAb2jeuF27dkHbfz1F8lUVkydPdnFyfZTvf/7nf/L2oX6HHHJItVNo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\n", "text/plain": [ "<Figure size 720x360 with 10 Axes>" ] }, "metadata": { "tags": [], "needs_background": "light" } } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Vgc-Jg0DPKYG", "outputId": "81b2d2af-7e3b-49e7-fd5b-4cf4ad7313f1" }, "source": [ "mlp = MLP([784, 128, 128, 10])\n", "mlp.summary()" ], "execution_count": 5, "outputs": [ { "output_type": "stream", "text": [ "Input Features:\t 784\n", "Number of Classes:\t 10\n", "Hidden Layers:\n", "===================\n", "Layer 1, Units 128\n", "Layer 2, Units 128\n", "===================\n", "Number of parameters: 118282\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "TFB4cJx9PKYG", "outputId": "fe9c4e7a-5e9b-4407-9e9a-6b6f6386eebb" }, "source": [ "batch_size = 64\n", "epochs = 20\n", "lr = 3e-3\n", "\n", "history = mlp.train(x_train, y_train, x_val, y_val, epochs, batch_size, lr)" ], "execution_count": 6, "outputs": [ { "output_type": "stream", "text": [ "Epoch 1/20\t[======]\tTrain Acc: 0.765625\tVal Acc: 0.8468\n", "Epoch 2/20\t[======]\tTrain Acc: 0.796875\tVal Acc: 0.8638\n", "Epoch 3/20\t[======]\tTrain Acc: 0.8125\tVal Acc: 0.876\n", "Epoch 4/20\t[======]\tTrain Acc: 0.84375\tVal Acc: 0.8756\n", "Epoch 5/20\t[======]\tTrain Acc: 0.859375\tVal Acc: 0.8812\n", "Epoch 6/20\t[======]\tTrain Acc: 0.859375\tVal Acc: 0.8814\n", "Epoch 7/20\t[======]\tTrain Acc: 0.875\tVal Acc: 0.89\n", "Epoch 8/20\t[======]\tTrain Acc: 0.875\tVal Acc: 0.8884\n", "Epoch 9/20\t[======]\tTrain Acc: 0.875\tVal Acc: 0.8884\n", "Epoch 10/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8904\n", "Epoch 11/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8856\n", "Epoch 12/20\t[======]\tTrain Acc: 0.90625\tVal Acc: 0.8818\n", "Epoch 13/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8832\n", "Epoch 14/20\t[======]\tTrain Acc: 0.90625\tVal Acc: 0.88\n", "Epoch 15/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8834\n", "Epoch 16/20\t[======]\tTrain Acc: 0.90625\tVal Acc: 0.9002\n", "Epoch 17/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8958\n", "Epoch 18/20\t[======]\tTrain Acc: 0.890625\tVal Acc: 0.8934\n", "Epoch 19/20\t[======]\tTrain Acc: 0.90625\tVal Acc: 0.8952\n", "Epoch 20/20\t[======]\tTrain Acc: 0.921875\tVal Acc: 0.8898\n" ], "name": "stdout" } ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 283 }, "id": "eZuK-dUuPKYH", "outputId": "cb0eb998-47b5-4f84-baef-15b4fec97daa" }, "source": [ "#Plotting Training-Validation accuracies and loss.\n", "\n", "plt.figure(figsize=(12, 4))\n", "epochs = len(history['val_loss'])\n", "plt.subplot(1, 2, 1)\n", "plt.plot(range(epochs), history['val_loss'], label='Val Loss')\n", "plt.plot(range(epochs), history['train_loss'], label='Train Loss')\n", "plt.xticks(list(range(epochs)))\n", "plt.xlabel('Epochs')\n", "plt.ylabel('Loss')\n", "plt.legend()\n", "plt.subplot(1, 2, 2)\n", "plt.plot(range(epochs), history['val_acc'], label='Val Acc')\n", "plt.plot(range(epochs), history['train_acc'], label='Train Acc')\n", "plt.xticks(list(range(epochs)))\n", "plt.xlabel('Epochs')\n", "plt.ylabel('Accuracy')\n", "plt.legend()\n", "plt.show()" ], "execution_count": 7, "outputs": [ { "output_type": "display_data", "data": { "image/png": "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\n", "text/plain": [ "<Figure size 864x288 with 2 Axes>" ] }, "metadata": { "tags": [], "needs_background": "light" } } ] }, { "cell_type": "code", "metadata": { "id": "mucpLU4oPKYH" }, "source": [ "test_accuracy = mlp.evaluate(x_test, y_test)" ], "execution_count": 8, "outputs": [] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "hZWj2_deZKb7", "outputId": "df2dff06-d5ba-43c2-919a-3c250c2316c1" }, "source": [ "print('Test Accuracy : ', test_accuracy)" ], "execution_count": 9, "outputs": [ { "output_type": "stream", "text": [ "Test Accuracy : 0.8723\n" ], "name": "stdout" } ] } ] }