Skip to content

Instantly share code, notes, and snippets.

@TatheerHussain
Last active April 15, 2020 02:34
Show Gist options
  • Save TatheerHussain/9271213ce25a2b4a8b94e2fa5ba982c0 to your computer and use it in GitHub Desktop.
Save TatheerHussain/9271213ce25a2b4a8b94e2fa5ba982c0 to your computer and use it in GitHub Desktop.
NN_MNIST_Scratch_v1.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "NN_MNIST_Scratch_v1.ipynb",
"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/TatheerHussain/9271213ce25a2b4a8b94e2fa5ba982c0/nn_mnist_scratch_v1.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "elUqQBMQqDaJ",
"colab_type": "text"
},
"source": [
"Building a neural network from scratch"
]
},
{
"cell_type": "code",
"metadata": {
"id": "eKct7a0wXW7Z",
"colab_type": "code",
"colab": {}
},
"source": [
"\n",
"# Import libraries\n",
"\n",
"import numpy as np\n",
"%matplotlib inline\n",
"import matplotlib\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.datasets import fetch_openml\n",
"from sklearn.metrics import classification_report, confusion_matrix\n"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "hD6CBNcFmMo-",
"colab_type": "code",
"colab": {}
},
"source": [
"# Read and transform data\n",
"mnist = fetch_openml('mnist_784')\n",
"inputData, y = mnist[\"data\"], mnist[\"target\"]\n",
"\n",
"inputData = inputData / 255\n",
"nDigits = 10"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "qvuA14k0mI2p",
"colab_type": "code",
"colab": {}
},
"source": [
"yOneHot = np.zeros([y.shape[0],nDigits])\n",
"for i in range(y.shape[0]):\n",
" yOneHot[i,int(y[i])]=1\n",
"\n",
"y = yOneHot\n",
"\n",
"m = 60000\n",
"m_test = inputData.shape[0] - m\n",
"\n",
"y_train, y_test = y[:m,:].reshape(m,nDigits), y[m:,:].reshape(m_test,nDigits)\n",
"InputData_train, InputData_test = inputData[:m,:], inputData[m:,:]\n",
"\n",
"\n",
"np.random.seed(1002)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "uu-TdfD7mwFw",
"colab_type": "code",
"colab": {}
},
"source": [
"#y[0:2, :]"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "2XiQVeFVnPLq",
"colab_type": "code",
"colab": {}
},
"source": [
"#y[7000, :]"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "6BgFi6VIXW7f",
"colab_type": "code",
"outputId": "c19aa751-88ed-4f5b-e024-8ede857caa94",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 265
}
},
"source": [
"# Show a random input\n",
"\n",
"i = 7000\n",
"plt.imshow(InputData_train[i,:].reshape(28,28), cmap = matplotlib.cm.binary)\n",
"plt.axis(\"off\")\n",
"plt.show()\n",
"print(y_train[i,:])"
],
"execution_count": 6,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAOcAAADnCAYAAADl9EEgAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAGNUlEQVR4nO3dT4jMfxzH8ZmNtBsncZ29SCnJTWqTA7VxEgcHSSTrrFBS1mk3khycKFknuchBWxspcZFwVw6OsvKn9rD2d/r9avvtvKffzE5e+9vH4+jV5zdTv9/Tt36fZqa5sLDQAPIM/Ok3ACxNnBBKnBBKnBBKnBBqTYfd/8qF/msu9YeenBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBBKnBCq008A0oX5+flyv379etvtwoUL5dljx46V+71798qdlcOTE0KJE0KJE0KJE0KJE0KJE0KJE0K55+yD2dnZcp+YmGi7NZvN8mynvVdv3rxpu33+/Lk8u2/fvnIfHBzs6j2tVp6cEEqcEEqcEEqcEEqcEEqcEEqcEMo9Zx9s3Lix3A8ePNh2m5qaKs8ODw9385b+MTc3V+4XL15su83MzJRnL126VO5Xrlwpdxbz5IRQ4oRQ4oRQ4oRQ4oRQ4oRQrlL64MWLF+X+5MmTttvu3bvLs+fPn+/qPf3t5cuX5d7puqSyZ8+ers/yb56cEEqcEEqcEEqcEEqcEEqcEEqcEMo9Zx8cOHCg3H/9+tV2W79+fXm216+XfPr0aU/nK5s2berbP3s18uSEUOKEUOKEUOKEUOKEUOKEUOKEUO45++DHjx/lXv2M38jIyHK/nUUWFha63vfv31+e3b59e1fviaV5ckIocUIocUIocUIocUIocUIocUIo95x9UN1jNhqNRqvVarudOHFiud/OIp3eW7V3Osvy8uSEUOKEUOKEUOKEUOKEUOKEUOKEUO45/4CvX7+23V69elWePXToUE+v/fDhw3LfsGFD2+306dM9vTb/jScnhBInhBInhBInhBInhBInhGp2+KrE+nsUWdLAQP13XvXRq05fL/ns2bNyn5iYKPfJycly37FjR9vt7du35Vm6tuR/EJ6cEEqcEEqcEEqcEEqcEEqcEEqcEMpHxvrg7Nmz5X779u2224cPH8qzW7duLffZ2dly72RsbKyn8ywfT04IJU4IJU4IJU4IJU4IJU4IJU4I5Z6zDzp9pnJ4eLjt9uDBg/Lsu3fvunlL/xgaGir3LVu2tN3m5ubKs+vWrevqPbE0T04IJU4IJU4IJU4IJU4IJU4IJU4I5Xtrw0xPT5f76OhoT//8Dv++y+/UPXnyZHn25s2b5T44OFjuq5jvrYWVRJwQSpwQSpwQSpwQSpwQSpwQyuc5w3z69Kmn861Wq9yPHDlS7teuXWu73blzp6v39Ldbt26Vu8+DLubJCaHECaHECaHECaHECaHECaFcpYR59OhRT+cfP35c7p1+QnBgoP3f15OTk+XZTlctR48eLfe9e/eW+2rjyQmhxAmhxAmhxAmhxAmhxAmhxAmh3HP+z2zevLnc165dW+7j4+Ntt9+/f5dnq4+bNRqNxtWrV8vdPedinpwQSpwQSpwQSpwQSpwQSpwQSpwQyj1nmKGhoXLv9BN+P3/+7On1q3vQsbGx8uz9+/fL/fnz5928pVXLkxNCiRNCiRNCiRNCiRNCiRNCiRNCNTvcm9WXaiy76enpch8dHS33bdu2lfvMzEy5d/o8aGXnzp3l/v79+3Kfn5/v+rVXuOZSf+jJCaHECaHECaHECaHECaHECaFcpYT58uVLue/atavcP378WO6nTp0q95GRkbbb1NRUefb169fl/v3793J3lbKYJyeEEieEEieEEieEEieEEieEEieEcs+5wty4caPcz507V+6dvlqz2Vzyym1ZHD9+vNzv3r3bt9cO554TVhJxQihxQihxQihxQihxQihxQig/AbjCnDlzpty/fftW7uPj412/dqvVKvfLly+X++HDh7t+7dXIkxNCiRNCiRNCiRNCiRNCiRNCiRNC+Twn/Hk+zwkriTghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDgh1JoO+5I/TQb0nycnhBInhBInhBInhBInhBInhPoLd6ji1/S0b58AAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
},
{
"output_type": "stream",
"text": [
"[0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "52aMz8S_XW7k",
"colab_type": "code",
"colab": {}
},
"source": [
"# Define activation, loss, and their derivatives\n",
"\n",
"def sigmoid(x):\n",
" return 1 / (1 + np.exp(-x))\n",
"\n",
"def sigmoid_derivative(z):\n",
" return z * (1-z)\n",
"\n",
"def relu (x):\n",
" return np.maximum(0,x) # ReLU is very simple\n",
"\n",
"def relu_derivative(x):\n",
" return 0.5 * (np.sign(x)+1) # ReLU derivative is either zero or 1.\n",
"\n",
"def CrossEntropyLoss(y, y_hat):\n",
" L_sum = np.sum(np.multiply(y, np.log(y_hat)))\n",
" m = y.shape[1]\n",
" L = -(1/m) * L_sum\n",
"\n",
" return L\n",
"\n",
"def softmax(y):\n",
" return np.exp(y) / np.sum(np.exp(y), axis=0)\n",
"\n",
"def CE_Softmax_Derivative(output, ideal_output):\n",
" return output - ideal_output"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "wI8vc500XW7o",
"colab_type": "code",
"colab": {}
},
"source": [
"inputDim = InputData_train.shape[1]\n",
"nHidden = 64\n",
"learning_rate = 1\n",
"weight_decay = 0.001\n",
"\n",
"W1 = 0.01*np.random.randn(nHidden, inputDim)\n",
"b1 = np.zeros((nHidden, 1))\n",
"W2 = 0.01*np.random.randn(nDigits, nHidden)\n",
"b2 = np.zeros((nDigits, 1))\n",
"\n",
"inputData = InputData_train\n",
"y = y_train"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "mI4j41M6XW7r",
"colab_type": "code",
"outputId": "6b0fbece-4e8b-4c0b-bff9-5291b802cf39",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 466
}
},
"source": [
"nEpochs = 100\n",
"costPlot = np.zeros(nEpochs)\n",
"\n",
"for i in range(nEpochs):\n",
"\n",
" Z1 = np.matmul(W1,inputData.T) + b1\n",
" A1 = relu(Z1)\n",
" Z2 = np.matmul(W2,A1) + b2\n",
" A2 = softmax(Z2)\n",
"\n",
" cost = CrossEntropyLoss(y.T, A2)\n",
" costPlot[i] = cost\n",
"\n",
" dZ2 = CE_Softmax_Derivative(A2,y.T)\n",
" dW2 = (1./m) * np.matmul(dZ2, A1.T)\n",
" db2 = (1./m) * np.sum(dZ2, axis=1, keepdims=True)\n",
"\n",
" dA1 = np.matmul(W2.T, dZ2)\n",
" dZ1 = dA1 * relu_derivative(Z1)\n",
" dW1 = (1./m) * np.matmul(dZ1, inputData)\n",
" db1 = (1./m) * np.sum(dZ1, axis=1, keepdims=True)\n",
"\n",
" W2 -= learning_rate * dW2 + weight_decay * W2\n",
" b2 -= learning_rate * db2\n",
" W1 -= learning_rate * dW1 + weight_decay * W1\n",
" b1 -= learning_rate * db1\n",
" \n",
" if (i % 10 == 0):\n",
" print(\"Epoch\", i, \"cost: \", cost)\n",
" \n",
"plt.plot(costPlot)\n",
"plt.xlabel('Epochs')\n",
"plt.ylabel('Training Loss')\n",
"plt.show"
],
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"text": [
"Epoch 0 cost: 2.3025926683067466\n",
"Epoch 10 cost: 1.3575995606291273\n",
"Epoch 20 cost: 1.5435466738823724\n",
"Epoch 30 cost: 1.0957404033897622\n",
"Epoch 40 cost: 0.9177537929310634\n",
"Epoch 50 cost: 0.5149939683116712\n",
"Epoch 60 cost: 0.6243709546604148\n",
"Epoch 70 cost: 0.4456593950527855\n",
"Epoch 80 cost: 0.34769817492745114\n",
"Epoch 90 cost: 0.3251370927925338\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<function matplotlib.pyplot.show>"
]
},
"metadata": {
"tags": []
},
"execution_count": 9
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "NtMx3OmkXW7v",
"colab_type": "code",
"outputId": "414c7e84-02d0-4396-aca6-eeb7a5ed5c2a",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 476
}
},
"source": [
"Z1 = np.matmul(W1, InputData_test.T) + b1\n",
"A1 = relu(Z1)\n",
"Z2 = np.matmul(W2, A1) + b2\n",
"\n",
"predictions = np.argmax(Z2, axis=0)\n",
"labels = np.argmax(y_test.T, axis=0)\n",
"\n",
"print(confusion_matrix(predictions, labels))\n",
"print(classification_report(predictions, labels))"
],
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 957 0 8 3 2 10 12 4 4 14]\n",
" [ 0 1097 4 0 1 2 2 9 4 3]\n",
" [ 1 1 926 26 6 7 4 30 9 5]\n",
" [ 1 4 14 919 1 67 1 4 14 13]\n",
" [ 0 0 13 0 893 7 13 7 6 27]\n",
" [ 0 0 0 18 0 677 14 0 6 2]\n",
" [ 8 4 14 1 14 15 901 0 9 1]\n",
" [ 3 2 13 10 1 8 0 936 9 15]\n",
" [ 9 27 38 28 13 93 11 5 908 24]\n",
" [ 1 0 2 5 51 6 0 33 5 905]]\n",
" precision recall f1-score support\n",
"\n",
" 0 0.98 0.94 0.96 1014\n",
" 1 0.97 0.98 0.97 1122\n",
" 2 0.90 0.91 0.90 1015\n",
" 3 0.91 0.89 0.90 1038\n",
" 4 0.91 0.92 0.92 966\n",
" 5 0.76 0.94 0.84 717\n",
" 6 0.94 0.93 0.94 967\n",
" 7 0.91 0.94 0.92 997\n",
" 8 0.93 0.79 0.85 1156\n",
" 9 0.90 0.90 0.90 1008\n",
"\n",
" accuracy 0.91 10000\n",
" macro avg 0.91 0.91 0.91 10000\n",
"weighted avg 0.92 0.91 0.91 10000\n",
"\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "mMAuqPf-XW7z",
"colab_type": "code",
"colab": {}
},
"source": [
""
],
"execution_count": 0,
"outputs": []
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment