diff --git a/cnn/CNN_application.ipynb b/cnn/CNN_application.ipynb new file mode 100644 index 0000000..583aa40 --- /dev/null +++ b/cnn/CNN_application.ipynb @@ -0,0 +1,983 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Convolutional Neural Networks: Application\n", + "\n", + "Welcome to Course 4's second assignment! In this notebook, you will:\n", + "\n", + "- Implement helper functions that you will use when implementing a TensorFlow model\n", + "- Implement a fully functioning ConvNet using TensorFlow \n", + "\n", + "**After this assignment you will be able to:**\n", + "\n", + "- Build and train a ConvNet in TensorFlow for a classification problem \n", + "\n", + "We assume here that you are already familiar with TensorFlow. If you are not, please refer the *TensorFlow Tutorial* of the third week of Course 2 (\"*Improving deep neural networks*\")." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.0 - TensorFlow model\n", + "\n", + "In the previous assignment, you built helper functions using numpy to understand the mechanics behind convolutional neural networks. Most practical applications of deep learning today are built using programming frameworks, which have many built-in functions you can simply call. \n", + "\n", + "As usual, we will start by loading in the packages. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "import numpy as np\n", + "import h5py\n", + "import matplotlib.pyplot as plt\n", + "import scipy\n", + "from PIL import Image\n", + "from scipy import ndimage\n", + "import tensorflow as tf\n", + "from tensorflow.python.framework import ops\n", + "from cnn_utils import *\n", + "\n", + "%matplotlib inline\n", + "np.random.seed(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the next cell to load the \"SIGNS\" dataset you are going to use." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Loading the data (signs)\n", + "X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a reminder, the SIGNS dataset is a collection of 6 signs representing numbers from 0 to 5.\n", + "\n", + "\n", + "\n", + "The next cell will show you an example of a labelled image in the dataset. Feel free to change the value of `index` below and re-run to see different examples. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "y = 2\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Example of a picture\n", + "index = 6\n", + "plt.imshow(X_train_orig[index])\n", + "print (\"y = \" + str(np.squeeze(Y_train_orig[:, index])))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In Course 2, you had built a fully-connected network for this dataset. But since this is an image dataset, it is more natural to apply a ConvNet to it.\n", + "\n", + "To get started, let's examine the shapes of your data. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "number of training examples = 1080\n", + "number of test examples = 120\n", + "X_train shape: (1080, 64, 64, 3)\n", + "Y_train shape: (1080, 6)\n", + "X_test shape: (120, 64, 64, 3)\n", + "Y_test shape: (120, 6)\n" + ] + } + ], + "source": [ + "X_train = X_train_orig/255.\n", + "X_test = X_test_orig/255.\n", + "Y_train = convert_to_one_hot(Y_train_orig, 6).T\n", + "Y_test = convert_to_one_hot(Y_test_orig, 6).T\n", + "print (\"number of training examples = \" + str(X_train.shape[0]))\n", + "print (\"number of test examples = \" + str(X_test.shape[0]))\n", + "print (\"X_train shape: \" + str(X_train.shape))\n", + "print (\"Y_train shape: \" + str(Y_train.shape))\n", + "print (\"X_test shape: \" + str(X_test.shape))\n", + "print (\"Y_test shape: \" + str(Y_test.shape))\n", + "conv_layers = {}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### 1.1 - Create placeholders\n", + "\n", + "TensorFlow requires that you create placeholders for the input data that will be fed into the model when running the session.\n", + "\n", + "**Exercise**: Implement the function below to create placeholders for the input image X and the output Y. You should not define the number of training examples for the moment. To do so, you could use \"None\" as the batch size, it will give you the flexibility to choose it later. Hence X should be of dimension **[None, n_H0, n_W0, n_C0]** and Y should be of dimension **[None, n_y]**. [Hint](https://www.tensorflow.org/api_docs/python/tf/placeholder)." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: create_placeholders\n", + "\n", + "def create_placeholders(n_H0, n_W0, n_C0, n_y):\n", + " \"\"\"\n", + " Creates the placeholders for the tensorflow session.\n", + " \n", + " Arguments:\n", + " n_H0 -- scalar, height of an input image\n", + " n_W0 -- scalar, width of an input image\n", + " n_C0 -- scalar, number of channels of the input\n", + " n_y -- scalar, number of classes\n", + " \n", + " Returns:\n", + " X -- placeholder for the data input, of shape [None, n_H0, n_W0, n_C0] and dtype \"float\"\n", + " Y -- placeholder for the input labels, of shape [None, n_y] and dtype \"float\"\n", + " \"\"\"\n", + "\n", + " ### START CODE HERE ### (≈2 lines)\n", + " X = tf.placeholder(dtype=tf.float32, shape=[None, n_H0, n_W0, n_C0], )\n", + " \n", + " Y = tf.placeholder(dtype=tf.float32, shape=[None, n_y])\n", + " \n", + " ### END CODE HERE ###\n", + " \n", + " return X, Y" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X = Tensor(\"Placeholder:0\", shape=(?, 64, 64, 3), dtype=float32)\n", + "Y = Tensor(\"Placeholder_1:0\", shape=(?, 6), dtype=float32)\n" + ] + } + ], + "source": [ + "X, Y = create_placeholders(64, 64, 3, 6)\n", + "print (\"X = \" + str(X))\n", + "print (\"Y = \" + str(Y))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + " X = Tensor(\"Placeholder:0\", shape=(?, 64, 64, 3), dtype=float32)\n", + "\n", + "
\n", + " Y = Tensor(\"Placeholder_1:0\", shape=(?, 6), dtype=float32)\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 - Initialize parameters\n", + "\n", + "You will initialize weights/filters $W1$ and $W2$ using `tf.contrib.layers.xavier_initializer(seed = 0)`. You don't need to worry about bias variables as you will soon see that TensorFlow functions take care of the bias. Note also that you will only initialize the weights/filters for the conv2d functions. TensorFlow initializes the layers for the fully connected part automatically. We will talk more about that later in this assignment.\n", + "\n", + "**Exercise:** Implement initialize_parameters(). The dimensions for each group of filters are provided below. Reminder - to initialize a parameter $W$ of shape [1,2,3,4] in Tensorflow, use:\n", + "```python\n", + "W = tf.get_variable(\"W\", [1,2,3,4], initializer = ...)\n", + "```\n", + "[More Info](https://www.tensorflow.org/api_docs/python/tf/get_variable)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: initialize_parameters\n", + "# W -- Weights, array of shape (f, f, n_C_prev, n_C)\n", + "def initialize_parameters():\n", + " \"\"\"\n", + " Initializes weight parameters to build a neural network with tensorflow. The shapes are:\n", + " W1 : [4, 4, 3, 8]\n", + " W2 : [2, 2, 8, 16]\n", + " Returns:\n", + " parameters -- a dictionary of tensors containing W1, W2\n", + " \"\"\"\n", + " \n", + " tf.set_random_seed(1) # so that your \"random\" numbers match ours\n", + " \n", + " ### START CODE HERE ### (approx. 2 lines of code)\n", + " W1 = tf.get_variable('W1',[4,4,3,8], initializer=tf.contrib.layers.xavier_initializer(seed=0))\n", + " W2 = tf.get_variable('W2',[2,2,8,16], initializer=tf.contrib.layers.xavier_initializer(seed=0))\n", + " ### END CODE HERE ###\n", + "\n", + " parameters = {\"W1\": W1,\n", + " \"W2\": W2}\n", + " \n", + " return parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "W0525 12:36:15.099149 7976 lazy_loader.py:50] \n", + "The TensorFlow contrib module will not be included in TensorFlow 2.0.\n", + "For more information, please see:\n", + " * https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md\n", + " * https://github.com/tensorflow/addons\n", + " * https://github.com/tensorflow/io (for I/O related ops)\n", + "If you depend on functionality not listed there, please file an issue.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "W1 = [ 0.00131723 0.1417614 -0.04434952 0.09197326 0.14984085 -0.03514394\n", + " -0.06847463 0.05245192]\n", + "W2 = [-0.08566415 0.17750949 0.11974221 0.16773748 -0.0830943 -0.08058\n", + " -0.00577033 -0.14643836 0.24162132 -0.05857408 -0.19055021 0.1345228\n", + " -0.22779644 -0.1601823 -0.16117483 -0.10286498]\n" + ] + } + ], + "source": [ + "tf.reset_default_graph()\n", + "with tf.Session() as sess_test:\n", + " parameters = initialize_parameters()\n", + " init = tf.global_variables_initializer()\n", + " sess_test.run(init)\n", + " print(\"W1 = \" + str(parameters[\"W1\"].eval()[1,1,1]))\n", + " print(\"W2 = \" + str(parameters[\"W2\"].eval()[1,1,1]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "** Expected Output:**\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " W1 = \n", + " \n", + "[ 0.00131723 0.14176141 -0.04434952 0.09197326 0.14984085 -0.03514394
\n", + " -0.06847463 0.05245192]\n", + "
\n", + " W2 = \n", + " \n", + "[-0.08566415 0.17750949 0.11974221 0.16773748 -0.0830943 -0.08058
\n", + " -0.00577033 -0.14643836 0.24162132 -0.05857408 -0.19055021 0.1345228
\n", + " -0.22779644 -0.1601823 -0.16117483 -0.10286498]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 - Forward propagation\n", + "\n", + "In TensorFlow, there are built-in functions that carry out the convolution steps for you.\n", + "\n", + "- **tf.nn.conv2d(X,W1, strides = [1,s,s,1], padding = 'SAME'):** given an input $X$ and a group of filters $W1$, this function convolves $W1$'s filters on X. The third input ([1,f,f,1]) represents the strides for each dimension of the input (m, n_H_prev, n_W_prev, n_C_prev). You can read the full documentation [here](https://www.tensorflow.org/api_docs/python/tf/nn/conv2d)\n", + "\n", + "- **tf.nn.max_pool(A, ksize = [1,f,f,1], strides = [1,s,s,1], padding = 'SAME'):** given an input A, this function uses a window of size (f, f) and strides of size (s, s) to carry out max pooling over each window. You can read the full documentation [here](https://www.tensorflow.org/api_docs/python/tf/nn/max_pool)\n", + "\n", + "- **tf.nn.relu(Z1):** computes the elementwise ReLU of Z1 (which can be any shape). You can read the full documentation [here.](https://www.tensorflow.org/api_docs/python/tf/nn/relu)\n", + "\n", + "- **tf.contrib.layers.flatten(P)**: given an input P, this function flattens each example into a 1D vector it while maintaining the batch-size. It returns a flattened tensor with shape [batch_size, k]. You can read the full documentation [here.](https://www.tensorflow.org/api_docs/python/tf/contrib/layers/flatten)\n", + "\n", + "- **tf.contrib.layers.fully_connected(F, num_outputs):** given a the flattened input F, it returns the output computed using a fully connected layer. You can read the full documentation [here.](https://www.tensorflow.org/api_docs/python/tf/contrib/layers/fully_connected)\n", + "\n", + "In the last function above (`tf.contrib.layers.fully_connected`), the fully connected layer automatically initializes weights in the graph and keeps on training them as you train the model. Hence, you did not need to initialize those weights when initializing the parameters. \n", + "\n", + "\n", + "**Exercise**: \n", + "\n", + "Implement the `forward_propagation` function below to build the following model: `CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED`. You should use the functions above. \n", + "\n", + "In detail, we will use the following parameters for all the steps:\n", + " - Conv2D: stride 1, padding is \"SAME\"\n", + " - ReLU\n", + " - Max pool: Use an 8 by 8 filter size and an 8 by 8 stride, padding is \"SAME\"\n", + " - Conv2D: stride 1, padding is \"SAME\"\n", + " - ReLU\n", + " - Max pool: Use a 4 by 4 filter size and a 4 by 4 stride, padding is \"SAME\"\n", + " - Flatten the previous output.\n", + " - FULLYCONNECTED (FC) layer: Apply a fully connected layer without an non-linear activation function. Do not call the softmax here. This will result in 6 neurons in the output layer, which then get passed later to a softmax. In TensorFlow, the softmax and cost function are lumped together into a single function, which you'll call in a different function when computing the cost. " + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: forward_propagation\n", + "\n", + "def forward_propagation(X, parameters, dropout=False):\n", + " \"\"\"\n", + " Implements the forward propagation for the model:\n", + " CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED\n", + " \n", + " Arguments:\n", + " X -- input dataset placeholder, of shape (input size, number of examples)\n", + " parameters -- python dictionary containing your parameters \"W1\", \"W2\"\n", + " the shapes are given in initialize_parameters\n", + "\n", + " Returns:\n", + " Z3 -- the output of the last LINEAR unit\n", + " \"\"\"\n", + " \n", + " # Retrieve the parameters from the dictionary \"parameters\" \n", + " W1 = parameters['W1']\n", + " W2 = parameters['W2']\n", + " \n", + " ### START CODE HERE ###\n", + " # CONV2D: stride of 1, padding 'SAME'\n", + " Z1 = tf.nn.conv2d(X, W1, strides=[1,1,1,1], padding='SAME' )\n", + " # RELU\n", + " A1 = tf.nn.relu(Z1)\n", + " # MAXPOOL: window 8x8, sride 8, padding 'SAME'\n", + " P1 = tf.nn.max_pool(A1,ksize=[1,8,8,1] ,strides=[1,8,8,1], padding='SAME' )\n", + " # CONV2D: filters W2, stride 1, padding 'SAME'\n", + " Z2 = tf.nn.conv2d(P1, W2, strides=[1,1,1,1], padding='SAME')\n", + " # RELU\n", + " A2 = tf.nn.relu(Z2)\n", + " # MAXPOOL: window 4x4, stride 4, padding 'SAME'\n", + " P2 = tf.nn.max_pool(A2,ksize=[1,4,4,1], strides=[1,4,4,1], padding='SAME')\n", + " # FLATTEN\n", + " P2 = tf.contrib.layers.flatten(P2)\n", + " \n", + " # FULLY-CONNECTED without non-linear activation function (not not call softmax).\n", + " # 6 neurons in output layer. Hint: one of the arguments should be \"activation_fn=None\" \n", + " if dropout:\n", + " P2=tf.contrib.layers.fully_connected(P2,90, activation_fn=tf.nn.relu)\n", + " P2=tf.nn.dropout(P2, rate=0.2)\n", + " Z3 = tf.contrib.layers.fully_connected(P2, 6, activation_fn=None)\n", + " ### END CODE HERE ###\n", + "\n", + " return Z3" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "W0525 13:07:36.688151 7976 deprecation.py:323] From E:\\Anaconda\\lib\\site-packages\\tensorflow\\contrib\\layers\\python\\layers\\layers.py:1634: flatten (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use keras.layers.flatten instead.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Z3 = [[ 1.4416982 -0.24909636 5.450499 -0.26189643 -0.20669901 1.3654672 ]\n", + " [ 1.4070845 -0.02573219 5.08928 -0.48669913 -0.40940714 1.2624855 ]]\n" + ] + } + ], + "source": [ + "tf.reset_default_graph()\n", + "\n", + "with tf.Session() as sess:\n", + " np.random.seed(1)\n", + " X, Y = create_placeholders(64, 64, 3, 6)\n", + " parameters = initialize_parameters()\n", + " Z3 = forward_propagation(X, parameters)\n", + " init = tf.global_variables_initializer()\n", + " sess.run(init)\n", + " a = sess.run(Z3, {X: np.random.randn(2,64,64,3), Y: np.random.randn(2,6)})\n", + " print(\"Z3 = \" + str(a))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + "
\n", + " Z3 =\n", + " \n", + " [[-0.44670227 -1.57208765 -1.53049231 -2.31013036 -1.29104376 0.46852064]
\n", + " [-0.17601591 -1.57972014 -1.4737016 -2.61672091 -1.00810647 0.5747785 ]]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.3 - Compute cost\n", + "\n", + "Implement the compute cost function below. You might find these two functions helpful: \n", + "\n", + "- **tf.nn.softmax_cross_entropy_with_logits(logits = Z3, labels = Y):** computes the softmax entropy loss. This function both computes the softmax activation function as well as the resulting loss. You can check the full documentation [here.](https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits)\n", + "- **tf.reduce_mean:** computes the mean of elements across dimensions of a tensor. Use this to sum the losses over all the examples to get the overall cost. You can check the full documentation [here.](https://www.tensorflow.org/api_docs/python/tf/reduce_mean)\n", + "\n", + "** Exercise**: Compute the cost below using the function above." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: compute_cost \n", + "\n", + "def compute_cost(Z3, Y):\n", + " \"\"\"\n", + " Computes the cost\n", + " \n", + " Arguments:\n", + " Z3 -- output of forward propagation (output of the last LINEAR unit), of shape (6, number of examples)\n", + " Y -- \"true\" labels vector placeholder, same shape as Z3\n", + " \n", + " Returns:\n", + " cost - Tensor of the cost function\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ### (1 line of code)\n", + " cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y) )\n", + " ### END CODE HERE ###\n", + " \n", + " return cost" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "W0525 13:11:38.626000 7976 deprecation.py:323] From :16: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "\n", + "Future major versions of TensorFlow will allow gradients to flow\n", + "into the labels input on backprop by default.\n", + "\n", + "See `tf.nn.softmax_cross_entropy_with_logits_v2`.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cost = 4.6648703\n" + ] + } + ], + "source": [ + "tf.reset_default_graph()\n", + "\n", + "with tf.Session() as sess:\n", + " np.random.seed(1)\n", + " X, Y = create_placeholders(64, 64, 3, 6)\n", + " parameters = initialize_parameters()\n", + " Z3 = forward_propagation(X, parameters)\n", + " cost = compute_cost(Z3, Y)\n", + " init = tf.global_variables_initializer()\n", + " sess.run(init)\n", + " a = sess.run(cost, {X: np.random.randn(4,64,64,3), Y: np.random.randn(4,6)})\n", + " print(\"cost = \" + str(a))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**: \n", + "\n", + "\n", + " \n", + " \n", + "
\n", + " cost =\n", + " \n", + " 2.91034\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.4 Model \n", + "\n", + "Finally you will merge the helper functions you implemented above to build a model. You will train it on the SIGNS dataset. \n", + "\n", + "You have implemented `random_mini_batches()` in the Optimization programming assignment of course 2. Remember that this function returns a list of mini-batches. \n", + "\n", + "**Exercise**: Complete the function below. \n", + "\n", + "The model below should:\n", + "\n", + "- create placeholders\n", + "- initialize parameters\n", + "- forward propagate\n", + "- compute the cost\n", + "- create an optimizer\n", + "\n", + "Finally you will create a session and run a for loop for num_epochs, get the mini-batches, and then for each mini-batch you will optimize the function. [Hint for initializing the variables](https://www.tensorflow.org/api_docs/python/tf/global_variables_initializer)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: model\n", + "\n", + "def model(X_train, Y_train, X_test, Y_test, learning_rate = 0.009,\n", + " num_epochs = 65, minibatch_size = 64, print_cost = True, dropout=False):\n", + " \"\"\"\n", + " Implements a three-layer ConvNet in Tensorflow:\n", + " CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> FULLYCONNECTED\n", + " \n", + " Arguments:\n", + " X_train -- training set, of shape (None, 64, 64, 3)\n", + " Y_train -- test set, of shape (None, n_y = 6)\n", + " X_test -- training set, of shape (None, 64, 64, 3)\n", + " Y_test -- test set, of shape (None, n_y = 6)\n", + " learning_rate -- learning rate of the optimization\n", + " num_epochs -- number of epochs of the optimization loop\n", + " minibatch_size -- size of a minibatch\n", + " print_cost -- True to print the cost every 100 epochs\n", + " \n", + " Returns:\n", + " train_accuracy -- real number, accuracy on the train set (X_train)\n", + " test_accuracy -- real number, testing accuracy on the test set (X_test)\n", + " parameters -- parameters learnt by the model. They can then be used to predict.\n", + " \"\"\"\n", + " \n", + " ops.reset_default_graph() # to be able to rerun the model without overwriting tf variables\n", + " tf.set_random_seed(1) # to keep results consistent (tensorflow seed)\n", + " seed = 3 # to keep results consistent (numpy seed)\n", + " (m, n_H0, n_W0, n_C0) = X_train.shape \n", + " n_y = Y_train.shape[1] \n", + " costs = [] # To keep track of the cost\n", + " \n", + " # Create Placeholders of the correct shape\n", + " ### START CODE HERE ### (1 line)\n", + " X,Y= create_placeholders(n_H0, n_W0, n_C0, n_y)\n", + " ### END CODE HERE ###\n", + "\n", + " # Initialize parameters\n", + " ### START CODE HERE ### (1 line)\n", + " parameters = initialize_parameters()\n", + " ### END CODE HERE ###\n", + " \n", + " # Forward propagation: Build the forward propagation in the tensorflow graph\n", + " ### START CODE HERE ### (1 line)\n", + " Z3 = forward_propagation(X, parameters, dropout=dropout)\n", + " ### END CODE HERE ###\n", + " \n", + " # Cost function: Add cost function to tensorflow graph\n", + " ### START CODE HERE ### (1 line)\n", + " cost = compute_cost(Z3, Y)\n", + " ### END CODE HERE ###\n", + " \n", + " # Backpropagation: Define the tensorflow optimizer. Use an AdamOptimizer that minimizes the cost.\n", + " ### START CODE HERE ### (1 line)\n", + " optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)\n", + " ### END CODE HERE ###\n", + " \n", + " # Initialize all the variables globally\n", + " init = tf.global_variables_initializer()\n", + " \n", + " # Start the session to compute the tensorflow graph\n", + " with tf.Session() as sess:\n", + " \n", + " # Run the initialization\n", + " sess.run(init)\n", + " \n", + " # Do the training loop\n", + " for epoch in range(num_epochs):\n", + "\n", + " minibatch_cost = 0.\n", + " num_minibatches = int(m / minibatch_size) # number of minibatches of size minibatch_size in the train set\n", + " seed = seed + 1\n", + " minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)\n", + "\n", + " for minibatch in minibatches:\n", + "\n", + " # Select a minibatch\n", + " (minibatch_X, minibatch_Y) = minibatch\n", + " # IMPORTANT: The line that runs the graph on a minibatch.\n", + " # Run the session to execute the optimizer and the cost, the feedict should contain a minibatch for (X,Y).\n", + " ### START CODE HERE ### (1 line)\n", + " _ , temp_cost = sess.run([optimizer, cost], {X:X_train, Y:Y_train})\n", + " ### END CODE HERE ###\n", + " \n", + " minibatch_cost += temp_cost / num_minibatches\n", + " \n", + "\n", + " # Print the cost every epoch\n", + " if print_cost == True and epoch % 5 == 0:\n", + " print (\"Cost after epoch %i: %f\" % (epoch, minibatch_cost))\n", + " if print_cost == True and epoch % 1 == 0:\n", + " costs.append(minibatch_cost)\n", + " \n", + " \n", + " # plot the cost\n", + " plt.plot(np.squeeze(costs))\n", + " plt.ylabel('cost')\n", + " plt.xlabel('iterations (per tens)')\n", + " plt.title(\"Learning rate =\" + str(learning_rate))\n", + " plt.show()\n", + "\n", + " # Calculate the correct predictions\n", + " predict_op = tf.argmax(Z3, 1)\n", + " correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))\n", + " \n", + " # Calculate accuracy on the test set\n", + " accuracy = tf.reduce_mean(tf.cast(correct_prediction, \"float\"))\n", + " print(accuracy)\n", + " train_accuracy = accuracy.eval({X: X_train, Y: Y_train})\n", + " test_accuracy = accuracy.eval({X: X_test, Y: Y_test})\n", + " print(\"Train Accuracy:\", train_accuracy)\n", + " print(\"Test Accuracy:\", test_accuracy)\n", + " \n", + " return train_accuracy, test_accuracy, parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the following cell to train your model for 100 epochs. Check if your cost after epoch 0 and 5 matches our output. If not, stop the cell and go back to your code!" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cost after epoch 0: 1.918536\n", + "Cost after epoch 5: 1.024695\n", + "Cost after epoch 10: 0.624790\n", + "Cost after epoch 15: 0.485562\n", + "Cost after epoch 20: 0.373167\n", + "Cost after epoch 25: 0.316183\n", + "Cost after epoch 30: 0.280050\n", + "Cost after epoch 35: 0.225940\n", + "Cost after epoch 40: 0.197010\n", + "Cost after epoch 45: 0.169021\n", + "Cost after epoch 50: 0.156169\n", + "Cost after epoch 55: 0.137946\n", + "Cost after epoch 60: 0.121304\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tensor(\"Mean_1:0\", shape=(), dtype=float32)\n", + "Train Accuracy: 0.97407407\n", + "Test Accuracy: 0.875\n" + ] + } + ], + "source": [ + "_, _, parameters = model(X_train, Y_train, X_test, Y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected output**: although it may not match perfectly, your expected output should be close to ours and your cost value should decrease.\n", + "\n", + " \n", + "\n", + " \n", + " \n", + "\n", + "\n", + " \n", + " \n", + "\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + "
\n", + " **Cost after epoch 0 =**\n", + " \n", + " 1.917929\n", + "
\n", + " **Cost after epoch 5 =**\n", + " \n", + " 1.506757\n", + "
\n", + " **Train Accuracy =**\n", + " \n", + " 0.940741\n", + "
\n", + " **Test Accuracy =**\n", + " \n", + " 0.783333\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Congratulations! You have finised the assignment and built a model that recognizes SIGN language with almost 80% accuracy on the test set. If you wish, feel free to play around with this dataset further. You can actually improve its accuracy by spending more time tuning the hyperparameters, or using regularization (as this model clearly has a high variance). \n", + "\n", + "Once again, here's a thumbs up for your work! " + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "E:\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:2: DeprecationWarning: `imread` is deprecated!\n", + "`imread` is deprecated in SciPy 1.0.0.\n", + "Use ``matplotlib.pyplot.imread`` instead.\n", + " \n", + "E:\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py:3: DeprecationWarning: `imresize` is deprecated!\n", + "`imresize` is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.\n", + "Use ``skimage.transform.resize`` instead.\n", + " This is separate from the ipykernel package so we can avoid doing imports until\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fname = \"images/thumbs_up.jpg\"\n", + "image = np.array(ndimage.imread(fname, flatten=False))\n", + "my_image = scipy.misc.imresize(image, size=(64,64))\n", + "plt.imshow(my_image)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Aditional part" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cost after epoch 0: 1.897077\n", + "Cost after epoch 5: 0.574760\n", + "Cost after epoch 10: 0.200760\n", + "Cost after epoch 15: 0.091636\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tensor(\"Mean_1:0\", shape=(), dtype=float32)\n", + "Train Accuracy: 0.975\n", + "Test Accuracy: 0.89166665\n" + ] + } + ], + "source": [ + "# Let's add dropout layer into model and repeat experiment\n", + "_, _, parameters = model(X_train, Y_train, X_test, Y_test, dropout=True, num_epochs = 20)" + ] + } + ], + "metadata": { + "coursera": { + "course_slug": "convolutional-neural-networks", + "graded_item_id": "bwbJV", + "launcher_item_id": "0TkXB" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/cnn/CNN_lesson.ipynb b/cnn/CNN_lesson.ipynb new file mode 100644 index 0000000..b73c48d --- /dev/null +++ b/cnn/CNN_lesson.ipynb @@ -0,0 +1,863 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "from scipy import misc\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "%matplotlib inline\n", + "\n", + "\n", + "img = misc.ascent()\n", + "plt.gray()\n", + "plt.imshow(img)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "filter = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])\n", + "# filter = filter.T\n", + "\n", + "\n", + "features = img.copy()\n", + "for i in range(1, img.shape[0] - 1):\n", + " for j in range(1, img.shape[1] - 1):\n", + " conv = img[i - 1, j - 1] * filter[0][0]\n", + " conv += img[i - 1, j] * filter[0][1]\n", + " conv += img[i - 1, j + 1] * filter[0][2]\n", + " conv += img[i, j - 1] * filter[1][0]\n", + " conv += img[i, j] * filter[1][1]\n", + " conv += img[i, j + 1] * filter[1][2]\n", + " conv += img[i + 1, j - 1] * filter[2][0]\n", + " conv += img[i + 1, j] * filter[2][1]\n", + " conv += img[i + 1, j + 1] * filter[2][2]\n", + " \n", + " conv = 0. if min(conv, 255.) < 0 else min(conv, 255.) \n", + " \n", + " features[i, j] = conv\n", + " \n", + "plt.imshow(features) " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pool_img = np.zeros((img.shape[0] // 2, img.shape[1] // 2))\n", + "\n", + "for i in range(0, features.shape[0], 2):\n", + " for j in range(0, features.shape[1], 2):\n", + " pool_img[i // 2, j // 2] = np.max(features[i:i+2, j:j+2])\n", + " \n", + "plt.imshow(pool_img) " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0528 09:08:06.997658 6852 deprecation.py:506] From E:\\Anaconda\\lib\\site-packages\\tensorflow\\python\\ops\\init_ops.py:1251: calling VarianceScaling.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Call initializer instance with the dtype argument instead of passing it to the constructor\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 4s 67us/sample - loss: 0.7327 - acc: 0.7620\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 4s 61us/sample - loss: 0.5099 - acc: 0.8270\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 4s 61us/sample - loss: 0.4664 - acc: 0.8389\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 4s 62us/sample - loss: 0.4416 - acc: 0.8465\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 4s 66us/sample - loss: 0.4251 - acc: 0.8525\n", + "10000/10000 [==============================] - 0s 41us/sample - loss: 0.4632 - acc: 0.8354\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.46315675230026243, 0.8354]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import tensorflow as tf\n", + "\n", + "\n", + "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.fashion_mnist.load_data()\n", + "x_train = x_train / 255.\n", + "x_test = x_test / 255.\n", + "\n", + "model = tf.keras.Sequential([\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + "])\n", + "model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + "history = model.fit(x_train, y_train, epochs=5)\n", + "model.evaluate(x_test, y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(history.history['loss'])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 48s 808us/sample - loss: 0.8787 - acc: 0.6826\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 46s 766us/sample - loss: 0.5463 - acc: 0.7960\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 48s 797us/sample - loss: 0.4764 - acc: 0.8256\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 47s 791us/sample - loss: 0.4315 - acc: 0.8427\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 52s 873us/sample - loss: 0.4006 - acc: 0.8546\n", + "10000/10000 [==============================] - 3s 282us/sample - loss: 0.4088 - acc: 0.8507\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.4087753909111023, 0.8507]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_train = x_train.reshape(60000, 28, 28, 1)\n", + "x_test = x_test.reshape(10000, 28, 28, 1)\n", + "\n", + "model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + "])\n", + "model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + "history = model.fit(x_train, y_train, epochs=5)\n", + "model.evaluate(x_test, y_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total time execution 241 seconds\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "print(f'Total time execution {(48+46+48+47+52)} seconds')\n", + "plt.title(f'n_convolutions={32}')\n", + "plt.plot(history.history['loss'])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "EXERCISES\n", + "===\n", + "\n", + " - Try editing the convolutions. Change the 32s to either 16 or 64. What impact will this have on accuracy and/or training time.\n", + " - Remove the final Convolution. What impact will this have on accuracy or training time?\n", + " - How about adding more Convolutions? What impact do you think this will have? Experiment with it.\n", + " - Remove all Convolutions but the first. What impact do you think this will have? Experiment with it.\n", + " - In the previous lesson you implemented a callback to check on the loss function and to cancel training once it hit a certain amount. See if you can implement that here!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.Try editing the convolutions. Change the 32s to either 16 or 64. What impact will this have on accuracy and/or training time." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "def my_model(x_train,y_train,x_test,y_test,n_convolutions=32):\n", + " model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu'),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + " ])\n", + " model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + " history = model.fit(x_train, y_train, epochs=5)\n", + " print('Model evaluate',model.evaluate(x_test, y_test))\n", + " plt.title(f'n_convolutions={n_convolutions}')\n", + " plt.plot(history.history['loss'])\n", + " return model, history" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 28s 469us/sample - loss: 0.8446 - acc: 0.6945\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 28s 468us/sample - loss: 0.5455 - acc: 0.7986\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 28s 464us/sample - loss: 0.4746 - acc: 0.8257\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 28s 469us/sample - loss: 0.4341 - acc: 0.8417\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 30s 495us/sample - loss: 0.4065 - acc: 0.8527\n", + "10000/10000 [==============================] - 2s 198us/sample - loss: 0.4191 - acc: 0.8499\n", + "Model evaluate [0.41913245186805725, 0.8499]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "model_16, history_16 = my_model(x_train,y_train,x_test,y_test,n_convolutions=16)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total time execution for n_filters=16 142 seconds\n" + ] + } + ], + "source": [ + "print(f'Total time execution for n_filters=16 {(28+28+28+28+30)} seconds')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 107s 2ms/sample - loss: 0.8770 - acc: 0.6848\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 105s 2ms/sample - loss: 0.5388 - acc: 0.7997\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 105s 2ms/sample - loss: 0.4628 - acc: 0.8318\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 105s 2ms/sample - loss: 0.4192 - acc: 0.8467\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 106s 2ms/sample - loss: 0.3871 - acc: 0.8595\n", + "10000/10000 [==============================] - 5s 517us/sample - loss: 0.3969 - acc: 0.8566\n", + "Model evaluate [0.39689865803718566, 0.8566]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "model_64, history_64 = my_model(x_train,y_train,x_test,y_test,n_convolutions=64)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total time execution for n_filters=16 528 seconds\n" + ] + } + ], + "source": [ + "print(f'Total time execution for n_filters=16 {(107+105+105+105+106)} seconds')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Report for different number of convolution filters (16, 32, 64)\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " n_filters\n", + " \n", + " Accuracy\n", + " \n", + " Time (sec)\n", + "
\n", + " 16\n", + " \n", + " 0.8499\n", + " \n", + " 142\n", + "
\n", + " 32\n", + " \n", + " 0.8507\n", + " \n", + " 241\n", + "
\n", + " 64\n", + " \n", + " 0.8566\n", + " \n", + " 528\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.Remove the final Convolution. What impact will this have on accuracy or training time?" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "def my_model(x_train,y_train,x_test,y_test,n_convolutions=32):\n", + " model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " #tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu'),\n", + " #tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + " ])\n", + " model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + " history = model.fit(x_train, y_train, epochs=5)\n", + " print('Model evaluate (1 conv_2d layer)',model.evaluate(x_test, y_test))\n", + " plt.title(f'n_convolutions={n_convolutions}')\n", + " plt.plot(history.history['loss'])\n", + " return model, history" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 39s 650us/sample - loss: 0.6920 - acc: 0.7566\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 40s 660us/sample - loss: 0.4868 - acc: 0.8260\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 53s 886us/sample - loss: 0.4327 - acc: 0.8470\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 41s 675us/sample - loss: 0.4009 - acc: 0.8579\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 39s 658us/sample - loss: 0.3709 - acc: 0.8692\n", + "10000/10000 [==============================] - 2s 216us/sample - loss: 0.3824 - acc: 0.8622\n", + "Model evaluate (1 conv_2d layer) [0.38239504699707033, 0.8622]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "model_1conv, history_1conv = my_model(x_train,y_train,x_test,y_test,n_convolutions=32)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total time execution 212\n" + ] + } + ], + "source": [ + "print(f'Total time execution {39+40+53+41+39}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Outcome: If we use only one convolutian layer accuracy increses and equals 0.8622 (time execution 212 sec)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.How about adding more Convolutions? What impact do you think this will have? Experiment with it." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def my_model_3(x_train,y_train,x_test,y_test,n_convolutions=32):\n", + " model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu'),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Conv2D(n_convolutions, (3, 3), activation='relu'),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + " ])\n", + " model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + " history = model.fit(x_train, y_train, epochs=5)\n", + " print('Model evaluate (1 conv_2d layer)',model.evaluate(x_test, y_test))\n", + " plt.title(f'n_convolutions={n_convolutions}')\n", + " plt.plot(history.history['loss'])\n", + " return model, history" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "60000/60000 [==============================] - 52s 866us/sample - loss: 1.3171 - acc: 0.5163\n", + "Epoch 2/5\n", + "60000/60000 [==============================] - 53s 877us/sample - loss: 0.7443 - acc: 0.7265\n", + "Epoch 3/5\n", + "60000/60000 [==============================] - 52s 872us/sample - loss: 0.6418 - acc: 0.7644\n", + "Epoch 4/5\n", + "60000/60000 [==============================] - 50s 840us/sample - loss: 0.5768 - acc: 0.7863\n", + "Epoch 5/5\n", + "60000/60000 [==============================] - 50s 841us/sample - loss: 0.5382 - acc: 0.8015\n", + "10000/10000 [==============================] - 3s 280us/sample - loss: 0.5354 - acc: 0.8044\n", + "Model evaluate (1 conv_2d layer) [0.5353573750972748, 0.8044]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "model_3, history_3 = my_model_3(x_train,y_train,x_test,y_test,n_convolutions=32)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total time execution 257\n" + ] + } + ], + "source": [ + "print(f'Total time execution {52+53+52+50+50}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Table of accuracy for different number of conv layers (convolution filters = 32)\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " n_conv_layers\n", + " \n", + " Accuracy\n", + " \n", + " Time (sec)\n", + "
\n", + " 1\n", + " \n", + " 0.8622\n", + " \n", + " 212\n", + "
\n", + " 2\n", + " \n", + " 0.8507\n", + " \n", + " 241\n", + "
\n", + " 3\n", + " \n", + " 0.8044\n", + " \n", + " 257\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Callback to check on the loss function and to cancel training once it hit a certain amount" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "from tensorflow.keras import callbacks" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Train on 60000 samples, validate on 10000 samples\n", + "Epoch 1/30\n", + "60000/60000 [==============================] - 59s 977us/sample - loss: 0.9093 - acc: 0.6723 - val_loss: 0.5892 - val_acc: 0.7794\n", + "Epoch 2/30\n", + "60000/60000 [==============================] - 57s 943us/sample - loss: 0.5277 - acc: 0.8045 - val_loss: 0.5143 - val_acc: 0.8090\n", + "Epoch 3/30\n", + "60000/60000 [==============================] - 59s 975us/sample - loss: 0.4614 - acc: 0.8329 - val_loss: 0.4520 - val_acc: 0.8385\n", + "Epoch 4/30\n", + "60000/60000 [==============================] - 55s 911us/sample - loss: 0.4208 - acc: 0.8474 - val_loss: 0.4320 - val_acc: 0.8432\n", + "Epoch 5/30\n", + "60000/60000 [==============================] - 55s 919us/sample - loss: 0.3934 - acc: 0.8585 - val_loss: 0.4002 - val_acc: 0.8563\n", + "Epoch 6/30\n", + "60000/60000 [==============================] - 54s 893us/sample - loss: 0.3726 - acc: 0.8637 - val_loss: 0.3825 - val_acc: 0.8615\n", + "Epoch 7/30\n", + "60000/60000 [==============================] - 54s 904us/sample - loss: 0.3555 - acc: 0.8699 - val_loss: 0.3671 - val_acc: 0.8661\n", + "Epoch 8/30\n", + "60000/60000 [==============================] - 52s 871us/sample - loss: 0.3408 - acc: 0.8769 - val_loss: 0.3624 - val_acc: 0.8700\n", + "Epoch 00008: early stopping\n" + ] + } + ], + "source": [ + "x_train = x_train.reshape(60000, 28, 28, 1)\n", + "x_test = x_test.reshape(10000, 28, 28, 1)\n", + "\n", + "es=callbacks.EarlyStopping(monitor='val_loss',verbose=1, min_delta=0.01, mode='min')\n", + "\n", + "model = tf.keras.Sequential([\n", + " tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),\n", + " tf.keras.layers.MaxPool2D(2, 2),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(128, activation=tf.nn.relu),\n", + " tf.keras.layers.Dense(10, activation='softmax'),\n", + "])\n", + "model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\n", + "\n", + "history = model.fit(x_train, y_train, epochs=30, validation_data=(x_test, y_test), callbacks=[es,])\n", + "#model.evaluate(x_test, y_test)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/cnn/CNN_step_by_step.ipynb b/cnn/CNN_step_by_step.ipynb new file mode 100644 index 0000000..6d581e1 --- /dev/null +++ b/cnn/CNN_step_by_step.ipynb @@ -0,0 +1,1375 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Convolutional Neural Networks: Step by Step\n", + "\n", + "Welcome to Course 4's first assignment! In this assignment, you will implement convolutional (CONV) and pooling (POOL) layers in numpy, including both forward propagation and (optionally) backward propagation. \n", + "\n", + "**Notation**:\n", + "- Superscript $[l]$ denotes an object of the $l^{th}$ layer. \n", + " - Example: $a^{[4]}$ is the $4^{th}$ layer activation. $W^{[5]}$ and $b^{[5]}$ are the $5^{th}$ layer parameters.\n", + "\n", + "\n", + "- Superscript $(i)$ denotes an object from the $i^{th}$ example. \n", + " - Example: $x^{(i)}$ is the $i^{th}$ training example input.\n", + " \n", + " \n", + "- Lowerscript $i$ denotes the $i^{th}$ entry of a vector.\n", + " - Example: $a^{[l]}_i$ denotes the $i^{th}$ entry of the activations in layer $l$, assuming this is a fully connected (FC) layer.\n", + " \n", + " \n", + "- $n_H$, $n_W$ and $n_C$ denote respectively the height, width and number of channels of a given layer. If you want to reference a specific layer $l$, you can also write $n_H^{[l]}$, $n_W^{[l]}$, $n_C^{[l]}$. \n", + "- $n_{H_{prev}}$, $n_{W_{prev}}$ and $n_{C_{prev}}$ denote respectively the height, width and number of channels of the previous layer. If referencing a specific layer $l$, this could also be denoted $n_H^{[l-1]}$, $n_W^{[l-1]}$, $n_C^{[l-1]}$. \n", + "\n", + "We assume that you are already familiar with `numpy` and/or have completed the previous courses of the specialization. Let's get started!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 - Packages\n", + "\n", + "Let's first import all the packages that you will need during this assignment. \n", + "- [numpy](www.numpy.org) is the fundamental package for scientific computing with Python.\n", + "- [matplotlib](http://matplotlib.org) is a library to plot graphs in Python.\n", + "- np.random.seed(1) is used to keep all the random function calls consistent. It will help us grade your work." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import h5py\n", + "import matplotlib.pyplot as plt\n", + "\n", + "%matplotlib inline\n", + "plt.rcParams['figure.figsize'] = (5.0, 4.0) # set default size of plots\n", + "plt.rcParams['image.interpolation'] = 'nearest'\n", + "plt.rcParams['image.cmap'] = 'gray'\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "np.random.seed(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 - Outline of the Assignment\n", + "\n", + "You will be implementing the building blocks of a convolutional neural network! Each function you will implement will have detailed instructions that will walk you through the steps needed:\n", + "\n", + "- Convolution functions, including:\n", + " - Zero Padding\n", + " - Convolve window \n", + " - Convolution forward\n", + " - Convolution backward (optional)\n", + "- Pooling functions, including:\n", + " - Pooling forward\n", + " - Create mask \n", + " - Distribute value\n", + " - Pooling backward (optional)\n", + " \n", + "This notebook will ask you to implement these functions from scratch in `numpy`. In the next notebook, you will use the TensorFlow equivalents of these functions to build the following model:\n", + "\n", + "\n", + "\n", + "**Note** that for every forward function, there is its corresponding backward equivalent. Hence, at every step of your forward module you will store some parameters in a cache. These parameters are used to compute gradients during backpropagation. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3 - Convolutional Neural Networks\n", + "\n", + "Although programming frameworks make convolutions easy to use, they remain one of the hardest concepts to understand in Deep Learning. A convolution layer transforms an input volume into an output volume of different size, as shown below. \n", + "\n", + "\n", + "\n", + "In this part, you will build every step of the convolution layer. You will first implement two helper functions: one for zero padding and the other for computing the convolution function itself. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1 - Zero-Padding\n", + "\n", + "Zero-padding adds zeros around the border of an image:\n", + "\n", + "\n", + "
**Figure 1** : **Zero-Padding**
Image (3 channels, RGB) with a padding of 2.
\n", + "\n", + "The main benefits of padding are the following:\n", + "\n", + "- It allows you to use a CONV layer without necessarily shrinking the height and width of the volumes. This is important for building deeper networks, since otherwise the height/width would shrink as you go to deeper layers. An important special case is the \"same\" convolution, in which the height/width is exactly preserved after one layer. \n", + "\n", + "- It helps us keep more of the information at the border of an image. Without padding, very few values at the next layer would be affected by pixels as the edges of an image.\n", + "\n", + "**Exercise**: Implement the following function, which pads all the images of a batch of examples X with zeros. [Use np.pad](https://docs.scipy.org/doc/numpy/reference/generated/numpy.pad.html). Note if you want to pad the array \"a\" of shape $(5,5,5,5,5)$ with `pad = 1` for the 2nd dimension, `pad = 3` for the 4th dimension and `pad = 0` for the rest, you would do:\n", + "```python\n", + "a = np.pad(a, ((0,0), (1,1), (0,0), (3,3), (0,0)), 'constant', constant_values = (..,..))\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: zero_pad\n", + "\n", + "def zero_pad(X, pad):\n", + " \"\"\"\n", + " Pad with zeros all images of the dataset X. The padding is applied to the height and width of an image, \n", + " as illustrated in Figure 1.\n", + " \n", + " Argument:\n", + " X -- python numpy array of shape (m, n_H, n_W, n_C) representing a batch of m images\n", + " pad -- integer, amount of padding around each image on vertical and horizontal dimensions\n", + " \n", + " Returns:\n", + " X_pad -- padded image of shape (m, n_H + 2*pad, n_W + 2*pad, n_C)\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ### (≈ 1 line)\n", + " X_pad = np.pad(X, [(0,0),(pad,pad),(pad,pad),(0,0)], 'constant', constant_values=0)\n", + " ### END CODE HERE ###\n", + " \n", + " return X_pad" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x.shape = (4, 3, 3, 2)\n", + "x_pad.shape = (4, 7, 7, 2)\n", + "x[1,1] = [[ 0.90085595 -0.68372786]\n", + " [-0.12289023 -0.93576943]\n", + " [-0.26788808 0.53035547]]\n", + "x_pad[1,1] = [[0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]\n", + " [0. 0.]]\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "np.random.seed(1)\n", + "x = np.random.randn(4, 3, 3, 2)\n", + "x_pad = zero_pad(x, 2)\n", + "print (\"x.shape =\", x.shape)\n", + "print (\"x_pad.shape =\", x_pad.shape)\n", + "print (\"x[1,1] =\", x[1,1])\n", + "print (\"x_pad[1,1] =\", x_pad[1,1])\n", + "\n", + "fig, axarr = plt.subplots(1, 2)\n", + "axarr[0].set_title('x')\n", + "axarr[0].imshow(x[0,:,:,0])\n", + "axarr[1].set_title('x_pad')\n", + "axarr[1].imshow(x_pad[0,:,:,0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
\n", + " **x.shape**:\n", + " \n", + " (4, 3, 3, 2)\n", + "
\n", + " **x_pad.shape**:\n", + " \n", + " (4, 7, 7, 2)\n", + "
\n", + " **x[1,1]**:\n", + " \n", + " [[ 0.90085595 -0.68372786]\n", + " [-0.12289023 -0.93576943]\n", + " [-0.26788808 0.53035547]]\n", + "
\n", + " **x_pad[1,1]**:\n", + " \n", + " [[ 0. 0.]\n", + " [ 0. 0.]\n", + " [ 0. 0.]\n", + " [ 0. 0.]\n", + " [ 0. 0.]\n", + " [ 0. 0.]\n", + " [ 0. 0.]]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2 - Single step of convolution \n", + "\n", + "In this part, implement a single step of convolution, in which you apply the filter to a single position of the input. This will be used to build a convolutional unit, which: \n", + "\n", + "- Takes an input volume \n", + "- Applies a filter at every position of the input\n", + "- Outputs another volume (usually of different size)\n", + "\n", + "\n", + "
**Figure 2** : **Convolution operation**
with a filter of 2x2 and a stride of 1 (stride = amount you move the window each time you slide)
\n", + "\n", + "In a computer vision application, each value in the matrix on the left corresponds to a single pixel value, and we convolve a 3x3 filter with the image by multiplying its values element-wise with the original matrix, then summing them up and adding a bias. In this first step of the exercise, you will implement a single step of convolution, corresponding to applying a filter to just one of the positions to get a single real-valued output. \n", + "\n", + "Later in this notebook, you'll apply this function to multiple positions of the input to implement the full convolutional operation. \n", + "\n", + "**Exercise**: Implement conv_single_step(). [Hint](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.sum.html).\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: conv_single_step\n", + "\n", + "def conv_single_step(a_slice_prev, W, b):\n", + " \"\"\"\n", + " Apply one filter defined by parameters W on a single slice (a_slice_prev) of the output activation \n", + " of the previous layer.\n", + " \n", + " Arguments:\n", + " a_slice_prev -- slice of input data of shape (f, f, n_C_prev)\n", + " W -- Weight parameters contained in a window - matrix of shape (f, f, n_C_prev)\n", + " b -- Bias parameters contained in a window - matrix of shape (1, 1, 1)\n", + " \n", + " Returns:\n", + " Z -- a scalar value, result of convolving the sliding window (W, b) on a slice x of the input data\n", + " \"\"\"\n", + "\n", + " ### START CODE HERE ### (≈ 2 lines of code)\n", + " # Element-wise product between a_slice and W. Do not add the bias yet.\n", + " s = np.multiply(a_slice_prev, W)\n", + " # Sum over all entries of the volume s.\n", + " Z = np.sum(s)\n", + " # Add bias b to Z. Cast b to a float() so that Z results in a scalar value.\n", + " Z = Z + b\n", + " ### END CODE HERE ###\n", + "\n", + " return Z" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Z = [[[-6.99908945]]]\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "a_slice_prev = np.random.randn(4, 4, 3)\n", + "W = np.random.randn(4, 4, 3)\n", + "b = np.random.randn(1, 1, 1)\n", + "\n", + "Z = conv_single_step(a_slice_prev, W, b)\n", + "print(\"Z =\", Z)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
\n", + " **Z**\n", + " \n", + " -6.99908945068\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### 3.3 - Convolutional Neural Networks - Forward pass\n", + "\n", + "In the forward pass, you will take many filters and convolve them on the input. Each 'convolution' gives you a 2D matrix output. You will then stack these outputs to get a 3D volume: \n", + "\n", + "
\n", + "\n", + "
\n", + "\n", + "**Exercise**: Implement the function below to convolve the filters W on an input activation A_prev. This function takes as input A_prev, the activations output by the previous layer (for a batch of m inputs), F filters/weights denoted by W, and a bias vector denoted by b, where each filter has its own (single) bias. Finally you also have access to the hyperparameters dictionary which contains the stride and the padding. \n", + "\n", + "**Hint**: \n", + "1. To select a 2x2 slice at the upper left corner of a matrix \"a_prev\" (shape (5,5,3)), you would do:\n", + "```python\n", + "a_slice_prev = a_prev[0:2,0:2,:]\n", + "```\n", + "This will be useful when you will define `a_slice_prev` below, using the `start/end` indexes you will define.\n", + "2. To define a_slice you will need to first define its corners `vert_start`, `vert_end`, `horiz_start` and `horiz_end`. This figure may be helpful for you to find how each of the corner can be defined using h, w, f and s in the code below.\n", + "\n", + "\n", + "
**Figure 3** : **Definition of a slice using vertical and horizontal start/end (with a 2x2 filter)**
This figure shows only a single channel.
\n", + "\n", + "\n", + "**Reminder**:\n", + "The formulas relating the output shape of the convolution to the input shape is:\n", + "$$ n_H = \\lfloor \\frac{n_{H_{prev}} - f + 2 \\times pad}{stride} \\rfloor +1 $$\n", + "$$ n_W = \\lfloor \\frac{n_{W_{prev}} - f + 2 \\times pad}{stride} \\rfloor +1 $$\n", + "$$ n_C = \\text{number of filters used in the convolution}$$\n", + "\n", + "For this exercise, we won't worry about vectorization, and will just implement everything with for-loops." + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: conv_forward\n", + "\n", + "def conv_forward(A_prev, W, b, hparameters):\n", + " \"\"\"\n", + " Implements the forward propagation for a convolution function\n", + " \n", + " Arguments:\n", + " A_prev -- output activations of the previous layer, numpy array of shape (m, n_H_prev, n_W_prev, n_C_prev)\n", + " W -- Weights, numpy array of shape (f, f, n_C_prev, n_C)\n", + " b -- Biases, numpy array of shape (1, 1, 1, n_C)\n", + " hparameters -- python dictionary containing \"stride\" and \"pad\"\n", + " \n", + " Returns:\n", + " Z -- conv output, numpy array of shape (m, n_H, n_W, n_C)\n", + " cache -- cache of values needed for the conv_backward() function\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ###\n", + " # Retrieve dimensions from A_prev's shape (≈1 line) \n", + " (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape\n", + " \n", + " # Retrieve dimensions from W's shape (≈1 line)\n", + " (f, f, n_C_prev, n_C) = W.shape\n", + " \n", + " # Retrieve information from \"hparameters\" (≈2 lines)\n", + " stride = hparameters['stride']\n", + " pad = hparameters['pad']\n", + " \n", + " # Compute the dimensions of the CONV output volume using the formula given above. Hint: use int() to floor. (≈2 lines)\n", + " n_H = np.int((n_H_prev-f+2*pad)/stride + 1)\n", + " n_W = np.int((n_W_prev-f+2*pad)/stride + 1)\n", + " \n", + " # Initialize the output volume Z with zeros. (≈1 line)\n", + " Z = np.zeros((m,n_H,n_W,n_C ))\n", + " \n", + " # Create A_prev_pad by padding A_prev\n", + " A_prev_pad = zero_pad(A_prev, pad)\n", + " for i in range(m): # loop over the batch of training examples\n", + " a_prev_pad = A_prev_pad[i] # Select ith training example's padded activation\n", + " for h in range(n_H): # loop over vertical axis of the output volume\n", + " for w in range(n_W): # loop over horizontal axis of the output volume\n", + " for c in range(n_C): # loop over channels (= #filters) of the output volume\n", + " \n", + " # Find the corners of the current \"slice\" (≈4 lines)\n", + " vert_start = h*stride\n", + " vert_end = vert_start+f\n", + " horiz_start = w*stride\n", + " horiz_end = horiz_start+f\n", + " \n", + " # Use the corners to define the (3D) slice of a_prev_pad (See Hint above the cell). (≈1 line)\n", + " a_slice_prev = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]\n", + " \n", + " # Convolve the (3D) slice with the correct filter W and bias b, to get back one output neuron. (≈1 line)\n", + " Z[i, h, w, c] = conv_single_step(a_slice_prev, W[:,:,:,c], b[:,:,:,c])\n", + " \n", + " ### END CODE HERE ###\n", + " \n", + " # Making sure your output shape is correct\n", + " assert(Z.shape == (m, n_H, n_W, n_C))\n", + " \n", + " # Save information in \"cache\" for the backprop\n", + " cache = (A_prev, W, b, hparameters)\n", + " \n", + " return Z, cache" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Z's mean = 0.048995203528855794\n", + "Z[3,2,1] = [-0.61490741 -6.7439236 -2.55153897 1.75698377 3.56208902 0.53036437\n", + " 5.18531798 8.75898442]\n", + "cache_conv[0][1][2][3] = [-0.20075807 0.18656139 0.41005165]\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "A_prev = np.random.randn(10,4,4,3)\n", + "W = np.random.randn(2,2,3,8)\n", + "b = np.random.randn(1,1,1,8)\n", + "hparameters = {\"pad\" : 2,\n", + " \"stride\": 2}\n", + "\n", + "Z, cache_conv = conv_forward(A_prev, W, b, hparameters)\n", + "print(\"Z's mean =\", np.mean(Z))\n", + "print(\"Z[3,2,1] =\", Z[3,2,1])\n", + "print(\"cache_conv[0][1][2][3] =\", cache_conv[0][1][2][3])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
\n", + " **Z's mean**\n", + " \n", + " 0.0489952035289\n", + "
\n", + " **Z[3,2,1]**\n", + " \n", + " [-0.61490741 -6.7439236 -2.55153897 1.75698377 3.56208902 0.53036437\n", + " 5.18531798 8.75898442]\n", + "
\n", + " **cache_conv[0][1][2][3]**\n", + " \n", + " [-0.20075807 0.18656139 0.41005165]\n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, CONV layer should also contain an activation, in which case we would add the following line of code:\n", + "\n", + "```python\n", + "# Convolve the window to get back one output neuron\n", + "Z[i, h, w, c] = ...\n", + "# Apply activation\n", + "A[i, h, w, c] = activation(Z[i, h, w, c])\n", + "```\n", + "\n", + "You don't need to do it here. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 - Pooling layer \n", + "\n", + "The pooling (POOL) layer reduces the height and width of the input. It helps reduce computation, as well as helps make feature detectors more invariant to its position in the input. The two types of pooling layers are: \n", + "\n", + "- Max-pooling layer: slides an ($f, f$) window over the input and stores the max value of the window in the output.\n", + "\n", + "- Average-pooling layer: slides an ($f, f$) window over the input and stores the average value of the window in the output.\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "These pooling layers have no parameters for backpropagation to train. However, they have hyperparameters such as the window size $f$. This specifies the height and width of the fxf window you would compute a max or average over. \n", + "\n", + "### 4.1 - Forward Pooling\n", + "Now, you are going to implement MAX-POOL and AVG-POOL, in the same function. \n", + "\n", + "**Exercise**: Implement the forward pass of the pooling layer. Follow the hints in the comments below.\n", + "\n", + "**Reminder**:\n", + "As there's no padding, the formulas binding the output shape of the pooling to the input shape is:\n", + "$$ n_H = \\lfloor \\frac{n_{H_{prev}} - f}{stride} \\rfloor +1 $$\n", + "$$ n_W = \\lfloor \\frac{n_{W_{prev}} - f}{stride} \\rfloor +1 $$\n", + "$$ n_C = n_{C_{prev}}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "# GRADED FUNCTION: pool_forward\n", + "\n", + "def pool_forward(A_prev, hparameters, mode = \"max\"):\n", + " \"\"\"\n", + " Implements the forward pass of the pooling layer\n", + " \n", + " Arguments:\n", + " A_prev -- Input data, numpy array of shape (m, n_H_prev, n_W_prev, n_C_prev)\n", + " hparameters -- python dictionary containing \"f\" and \"stride\"\n", + " mode -- the pooling mode you would like to use, defined as a string (\"max\" or \"average\")\n", + " \n", + " Returns:\n", + " A -- output of the pool layer, a numpy array of shape (m, n_H, n_W, n_C)\n", + " cache -- cache used in the backward pass of the pooling layer, contains the input and hparameters \n", + " \"\"\"\n", + " \n", + " # Retrieve dimensions from the input shape\n", + " (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape\n", + " \n", + " # Retrieve hyperparameters from \"hparameters\"\n", + " f = hparameters[\"f\"]\n", + " stride = hparameters[\"stride\"]\n", + " \n", + " # Define the dimensions of the output\n", + " n_H = int(1 + (n_H_prev - f) / stride)\n", + " n_W = int(1 + (n_W_prev - f) / stride)\n", + " n_C = n_C_prev\n", + " \n", + " # Initialize output matrix A\n", + " A = np.zeros((m, n_H, n_W, n_C)) \n", + " \n", + " ### START CODE HERE ###\n", + " for i in range(m): # loop over the training examples\n", + " for h in range(n_H): # loop on the vertical axis of the output volume\n", + " for w in range(n_W): # loop on the horizontal axis of the output volume\n", + " for c in range (n_C): # loop over the channels of the output volume\n", + " \n", + " # Find the corners of the current \"slice\" (≈4 lines)\n", + " vert_start = h*stride\n", + " vert_end = vert_start+f\n", + " horiz_start = w*stride\n", + " horiz_end = horiz_start+f\n", + " \n", + " # Use the corners to define the current slice on the ith training example of A_prev, channel c. (≈1 line)\n", + " a_prev_slice = A_prev[i,vert_start:vert_end,horiz_start:horiz_end,c ]\n", + " \n", + " # Compute the pooling operation on the slice. Use an if statment to differentiate the modes. Use np.max/np.mean.\n", + " if mode == \"max\":\n", + " A[i, h, w, c] = np.max(a_prev_slice)\n", + " elif mode == \"average\":\n", + " A[i, h, w, c] = np.mean(a_prev_slice)\n", + " \n", + " ### END CODE HERE ###\n", + " \n", + " # Store the input and hparameters in \"cache\" for pool_backward()\n", + " cache = (A_prev, hparameters)\n", + " \n", + " # Making sure your output shape is correct\n", + " assert(A.shape == (m, n_H, n_W, n_C))\n", + " \n", + " return A, cache" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mode = max\n", + "A = [[[[1.74481176 0.86540763 1.13376944]]]\n", + "\n", + "\n", + " [[[1.13162939 1.51981682 2.18557541]]]]\n", + "\n", + "mode = average\n", + "A = [[[[ 0.02105773 -0.20328806 -0.40389855]]]\n", + "\n", + "\n", + " [[[-0.22154621 0.51716526 0.48155844]]]]\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "A_prev = np.random.randn(2, 4, 4, 3)\n", + "hparameters = {\"stride\" : 2, \"f\": 3}\n", + "\n", + "A, cache = pool_forward(A_prev, hparameters)\n", + "print(\"mode = max\")\n", + "print(\"A =\", A)\n", + "print()\n", + "A, cache = pool_forward(A_prev, hparameters, mode = \"average\")\n", + "print(\"mode = average\")\n", + "print(\"A =\", A)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output:**\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " A =\n", + " \n", + " [[[[ 1.74481176 0.86540763 1.13376944]]]\n", + " [[[ 1.13162939 1.51981682 2.18557541]]]]\n", + "
\n", + " A =\n", + " \n", + " [[[[ 0.02105773 -0.20328806 -0.40389855]]]\n", + " [[[-0.22154621 0.51716526 0.48155844]]]]\n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Congratulations! You have now implemented the forward passes of all the layers of a convolutional network. \n", + "\n", + "The remainer of this notebook is optional, and will not be graded.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 - Backpropagation in convolutional neural networks (OPTIONAL / UNGRADED)\n", + "\n", + "In modern deep learning frameworks, you only have to implement the forward pass, and the framework takes care of the backward pass, so most deep learning engineers don't need to bother with the details of the backward pass. The backward pass for convolutional networks is complicated. If you wish however, you can work through this optional portion of the notebook to get a sense of what backprop in a convolutional network looks like. \n", + "\n", + "When in an earlier course you implemented a simple (fully connected) neural network, you used backpropagation to compute the derivatives with respect to the cost to update the parameters. Similarly, in convolutional neural networks you can to calculate the derivatives with respect to the cost in order to update the parameters. The backprop equations are not trivial and we did not derive them in lecture, but we briefly presented them below.\n", + "\n", + "### 5.1 - Convolutional layer backward pass \n", + "\n", + "Let's start by implementing the backward pass for a CONV layer. \n", + "\n", + "#### 5.1.1 - Computing dA:\n", + "This is the formula for computing $dA$ with respect to the cost for a certain filter $W_c$ and a given training example:\n", + "\n", + "$$ dA += \\sum _{h=0} ^{n_H} \\sum_{w=0} ^{n_W} W_c \\times dZ_{hw} \\tag{1}$$\n", + "\n", + "Where $W_c$ is a filter and $dZ_{hw}$ is a scalar corresponding to the gradient of the cost with respect to the output of the conv layer Z at the hth row and wth column (corresponding to the dot product taken at the ith stride left and jth stride down). Note that at each time, we multiply the the same filter $W_c$ by a different dZ when updating dA. We do so mainly because when computing the forward propagation, each filter is dotted and summed by a different a_slice. Therefore when computing the backprop for dA, we are just adding the gradients of all the a_slices. \n", + "\n", + "In code, inside the appropriate for-loops, this formula translates into:\n", + "```python\n", + "da_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :] += W[:,:,:,c] * dZ[i, h, w, c]\n", + "```\n", + "\n", + "#### 5.1.2 - Computing dW:\n", + "This is the formula for computing $dW_c$ ($dW_c$ is the derivative of one filter) with respect to the loss:\n", + "\n", + "$$ dW_c += \\sum _{h=0} ^{n_H} \\sum_{w=0} ^ {n_W} a_{slice} \\times dZ_{hw} \\tag{2}$$\n", + "\n", + "Where $a_{slice}$ corresponds to the slice which was used to generate the acitivation $Z_{ij}$. Hence, this ends up giving us the gradient for $W$ with respect to that slice. Since it is the same $W$, we will just add up all such gradients to get $dW$. \n", + "\n", + "In code, inside the appropriate for-loops, this formula translates into:\n", + "```python\n", + "dW[:,:,:,c] += a_slice * dZ[i, h, w, c]\n", + "```\n", + "\n", + "#### 5.1.3 - Computing db:\n", + "\n", + "This is the formula for computing $db$ with respect to the cost for a certain filter $W_c$:\n", + "\n", + "$$ db = \\sum_h \\sum_w dZ_{hw} \\tag{3}$$\n", + "\n", + "As you have previously seen in basic neural networks, db is computed by summing $dZ$. In this case, you are just summing over all the gradients of the conv output (Z) with respect to the cost. \n", + "\n", + "In code, inside the appropriate for-loops, this formula translates into:\n", + "```python\n", + "db[:,:,:,c] += dZ[i, h, w, c]\n", + "```\n", + "\n", + "**Exercise**: Implement the `conv_backward` function below. You should sum over all the training examples, filters, heights, and widths. You should then compute the derivatives using formulas 1, 2 and 3 above. " + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [], + "source": [ + "def conv_backward(dZ, cache):\n", + " \"\"\"\n", + " Implement the backward propagation for a convolution function\n", + " \n", + " Arguments:\n", + " dZ -- gradient of the cost with respect to the output of the conv layer (Z), numpy array of shape (m, n_H, n_W, n_C)\n", + " cache -- cache of values needed for the conv_backward(), output of conv_forward()\n", + " \n", + " Returns:\n", + " dA_prev -- gradient of the cost with respect to the input of the conv layer (A_prev),\n", + " numpy array of shape (m, n_H_prev, n_W_prev, n_C_prev)\n", + " dW -- gradient of the cost with respect to the weights of the conv layer (W)\n", + " numpy array of shape (f, f, n_C_prev, n_C)\n", + " db -- gradient of the cost with respect to the biases of the conv layer (b)\n", + " numpy array of shape (1, 1, 1, n_C)\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ###\n", + " # Retrieve information from \"cache\"\n", + " (A_prev, W, b, hparameters) = cache\n", + " \n", + " # Retrieve dimensions from A_prev's shape\n", + " (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape\n", + " \n", + " # Retrieve dimensions from W's shape\n", + " (f, f, n_C_prev, n_C) = W.shape\n", + " \n", + " # Retrieve information from \"hparameters\"\n", + " stride = hparameters['stride']\n", + " pad = hparameters['pad']\n", + " \n", + " # Retrieve dimensions from dZ's shape\n", + " (m, n_H, n_W, n_C) = dZ.shape\n", + " \n", + " # Initialize dA_prev, dW, db with the correct shapes\n", + " dA_prev = np.zeros(A_prev.shape) \n", + " dW = np.zeros(W.shape)\n", + " db = np.zeros(b.shape)\n", + "\n", + " # Pad A_prev and dA_prev\n", + " A_prev_pad = zero_pad(A_prev, pad)\n", + " dA_prev_pad = zero_pad(dA_prev, pad)\n", + " \n", + " for i in range(m): # loop over the training examples\n", + " \n", + " # select ith training example from A_prev_pad and dA_prev_pad\n", + " a_prev_pad = A_prev_pad[i]\n", + " da_prev_pad = dA_prev_pad[i]\n", + " \n", + " for h in range(n_H): # loop over vertical axis of the output volume\n", + " for w in range(n_W): # loop over horizontal axis of the output volume\n", + " for c in range(n_C): # loop over the channels of the output volume\n", + " \n", + " # Find the corners of the current \"slice\"\n", + " vert_start = h*stride\n", + " vert_end = vert_start+f\n", + " horiz_start = w*stride\n", + " horiz_end = horiz_start+f\n", + " \n", + " # Use the corners to define the slice from a_prev_pad\n", + " a_slice = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]\n", + "\n", + " # Update gradients for the window and the filter's parameters using the code formulas given above\n", + " da_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :] += W[:,:,:,c]*dZ[i,h,w,c]\n", + " dW[:,:,:,c] += a_slice*dZ[i,h,w,c]\n", + " db[:,:,:,c] += dZ[i,h,w,c]\n", + " \n", + " # Set the ith training example's dA_prev to the unpaded da_prev_pad (Hint: use X[pad:-pad, pad:-pad, :])\n", + " dA_prev[i, :, :, :] = da_prev_pad[pad:-pad, pad:-pad, :]\n", + " ### END CODE HERE ###\n", + " \n", + " # Making sure your output shape is correct\n", + " assert(dA_prev.shape == (m, n_H_prev, n_W_prev, n_C_prev))\n", + " \n", + " return dA_prev, dW, db" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dA_mean = 1.4524377775388075\n", + "dW_mean = 1.7269914583139097\n", + "db_mean = 7.839232564616838\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "dA, dW, db = conv_backward(Z, cache_conv)\n", + "print(\"dA_mean =\", np.mean(dA))\n", + "print(\"dW_mean =\", np.mean(dW))\n", + "print(\"db_mean =\", np.mean(db))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "** Expected Output: **\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
\n", + " **dA_mean**\n", + " \n", + " 1.45243777754\n", + "
\n", + " **dW_mean**\n", + " \n", + " 1.72699145831\n", + "
\n", + " **db_mean**\n", + " \n", + " 7.83923256462\n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5.2 Pooling layer - backward pass\n", + "\n", + "Next, let's implement the backward pass for the pooling layer, starting with the MAX-POOL layer. Even though a pooling layer has no parameters for backprop to update, you still need to backpropagation the gradient through the pooling layer in order to compute gradients for layers that came before the pooling layer. \n", + "\n", + "### 5.2.1 Max pooling - backward pass \n", + "\n", + "Before jumping into the backpropagation of the pooling layer, you are going to build a helper function called `create_mask_from_window()` which does the following: \n", + "\n", + "$$ X = \\begin{bmatrix}\n", + "1 && 3 \\\\\n", + "4 && 2\n", + "\\end{bmatrix} \\quad \\rightarrow \\quad M =\\begin{bmatrix}\n", + "0 && 0 \\\\\n", + "1 && 0\n", + "\\end{bmatrix}\\tag{4}$$\n", + "\n", + "As you can see, this function creates a \"mask\" matrix which keeps track of where the maximum of the matrix is. True (1) indicates the position of the maximum in X, the other entries are False (0). You'll see later that the backward pass for average pooling will be similar to this but using a different mask. \n", + "\n", + "**Exercise**: Implement `create_mask_from_window()`. This function will be helpful for pooling backward. \n", + "Hints:\n", + "- [np.max()]() may be helpful. It computes the maximum of an array.\n", + "- If you have a matrix X and a scalar x: `A = (X == x)` will return a matrix A of the same size as X such that:\n", + "```\n", + "A[i,j] = True if X[i,j] = x\n", + "A[i,j] = False if X[i,j] != x\n", + "```\n", + "- Here, you don't need to consider cases where there are several maxima in a matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "def create_mask_from_window(x):\n", + " \"\"\"\n", + " Creates a mask from an input matrix x, to identify the max entry of x.\n", + " \n", + " Arguments:\n", + " x -- Array of shape (f, f)\n", + " \n", + " Returns:\n", + " mask -- Array of the same shape as window, contains a True at the position corresponding to the max entry of x.\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ### (≈1 line)\n", + " mask = (x==np.max(x))\n", + " ### END CODE HERE ###\n", + " \n", + " return mask" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x = [[ 1.62434536 -0.61175641 -0.52817175]\n", + " [-1.07296862 0.86540763 -2.3015387 ]]\n", + "mask = [[ True False False]\n", + " [False False False]]\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "x = np.random.randn(2,3)\n", + "mask = create_mask_from_window(x)\n", + "print('x = ', x)\n", + "print(\"mask = \", mask)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "**Expected Output:** \n", + "\n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "**x =**\n", + "\n", + "\n", + "[[ 1.62434536 -0.61175641 -0.52817175]
\n", + " [-1.07296862 0.86540763 -2.3015387 ]]\n", + "\n", + "
\n", + "**mask =**\n", + "\n", + "[[ True False False]
\n", + " [False False False]]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Why do we keep track of the position of the max? It's because this is the input value that ultimately influenced the output, and therefore the cost. Backprop is computing gradients with respect to the cost, so anything that influences the ultimate cost should have a non-zero gradient. So, backprop will \"propagate\" the gradient back to this particular input value that had influenced the cost. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2.2 - Average pooling - backward pass \n", + "\n", + "In max pooling, for each input window, all the \"influence\" on the output came from a single input value--the max. In average pooling, every element of the input window has equal influence on the output. So to implement backprop, you will now implement a helper function that reflects this.\n", + "\n", + "For example if we did average pooling in the forward pass using a 2x2 filter, then the mask you'll use for the backward pass will look like: \n", + "$$ dZ = 1 \\quad \\rightarrow \\quad dZ =\\begin{bmatrix}\n", + "1/4 && 1/4 \\\\\n", + "1/4 && 1/4\n", + "\\end{bmatrix}\\tag{5}$$\n", + "\n", + "This implies that each position in the $dZ$ matrix contributes equally to output because in the forward pass, we took an average. \n", + "\n", + "**Exercise**: Implement the function below to equally distribute a value dz through a matrix of dimension shape. [Hint](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ones.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "def distribute_value(dz, shape):\n", + " \"\"\"\n", + " Distributes the input value in the matrix of dimension shape\n", + " \n", + " Arguments:\n", + " dz -- input scalar\n", + " shape -- the shape (n_H, n_W) of the output matrix for which we want to distribute the value of dz\n", + " \n", + " Returns:\n", + " a -- Array of size (n_H, n_W) for which we distributed the value of dz\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ###\n", + " # Retrieve dimensions from shape (≈1 line)\n", + " (n_H, n_W) = shape\n", + " \n", + " # Compute the value to distribute on the matrix (≈1 line)\n", + " average = dz/(n_H+n_W)\n", + " \n", + " # Create a matrix where every entry is the \"average\" value (≈1 line)\n", + " a = np.zeros(shape)+average\n", + " ### END CODE HERE ###\n", + " \n", + " return a" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "distributed value = [[0.5 0.5]\n", + " [0.5 0.5]]\n" + ] + } + ], + "source": [ + "a = distribute_value(2, (2,2))\n", + "print('distributed value =', a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**: \n", + "\n", + " \n", + " \n", + "\n", + "\n", + "\n", + "
\n", + "distributed_value =\n", + "\n", + "[[ 0.5 0.5]\n", + " \n", + "[ 0.5 0.5]]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2.3 Putting it together: Pooling backward \n", + "\n", + "You now have everything you need to compute backward propagation on a pooling layer.\n", + "\n", + "**Exercise**: Implement the `pool_backward` function in both modes (`\"max\"` and `\"average\"`). You will once again use 4 for-loops (iterating over training examples, height, width, and channels). You should use an `if/elif` statement to see if the mode is equal to `'max'` or `'average'`. If it is equal to 'average' you should use the `distribute_value()` function you implemented above to create a matrix of the same shape as `a_slice`. Otherwise, the mode is equal to '`max`', and you will create a mask with `create_mask_from_window()` and multiply it by the corresponding value of dZ." + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [], + "source": [ + "def pool_backward(dA, cache, mode = \"max\"):\n", + " \"\"\"\n", + " Implements the backward pass of the pooling layer\n", + " \n", + " Arguments:\n", + " dA -- gradient of cost with respect to the output of the pooling layer, same shape as A\n", + " cache -- cache output from the forward pass of the pooling layer, contains the layer's input and hparameters \n", + " mode -- the pooling mode you would like to use, defined as a string (\"max\" or \"average\")\n", + " \n", + " Returns:\n", + " dA_prev -- gradient of cost with respect to the input of the pooling layer, same shape as A_prev\n", + " \"\"\"\n", + " \n", + " ### START CODE HERE ###\n", + " \n", + " # Retrieve information from cache (≈1 line)\n", + " (A_prev, hparameters) = cache\n", + " \n", + " # Retrieve hyperparameters from \"hparameters\" (≈2 lines)\n", + " stride = hparameters['stride']\n", + " f = hparameters['f']\n", + " \n", + " # Retrieve dimensions from A_prev's shape and dA's shape (≈2 lines)\n", + " m, n_H_prev, n_W_prev, n_C_prev = A_prev.shape\n", + " m, n_H, n_W, n_C = dA.shape\n", + " print(f'dA_shape {dA.shape}')\n", + " \n", + " # Initialize dA_prev with zeros (≈1 line)\n", + " dA_prev = np.zeros(A_prev.shape)\n", + " \n", + " for i in range(m): # loop over the training examples\n", + " \n", + " # select training example from A_prev (≈1 line)\n", + " a_prev = A_prev[i]\n", + " \n", + " for h in range(n_H): # loop on the vertical axis\n", + " for w in range(n_W): # loop on the horizontal axis\n", + " for c in range(n_C): # loop over the channels (depth)\n", + " \n", + " # Find the corners of the current \"slice\" (≈4 lines)\n", + " vert_start = h*stride\n", + " vert_end = vert_start+f\n", + " horiz_start = w*stride\n", + " horiz_end = horiz_start+f\n", + " \n", + " # Compute the backward propagation in both modes.\n", + " if mode == \"max\":\n", + " \n", + " # Use the corners and \"c\" to define the current slice from a_prev (≈1 line)\n", + " a_prev_slice = a_prev[vert_start:vert_end, horiz_start:horiz_end, c ]\n", + " # Create the mask from a_prev_slice (≈1 line)\n", + " mask = create_mask_from_window(a_prev_slice)\n", + " # Set dA_prev to be dA_prev + (the mask multiplied by the correct entry of dA) (≈1 line)\n", + " dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += dA[i, h, w, c]*mask\n", + " \n", + " elif mode == \"average\":\n", + " \n", + " # Get the value a from dA (≈1 line)\n", + " da = dA[i,h,w, c]\n", + " # Define the shape of the filter as fxf (≈1 line)\n", + " shape = (f,f)\n", + " # Distribute it to get the correct slice of dA_prev. i.e. Add the distributed value of da. (≈1 line)\n", + " dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += distribute_value(da, shape)\n", + " \n", + " ### END CODE ###\n", + " \n", + " # Making sure your output shape is correct\n", + " assert(dA_prev.shape == A_prev.shape)\n", + " \n", + " return dA_prev" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dA_shape (5, 4, 2, 2)\n", + "mode = max\n", + "mean of dA = 0.14571390272918056\n", + "dA_prev[1,1] = [[ 0. 0. ]\n", + " [ 5.05844394 -1.68282702]\n", + " [ 0. 0. ]]\n", + "\n", + "dA_shape (5, 4, 2, 2)\n", + "mode = average\n", + "mean of dA = 0.14571390272918056\n", + "dA_prev[1,1] = [[ 0.08485462 0.2787552 ]\n", + " [ 1.26461098 -0.25749373]\n", + " [ 1.17975636 -0.53624893]]\n" + ] + } + ], + "source": [ + "np.random.seed(1)\n", + "A_prev = np.random.randn(5, 5, 3, 2)\n", + "hparameters = {\"stride\" : 1, \"f\": 2}\n", + "A, cache = pool_forward(A_prev, hparameters)\n", + "dA = np.random.randn(5, 4, 2, 2)\n", + "\n", + "dA_prev = pool_backward(dA, cache, mode = \"max\")\n", + "print(\"mode = max\")\n", + "print('mean of dA = ', np.mean(dA))\n", + "print('dA_prev[1,1] = ', dA_prev[1,1]) \n", + "print()\n", + "dA_prev = pool_backward(dA, cache, mode = \"average\")\n", + "print(\"mode = average\")\n", + "print('mean of dA = ', np.mean(dA))\n", + "print('dA_prev[1,1] = ', dA_prev[1,1]) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**: \n", + "\n", + "mode = max:\n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "**mean of dA =**\n", + "\n", + "\n", + "0.145713902729\n", + "\n", + "
\n", + "**dA_prev[1,1] =** \n", + "\n", + "[[ 0. 0. ]
\n", + " [ 5.05844394 -1.68282702]
\n", + " [ 0. 0. ]]\n", + "
\n", + "\n", + "mode = average\n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "**mean of dA =**\n", + "\n", + "\n", + "0.145713902729\n", + "\n", + "
\n", + "**dA_prev[1,1] =** \n", + "\n", + "[[ 0.08485462 0.2787552 ]
\n", + " [ 1.26461098 -0.25749373]
\n", + " [ 1.17975636 -0.53624893]]\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Congratulations !\n", + "\n", + "Congratulation on completing this assignment. You now understand how convolutional neural networks work. You have implemented all the building blocks of a neural network. In the next assignment you will implement a ConvNet using TensorFlow." + ] + } + ], + "metadata": { + "coursera": { + "course_slug": "convolutional-neural-networks", + "graded_item_id": "qO8ng", + "launcher_item_id": "7XDi8" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/cnn/cnn_report.pdf b/cnn/cnn_report.pdf new file mode 100644 index 0000000..082457b Binary files /dev/null and b/cnn/cnn_report.pdf differ diff --git a/cnn/cnn_utils.py b/cnn/cnn_utils.py new file mode 100644 index 0000000..4bdf418 --- /dev/null +++ b/cnn/cnn_utils.py @@ -0,0 +1,155 @@ +import math +import numpy as np +import h5py +import matplotlib.pyplot as plt +import tensorflow as tf +from tensorflow.python.framework import ops + +def load_dataset(): + train_dataset = h5py.File('datasets/train_signs.h5', "r") + train_set_x_orig = np.array(train_dataset["train_set_x"][:]) # your train set features + train_set_y_orig = np.array(train_dataset["train_set_y"][:]) # your train set labels + + test_dataset = h5py.File('datasets/test_signs.h5', "r") + test_set_x_orig = np.array(test_dataset["test_set_x"][:]) # your test set features + test_set_y_orig = np.array(test_dataset["test_set_y"][:]) # your test set labels + + classes = np.array(test_dataset["list_classes"][:]) # the list of classes + + train_set_y_orig = train_set_y_orig.reshape((1, train_set_y_orig.shape[0])) + test_set_y_orig = test_set_y_orig.reshape((1, test_set_y_orig.shape[0])) + + return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes + + +def random_mini_batches(X, Y, mini_batch_size = 64, seed = 0): + """ + Creates a list of random minibatches from (X, Y) + + Arguments: + X -- input data, of shape (input size, number of examples) (m, Hi, Wi, Ci) + Y -- true "label" vector (containing 0 if cat, 1 if non-cat), of shape (1, number of examples) (m, n_y) + mini_batch_size - size of the mini-batches, integer + seed -- this is only for the purpose of grading, so that you're "random minibatches are the same as ours. + + Returns: + mini_batches -- list of synchronous (mini_batch_X, mini_batch_Y) + """ + + m = X.shape[0] # number of training examples + mini_batches = [] + np.random.seed(seed) + + # Step 1: Shuffle (X, Y) + permutation = list(np.random.permutation(m)) + shuffled_X = X[permutation,:,:,:] + shuffled_Y = Y[permutation,:] + + # Step 2: Partition (shuffled_X, shuffled_Y). Minus the end case. + num_complete_minibatches = math.floor(m/mini_batch_size) # number of mini batches of size mini_batch_size in your partitionning + for k in range(0, num_complete_minibatches): + mini_batch_X = shuffled_X[k * mini_batch_size : k * mini_batch_size + mini_batch_size,:,:,:] + mini_batch_Y = shuffled_Y[k * mini_batch_size : k * mini_batch_size + mini_batch_size,:] + mini_batch = (mini_batch_X, mini_batch_Y) + mini_batches.append(mini_batch) + + # Handling the end case (last mini-batch < mini_batch_size) + if m % mini_batch_size != 0: + mini_batch_X = shuffled_X[num_complete_minibatches * mini_batch_size : m,:,:,:] + mini_batch_Y = shuffled_Y[num_complete_minibatches * mini_batch_size : m,:] + mini_batch = (mini_batch_X, mini_batch_Y) + mini_batches.append(mini_batch) + + return mini_batches + + +def convert_to_one_hot(Y, C): + Y = np.eye(C)[Y.reshape(-1)].T + return Y + + +def forward_propagation_for_predict(X, parameters): + """ + Implements the forward propagation for the model: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX + + Arguments: + X -- input dataset placeholder, of shape (input size, number of examples) + parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3" + the shapes are given in initialize_parameters + + Returns: + Z3 -- the output of the last LINEAR unit + """ + + # Retrieve the parameters from the dictionary "parameters" + W1 = parameters['W1'] + b1 = parameters['b1'] + W2 = parameters['W2'] + b2 = parameters['b2'] + W3 = parameters['W3'] + b3 = parameters['b3'] + # Numpy Equivalents: + Z1 = tf.add(tf.matmul(W1, X), b1) # Z1 = np.dot(W1, X) + b1 + A1 = tf.nn.relu(Z1) # A1 = relu(Z1) + Z2 = tf.add(tf.matmul(W2, A1), b2) # Z2 = np.dot(W2, a1) + b2 + A2 = tf.nn.relu(Z2) # A2 = relu(Z2) + Z3 = tf.add(tf.matmul(W3, A2), b3) # Z3 = np.dot(W3,Z2) + b3 + + return Z3 + +def predict(X, parameters): + + W1 = tf.convert_to_tensor(parameters["W1"]) + b1 = tf.convert_to_tensor(parameters["b1"]) + W2 = tf.convert_to_tensor(parameters["W2"]) + b2 = tf.convert_to_tensor(parameters["b2"]) + W3 = tf.convert_to_tensor(parameters["W3"]) + b3 = tf.convert_to_tensor(parameters["b3"]) + + params = {"W1": W1, + "b1": b1, + "W2": W2, + "b2": b2, + "W3": W3, + "b3": b3} + + x = tf.placeholder("float", [12288, 1]) + + z3 = forward_propagation_for_predict(x, params) + p = tf.argmax(z3) + + sess = tf.Session() + prediction = sess.run(p, feed_dict = {x: X}) + + return prediction + +#def predict(X, parameters): +# +# W1 = tf.convert_to_tensor(parameters["W1"]) +# b1 = tf.convert_to_tensor(parameters["b1"]) +# W2 = tf.convert_to_tensor(parameters["W2"]) +# b2 = tf.convert_to_tensor(parameters["b2"]) +## W3 = tf.convert_to_tensor(parameters["W3"]) +## b3 = tf.convert_to_tensor(parameters["b3"]) +# +## params = {"W1": W1, +## "b1": b1, +## "W2": W2, +## "b2": b2, +## "W3": W3, +## "b3": b3} +# +# params = {"W1": W1, +# "b1": b1, +# "W2": W2, +# "b2": b2} +# +# x = tf.placeholder("float", [12288, 1]) +# +# z3 = forward_propagation(x, params) +# p = tf.argmax(z3) +# +# with tf.Session() as sess: +# prediction = sess.run(p, feed_dict = {x: X}) +# +# return prediction \ No newline at end of file diff --git a/cnn/datasets/test_signs.h5 b/cnn/datasets/test_signs.h5 new file mode 100644 index 0000000..ac34131 Binary files /dev/null and b/cnn/datasets/test_signs.h5 differ diff --git a/cnn/datasets/train_signs.h5 b/cnn/datasets/train_signs.h5 new file mode 100644 index 0000000..15904fb Binary files /dev/null and b/cnn/datasets/train_signs.h5 differ diff --git a/cnn/images/Convolution_schematic.gif b/cnn/images/Convolution_schematic.gif new file mode 100644 index 0000000..d8c73dc Binary files /dev/null and b/cnn/images/Convolution_schematic.gif differ diff --git a/cnn/images/PAD.png b/cnn/images/PAD.png new file mode 100644 index 0000000..883ad2d Binary files /dev/null and b/cnn/images/PAD.png differ diff --git a/cnn/images/SIGNS.png b/cnn/images/SIGNS.png new file mode 100644 index 0000000..abba7c4 Binary files /dev/null and b/cnn/images/SIGNS.png differ diff --git a/cnn/images/a_pool.png b/cnn/images/a_pool.png new file mode 100644 index 0000000..93c2f33 Binary files /dev/null and b/cnn/images/a_pool.png differ diff --git a/cnn/images/ave-pool.png b/cnn/images/ave-pool.png new file mode 100644 index 0000000..eb2704e Binary files /dev/null and b/cnn/images/ave-pool.png differ diff --git a/cnn/images/ave_pool1.png b/cnn/images/ave_pool1.png new file mode 100644 index 0000000..5e36230 Binary files /dev/null and b/cnn/images/ave_pool1.png differ diff --git a/cnn/images/average_pool.png b/cnn/images/average_pool.png new file mode 100644 index 0000000..d60c6aa Binary files /dev/null and b/cnn/images/average_pool.png differ diff --git a/cnn/images/conv.png b/cnn/images/conv.png new file mode 100644 index 0000000..0ae8eef Binary files /dev/null and b/cnn/images/conv.png differ diff --git a/cnn/images/conv1.png b/cnn/images/conv1.png new file mode 100644 index 0000000..fd0e1a8 Binary files /dev/null and b/cnn/images/conv1.png differ diff --git a/cnn/images/conv_kiank.mp4 b/cnn/images/conv_kiank.mp4 new file mode 100644 index 0000000..c550f75 Binary files /dev/null and b/cnn/images/conv_kiank.mp4 differ diff --git a/cnn/images/conv_nn.png b/cnn/images/conv_nn.png new file mode 100644 index 0000000..e90a9de Binary files /dev/null and b/cnn/images/conv_nn.png differ diff --git a/cnn/images/max_pool.png b/cnn/images/max_pool.png new file mode 100644 index 0000000..17c82ba Binary files /dev/null and b/cnn/images/max_pool.png differ diff --git a/cnn/images/max_pool1.png b/cnn/images/max_pool1.png new file mode 100644 index 0000000..36acdb5 Binary files /dev/null and b/cnn/images/max_pool1.png differ diff --git a/cnn/images/model.png b/cnn/images/model.png new file mode 100644 index 0000000..84dc475 Binary files /dev/null and b/cnn/images/model.png differ diff --git a/cnn/images/thumbs_up.jpg b/cnn/images/thumbs_up.jpg new file mode 100644 index 0000000..64ab7dc Binary files /dev/null and b/cnn/images/thumbs_up.jpg differ diff --git a/cnn/images/vert_horiz_kiank.png b/cnn/images/vert_horiz_kiank.png new file mode 100644 index 0000000..15e28bb Binary files /dev/null and b/cnn/images/vert_horiz_kiank.png differ diff --git a/cnn/my_signs_tf.ipynb b/cnn/my_signs_tf.ipynb new file mode 100644 index 0000000..02a4994 --- /dev/null +++ b/cnn/my_signs_tf.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import tensorflow as tf\n", + "import h5py\n", + "import matplotlib.pyplot as plt\n", + "from tensorflow.python.framework import ops" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "train_data=h5py.File('datasets/train_signs.h5', 'r')\n", + "test_data=h5py.File('datasets/test_signs.h5', 'r')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "x_train=np.array(train_data['train_set_x'])/255\n", + "y_train=np.array(train_data['train_set_y'])\n", + "\n", + "x_test=np.array(test_data['test_set_x'])/255\n", + "y_test=np.array(test_data['test_set_y'])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "classes= np.array(train_data['list_classes'])\n", + "M=np.eye(classes.shape[0])\n", + "def one_hot(Y,classes=classes):\n", + " Y_hot=np.zeros((Y.shape[0], classes.shape[0]))\n", + " for i in range(Y.shape[0]):\n", + " Y_hot[i]=M[Y[i]]\n", + " return Y_hot" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "y_train=one_hot(y_train, classes)\n", + "y_test=one_hot(y_test, classes)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y_train.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def forward_prop(X,parameters):\n", + " W1=parameters['W1']\n", + " W2=parameters['W2']\n", + " Z1=tf.nn.conv2d(X, filter=W1, strides=[1,1,1,1], padding='SAME')\n", + " A1=tf.nn.relu(Z1)\n", + " A1=tf.nn.max_pool(A1,ksize=[1,8,8,1],strides=[1,8,8,1], padding='SAME')\n", + " Z2=tf.nn.conv2d(A1, filter=W2, strides=[1,1,1,1], padding='SAME')\n", + " A2=tf.nn.relu(Z2)\n", + " A2=tf.nn.max_pool(A2, ksize=[1,4,4,1], strides=[1,4,4,1], padding='SAME')\n", + "\n", + " F=tf.contrib.layers.flatten(A2)\n", + " Z3=tf.contrib.layers.fully_connected(F,6, activation_fn=None)\n", + " return Z3" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "ops.reset_default_graph()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def cost(Z3,Y):\n", + " return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y)) " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "X=tf.placeholder(dtype=tf.float32, shape=[None,64,64,3])\n", + "Y=tf.placeholder(dtype=tf.float32, shape=[None,6])\n", + "\n", + "tf.set_random_seed(1)\n", + "W1=tf.get_variable('W1', shape=[4,4,3,8], initializer=tf.contrib.layers.xavier_initializer(seed=0))\n", + "W2=tf.get_variable('W2', shape=[2,2,8,16], initializer=tf.contrib.layers.xavier_initializer(seed=0))\n", + "parameters={'W1':W1, 'W2':W2}\n", + "\n", + "Z3=forward_prop(X,parameters)\n", + "cost=cost(Z3,Y)\n", + "optimizer=tf.train.AdamOptimizer(learning_rate=0.009).minimize(cost)\n", + "init=tf.global_variables_initializer()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tensor(\"Mean_3:0\", shape=(), dtype=float32)\n", + "Train Accuracy: 0.4074074\n", + "Test Accuracy: 0.40833333\n" + ] + } + ], + "source": [ + "scores=[]\n", + "with tf.Session() as sess:\n", + " sess.run(init)\n", + " for i in range (50):\n", + " _,score=sess.run([optimizer,cost],{X:x_train, Y:y_train})\n", + " #print(f'Score: {score}, iterration: {i}')\n", + " scores.append(score)\n", + " predict_op = tf.argmax(Z3, 1)\n", + " correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))\n", + " \n", + " # Calculate accuracy on the test set\n", + " accuracy = tf.reduce_mean(tf.cast(correct_prediction, \"float\"))\n", + " print(accuracy)\n", + " train_accuracy = accuracy.eval({X: x_train, Y: y_train})\n", + " test_accuracy = accuracy.eval({X: x_test, Y: y_test})\n", + " print(\"Train Accuracy:\", train_accuracy)\n", + " print(\"Test Accuracy:\", test_accuracy)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(scores)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Tensor(\"Mean_2:0\", shape=(), dtype=float32)\n" + ] + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/face_recognition_with_ORL/Face_identification_problem.docx b/face_recognition_with_ORL/Face_identification_problem.docx new file mode 100644 index 0000000..0305198 Binary files /dev/null and b/face_recognition_with_ORL/Face_identification_problem.docx differ diff --git a/optimization_algorithms/Optimization methods.ipynb b/optimization_algorithms/Optimization methods.ipynb new file mode 100644 index 0000000..13aedae --- /dev/null +++ b/optimization_algorithms/Optimization methods.ipynb @@ -0,0 +1,1383 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Optimization Methods\n", + "\n", + "Until now, you've always used Gradient Descent to update the parameters and minimize the cost. In this notebook, you will learn more advanced optimization methods that can speed up learning and perhaps even get you to a better final value for the cost function. Having a good optimization algorithm can be the difference between waiting days vs. just a few hours to get a good result. \n", + "\n", + "Gradient descent goes \"downhill\" on a cost function $J$. Think of it as trying to do this: \n", + "\n", + "
**Figure 1** : **Minimizing the cost is like finding the lowest point in a hilly landscape**
At each step of the training, you update your parameters following a certain direction to try to get to the lowest possible point.
\n", + "\n", + "**Notations**: As usual, $\\frac{\\partial J}{\\partial a } = $ `da` for any variable `a`.\n", + "\n", + "To get started, run the following code to import the libraries you will need." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import scipy.io\n", + "import math\n", + "import sklearn\n", + "import sklearn.datasets\n", + "\n", + "from opt_utils import load_params_and_grads, initialize_parameters, forward_propagation, backward_propagation\n", + "from opt_utils import compute_cost, predict, predict_dec, plot_decision_boundary, load_dataset\n", + "from testCases import *\n", + "\n", + "%matplotlib inline\n", + "plt.rcParams['figure.figsize'] = (7.0, 4.0) # set default size of plots\n", + "plt.rcParams['image.interpolation'] = 'nearest'\n", + "plt.rcParams['image.cmap'] = 'gray'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1 - Gradient Descent\n", + "\n", + "A simple optimization method in machine learning is gradient descent (GD). When you take gradient steps with respect to all $m$ examples on each step, it is also called Batch Gradient Descent. \n", + "\n", + "**Warm-up exercise**: Implement the gradient descent update rule. The gradient descent rule is, for $l = 1, ..., L$: \n", + "$$ W^{[l]} = W^{[l]} - \\alpha \\text{ } dW^{[l]} \\tag{1}$$\n", + "$$ b^{[l]} = b^{[l]} - \\alpha \\text{ } db^{[l]} \\tag{2}$$\n", + "\n", + "where L is the number of layers and $\\alpha$ is the learning rate. All parameters should be stored in the `parameters` dictionary. Note that the iterator `l` starts at 0 in the `for` loop while the first parameters are $W^{[1]}$ and $b^{[1]}$. You need to shift `l` to `l+1` when coding." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: update_parameters_with_gd\n", + "\n", + "def update_parameters_with_gd(parameters, grads, learning_rate):\n", + " \"\"\"\n", + " Update parameters using one step of gradient descent\n", + " \n", + " Arguments:\n", + " parameters -- python dictionary containing your parameters to be updated:\n", + " parameters['W' + str(l)] = Wl\n", + " parameters['b' + str(l)] = bl\n", + " grads -- python dictionary containing your gradients to update each parameters:\n", + " grads['dW' + str(l)] = dWl\n", + " grads['db' + str(l)] = dbl\n", + " learning_rate -- the learning rate, scalar.\n", + " \n", + " Returns:\n", + " parameters -- python dictionary containing your updated parameters \n", + " \"\"\"\n", + "\n", + " L = len(parameters) // 2 # number of layers in the neural networks\n", + "\n", + " # Update rule for each parameter\n", + " for l in range(L):\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " parameters[\"W\" + str(l+1)] = None\n", + " parameters[\"b\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + " \n", + " return parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "scrolled": true + }, + "outputs": [], + "source": [ + "parameters, grads, learning_rate = update_parameters_with_gd_test_case()\n", + "\n", + "parameters = update_parameters_with_gd(parameters, grads, learning_rate)\n", + "print(\"W1 = \" + str(parameters[\"W1\"]))\n", + "print(\"b1 = \" + str(parameters[\"b1\"]))\n", + "print(\"W2 = \" + str(parameters[\"W2\"]))\n", + "print(\"b2 = \" + str(parameters[\"b2\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
**W1** [[ 1.63535156 -0.62320365 -0.53718766]\n", + " [-1.07799357 0.85639907 -2.29470142]]
**b1** [[ 1.74604067]\n", + " [-0.75184921]]
**W2** [[ 0.32171798 -0.25467393 1.46902454]\n", + " [-2.05617317 -0.31554548 -0.3756023 ]\n", + " [ 1.1404819 -1.09976462 -0.1612551 ]]
**b2** [[-0.88020257]\n", + " [ 0.02561572]\n", + " [ 0.57539477]]
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A variant of this is Stochastic Gradient Descent (SGD), which is equivalent to mini-batch gradient descent where each mini-batch has just 1 example. The update rule that you have just implemented does not change. What changes is that you would be computing gradients on just one training example at a time, rather than on the whole training set. The code examples below illustrate the difference between stochastic gradient descent and (batch) gradient descent. \n", + "\n", + "- **(Batch) Gradient Descent**:\n", + "\n", + "``` python\n", + "X = data_input\n", + "Y = labels\n", + "parameters = initialize_parameters(layers_dims)\n", + "for i in range(0, num_iterations):\n", + " # Forward propagation\n", + " a, caches = forward_propagation(X, parameters)\n", + " # Compute cost.\n", + " cost = compute_cost(a, Y)\n", + " # Backward propagation.\n", + " grads = backward_propagation(a, caches, parameters)\n", + " # Update parameters.\n", + " parameters = update_parameters(parameters, grads)\n", + " \n", + "```\n", + "\n", + "- **Stochastic Gradient Descent**:\n", + "\n", + "```python\n", + "X = data_input\n", + "Y = labels\n", + "parameters = initialize_parameters(layers_dims)\n", + "for i in range(0, num_iterations):\n", + " for j in range(0, m):\n", + " # Forward propagation\n", + " a, caches = forward_propagation(X[:,j], parameters)\n", + " # Compute cost\n", + " cost = compute_cost(a, Y[:,j])\n", + " # Backward propagation\n", + " grads = backward_propagation(a, caches, parameters)\n", + " # Update parameters.\n", + " parameters = update_parameters(parameters, grads)\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In Stochastic Gradient Descent, you use only 1 training example before updating the gradients. When the training set is large, SGD can be faster. But the parameters will \"oscillate\" toward the minimum rather than converge smoothly. Here is an illustration of this: \n", + "\n", + "\n", + "
**Figure 1** : **SGD vs GD**
\"+\" denotes a minimum of the cost. SGD leads to many oscillations to reach convergence. But each step is a lot faster to compute for SGD than for GD, as it uses only one training example (vs. the whole batch for GD).
\n", + "\n", + "**Note** also that implementing SGD requires 3 for-loops in total:\n", + "1. Over the number of iterations\n", + "2. Over the $m$ training examples\n", + "3. Over the layers (to update all parameters, from $(W^{[1]},b^{[1]})$ to $(W^{[L]},b^{[L]})$)\n", + "\n", + "In practice, you'll often get faster results if you do not use neither the whole training set, nor only one training example, to perform each update. Mini-batch gradient descent uses an intermediate number of examples for each step. With mini-batch gradient descent, you loop over the mini-batches instead of looping over individual training examples.\n", + "\n", + "\n", + "
**Figure 2** : **SGD vs Mini-Batch GD**
\"+\" denotes a minimum of the cost. Using mini-batches in your optimization algorithm often leads to faster optimization.
\n", + "\n", + "\n", + "**What you should remember**:\n", + "- The difference between gradient descent, mini-batch gradient descent and stochastic gradient descent is the number of examples you use to perform one update step.\n", + "- You have to tune a learning rate hyperparameter $\\alpha$.\n", + "- With a well-turned mini-batch size, usually it outperforms either gradient descent or stochastic gradient descent (particularly when the training set is large)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2 - Mini-Batch Gradient descent\n", + "\n", + "Let's learn how to build mini-batches from the training set (X, Y).\n", + "\n", + "There are two steps:\n", + "- **Shuffle**: Create a shuffled version of the training set (X, Y) as shown below. Each column of X and Y represents a training example. Note that the random shuffling is done synchronously between X and Y. Such that after the shuffling the $i^{th}$ column of X is the example corresponding to the $i^{th}$ label in Y. The shuffling step ensures that examples will be split randomly into different mini-batches. \n", + "\n", + "\n", + "\n", + "- **Partition**: Partition the shuffled (X, Y) into mini-batches of size `mini_batch_size` (here 64). Note that the number of training examples is not always divisible by `mini_batch_size`. The last mini batch might be smaller, but you don't need to worry about this. When the final mini-batch is smaller than the full `mini_batch_size`, it will look like this: \n", + "\n", + "\n", + "\n", + "**Exercise**: Implement `random_mini_batches`. We coded the shuffling part for you. To help you with the partitioning step, we give you the following code that selects the indexes for the $1^{st}$ and $2^{nd}$ mini-batches:\n", + "```python\n", + "first_mini_batch_X = shuffled_X[:, 0 : mini_batch_size]\n", + "second_mini_batch_X = shuffled_X[:, mini_batch_size : 2 * mini_batch_size]\n", + "...\n", + "```\n", + "\n", + "Note that the last mini-batch might end up smaller than `mini_batch_size=64`. Let $\\lfloor s \\rfloor$ represents $s$ rounded down to the nearest integer (this is `math.floor(s)` in Python). If the total number of examples is not a multiple of `mini_batch_size=64` then there will be $\\lfloor \\frac{m}{mini\\_batch\\_size}\\rfloor$ mini-batches with a full 64 examples, and the number of examples in the final mini-batch will be ($m-mini_\\_batch_\\_size \\times \\lfloor \\frac{m}{mini\\_batch\\_size}\\rfloor$). " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: random_mini_batches\n", + "\n", + "def random_mini_batches(X, Y, mini_batch_size = 64, seed = 0):\n", + " \"\"\"\n", + " Creates a list of random minibatches from (X, Y)\n", + " \n", + " Arguments:\n", + " X -- input data, of shape (input size, number of examples)\n", + " Y -- true \"label\" vector (1 for blue dot / 0 for red dot), of shape (1, number of examples)\n", + " mini_batch_size -- size of the mini-batches, integer\n", + " \n", + " Returns:\n", + " mini_batches -- list of synchronous (mini_batch_X, mini_batch_Y)\n", + " \"\"\"\n", + " \n", + " np.random.seed(seed) # To make your \"random\" minibatches the same as ours\n", + " m = X.shape[1] # number of training examples\n", + " mini_batches = []\n", + " \n", + " # Step 1: Shuffle (X, Y)\n", + " permutation = list(np.random.permutation(m))\n", + " shuffled_X = X[:, permutation]\n", + " shuffled_Y = Y[:, permutation].reshape((1,m))\n", + "\n", + " # Step 2: Partition (shuffled_X, shuffled_Y). Minus the end case.\n", + " num_complete_minibatches = math.floor(m/mini_batch_size) # number of mini batches of size mini_batch_size in your partitionning\n", + " for k in range(0, num_complete_minibatches):\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " mini_batch_X = None\n", + " mini_batch_Y = None\n", + " ### END CODE HERE ###\n", + " mini_batch = (mini_batch_X, mini_batch_Y)\n", + " mini_batches.append(mini_batch)\n", + " \n", + " # Handling the end case (last mini-batch < mini_batch_size)\n", + " if m % mini_batch_size != 0:\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " mini_batch_X = None\n", + " mini_batch_Y = None\n", + " ### END CODE HERE ###\n", + " mini_batch = (mini_batch_X, mini_batch_Y)\n", + " mini_batches.append(mini_batch)\n", + " \n", + " return mini_batches" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "X_assess, Y_assess, mini_batch_size = random_mini_batches_test_case()\n", + "mini_batches = random_mini_batches(X_assess, Y_assess, mini_batch_size)\n", + "\n", + "print (\"shape of the 1st mini_batch_X: \" + str(mini_batches[0][0].shape))\n", + "print (\"shape of the 2nd mini_batch_X: \" + str(mini_batches[1][0].shape))\n", + "print (\"shape of the 3rd mini_batch_X: \" + str(mini_batches[2][0].shape))\n", + "print (\"shape of the 1st mini_batch_Y: \" + str(mini_batches[0][1].shape))\n", + "print (\"shape of the 2nd mini_batch_Y: \" + str(mini_batches[1][1].shape)) \n", + "print (\"shape of the 3rd mini_batch_Y: \" + str(mini_batches[2][1].shape))\n", + "print (\"mini batch sanity check: \" + str(mini_batches[0][0][0][0:3]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
**shape of the 1st mini_batch_X** (12288, 64)
**shape of the 2nd mini_batch_X** (12288, 64)
**shape of the 3rd mini_batch_X** (12288, 20)
**shape of the 1st mini_batch_Y** (1, 64)
**shape of the 2nd mini_batch_Y** (1, 64)
**shape of the 3rd mini_batch_Y** (1, 20)
**mini batch sanity check** [ 0.90085595 -0.7612069 0.2344157 ]
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "**What you should remember**:\n", + "- Shuffling and Partitioning are the two steps required to build mini-batches\n", + "- Powers of two are often chosen to be the mini-batch size, e.g., 16, 32, 64, 128." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3 - Momentum\n", + "\n", + "Because mini-batch gradient descent makes a parameter update after seeing just a subset of examples, the direction of the update has some variance, and so the path taken by mini-batch gradient descent will \"oscillate\" toward convergence. Using momentum can reduce these oscillations. \n", + "\n", + "Momentum takes into account the past gradients to smooth out the update. We will store the 'direction' of the previous gradients in the variable $v$. Formally, this will be the exponentially weighted average of the gradient on previous steps. You can also think of $v$ as the \"velocity\" of a ball rolling downhill, building up speed (and momentum) according to the direction of the gradient/slope of the hill. \n", + "\n", + "\n", + "
**Figure 3**: The red arrows shows the direction taken by one step of mini-batch gradient descent with momentum. The blue points show the direction of the gradient (with respect to the current mini-batch) on each step. Rather than just following the gradient, we let the gradient influence $v$ and then take a step in the direction of $v$.
\n", + "\n", + "\n", + "**Exercise**: Initialize the velocity. The velocity, $v$, is a python dictionary that needs to be initialized with arrays of zeros. Its keys are the same as those in the `grads` dictionary, that is:\n", + "for $l =1,...,L$:\n", + "```python\n", + "v[\"dW\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"W\" + str(l+1)])\n", + "v[\"db\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"b\" + str(l+1)])\n", + "```\n", + "**Note** that the iterator l starts at 0 in the for loop while the first parameters are v[\"dW1\"] and v[\"db1\"] (that's a \"one\" on the superscript). This is why we are shifting l to l+1 in the `for` loop." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: initialize_velocity\n", + "\n", + "def initialize_velocity(parameters):\n", + " \"\"\"\n", + " Initializes the velocity as a python dictionary with:\n", + " - keys: \"dW1\", \"db1\", ..., \"dWL\", \"dbL\" \n", + " - values: numpy arrays of zeros of the same shape as the corresponding gradients/parameters.\n", + " Arguments:\n", + " parameters -- python dictionary containing your parameters.\n", + " parameters['W' + str(l)] = Wl\n", + " parameters['b' + str(l)] = bl\n", + " \n", + " Returns:\n", + " v -- python dictionary containing the current velocity.\n", + " v['dW' + str(l)] = velocity of dWl\n", + " v['db' + str(l)] = velocity of dbl\n", + " \"\"\"\n", + " \n", + " L = len(parameters) // 2 # number of layers in the neural networks\n", + " v = {}\n", + " \n", + " # Initialize velocity\n", + " for l in range(L):\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " v[\"dW\" + str(l+1)] = None\n", + " v[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + " \n", + " return v" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "parameters = initialize_velocity_test_case()\n", + "\n", + "v = initialize_velocity(parameters)\n", + "print(\"v[\\\"dW1\\\"] = \" + str(v[\"dW1\"]))\n", + "print(\"v[\\\"db1\\\"] = \" + str(v[\"db1\"]))\n", + "print(\"v[\\\"dW2\\\"] = \" + str(v[\"dW2\"]))\n", + "print(\"v[\\\"db2\\\"] = \" + str(v[\"db2\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
**v[\"dW1\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**v[\"db1\"]** [[ 0.]\n", + " [ 0.]]
**v[\"dW2\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**v[\"db2\"]** [[ 0.]\n", + " [ 0.]\n", + " [ 0.]]
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Exercise**: Now, implement the parameters update with momentum. The momentum update rule is, for $l = 1, ..., L$: \n", + "\n", + "$$ \\begin{cases}\n", + "v_{dW^{[l]}} = \\beta v_{dW^{[l]}} + (1 - \\beta) dW^{[l]} \\\\\n", + "W^{[l]} = W^{[l]} - \\alpha v_{dW^{[l]}}\n", + "\\end{cases}\\tag{3}$$\n", + "\n", + "$$\\begin{cases}\n", + "v_{db^{[l]}} = \\beta v_{db^{[l]}} + (1 - \\beta) db^{[l]} \\\\\n", + "b^{[l]} = b^{[l]} - \\alpha v_{db^{[l]}} \n", + "\\end{cases}\\tag{4}$$\n", + "\n", + "where L is the number of layers, $\\beta$ is the momentum and $\\alpha$ is the learning rate. All parameters should be stored in the `parameters` dictionary. Note that the iterator `l` starts at 0 in the `for` loop while the first parameters are $W^{[1]}$ and $b^{[1]}$ (that's a \"one\" on the superscript). So you will need to shift `l` to `l+1` when coding." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: update_parameters_with_momentum\n", + "\n", + "def update_parameters_with_momentum(parameters, grads, v, beta, learning_rate):\n", + " \"\"\"\n", + " Update parameters using Momentum\n", + " \n", + " Arguments:\n", + " parameters -- python dictionary containing your parameters:\n", + " parameters['W' + str(l)] = Wl\n", + " parameters['b' + str(l)] = bl\n", + " grads -- python dictionary containing your gradients for each parameters:\n", + " grads['dW' + str(l)] = dWl\n", + " grads['db' + str(l)] = dbl\n", + " v -- python dictionary containing the current velocity:\n", + " v['dW' + str(l)] = ...\n", + " v['db' + str(l)] = ...\n", + " beta -- the momentum hyperparameter, scalar\n", + " learning_rate -- the learning rate, scalar\n", + " \n", + " Returns:\n", + " parameters -- python dictionary containing your updated parameters \n", + " v -- python dictionary containing your updated velocities\n", + " \"\"\"\n", + "\n", + " L = len(parameters) // 2 # number of layers in the neural networks\n", + " \n", + " # Momentum update for each parameter\n", + " for l in range(L):\n", + " \n", + " ### START CODE HERE ### (approx. 4 lines)\n", + " # compute velocities\n", + " v[\"dW\" + str(l+1)] = None\n", + " v[\"db\" + str(l+1)] = None\n", + " # update parameters\n", + " parameters[\"W\" + str(l+1)] = None\n", + " parameters[\"b\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + " \n", + " return parameters, v" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "parameters, grads, v = update_parameters_with_momentum_test_case()\n", + "\n", + "parameters, v = update_parameters_with_momentum(parameters, grads, v, beta = 0.9, learning_rate = 0.01)\n", + "print(\"W1 = \" + str(parameters[\"W1\"]))\n", + "print(\"b1 = \" + str(parameters[\"b1\"]))\n", + "print(\"W2 = \" + str(parameters[\"W2\"]))\n", + "print(\"b2 = \" + str(parameters[\"b2\"]))\n", + "print(\"v[\\\"dW1\\\"] = \" + str(v[\"dW1\"]))\n", + "print(\"v[\\\"db1\\\"] = \" + str(v[\"db1\"]))\n", + "print(\"v[\\\"dW2\\\"] = \" + str(v[\"dW2\"]))\n", + "print(\"v[\\\"db2\\\"] = \" + str(v[\"db2\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
**W1** [[ 1.62544598 -0.61290114 -0.52907334]\n", + " [-1.07347112 0.86450677 -2.30085497]]
**b1** [[ 1.74493465]\n", + " [-0.76027113]]
**W2** [[ 0.31930698 -0.24990073 1.4627996 ]\n", + " [-2.05974396 -0.32173003 -0.38320915]\n", + " [ 1.13444069 -1.0998786 -0.1713109 ]]
**b2** [[-0.87809283]\n", + " [ 0.04055394]\n", + " [ 0.58207317]]
**v[\"dW1\"]** [[-0.11006192 0.11447237 0.09015907]\n", + " [ 0.05024943 0.09008559 -0.06837279]]
**v[\"db1\"]** [[-0.01228902]\n", + " [-0.09357694]]
**v[\"dW2\"]** [[-0.02678881 0.05303555 -0.06916608]\n", + " [-0.03967535 -0.06871727 -0.08452056]\n", + " [-0.06712461 -0.00126646 -0.11173103]]
**v[\"db2\"]** [[ 0.02344157]\n", + " [ 0.16598022]\n", + " [ 0.07420442]]
\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "**Note** that:\n", + "- The velocity is initialized with zeros. So the algorithm will take a few iterations to \"build up\" velocity and start to take bigger steps.\n", + "- If $\\beta = 0$, then this just becomes standard gradient descent without momentum. \n", + "\n", + "**How do you choose $\\beta$?**\n", + "\n", + "- The larger the momentum $\\beta$ is, the smoother the update because the more we take the past gradients into account. But if $\\beta$ is too big, it could also smooth out the updates too much. \n", + "- Common values for $\\beta$ range from 0.8 to 0.999. If you don't feel inclined to tune this, $\\beta = 0.9$ is often a reasonable default. \n", + "- Tuning the optimal $\\beta$ for your model might need trying several values to see what works best in term of reducing the value of the cost function $J$. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "**What you should remember**:\n", + "- Momentum takes past gradients into account to smooth out the steps of gradient descent. It can be applied with batch gradient descent, mini-batch gradient descent or stochastic gradient descent.\n", + "- You have to tune a momentum hyperparameter $\\beta$ and a learning rate $\\alpha$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4 - Adam\n", + "\n", + "Adam is one of the most effective optimization algorithms for training neural networks. It combines ideas from RMSProp (described in lecture) and Momentum. \n", + "\n", + "**How does Adam work?**\n", + "1. It calculates an exponentially weighted average of past gradients, and stores it in variables $v$ (before bias correction) and $v^{corrected}$ (with bias correction). \n", + "2. It calculates an exponentially weighted average of the squares of the past gradients, and stores it in variables $s$ (before bias correction) and $s^{corrected}$ (with bias correction). \n", + "3. It updates parameters in a direction based on combining information from \"1\" and \"2\".\n", + "\n", + "The update rule is, for $l = 1, ..., L$: \n", + "\n", + "$$\\begin{cases}\n", + "v_{dW^{[l]}} = \\beta_1 v_{dW^{[l]}} + (1 - \\beta_1) \\frac{\\partial \\mathcal{J} }{ \\partial W^{[l]} } \\\\\n", + "v^{corrected}_{dW^{[l]}} = \\frac{v_{dW^{[l]}}}{1 - (\\beta_1)^t} \\\\\n", + "s_{dW^{[l]}} = \\beta_2 s_{dW^{[l]}} + (1 - \\beta_2) (\\frac{\\partial \\mathcal{J} }{\\partial W^{[l]} })^2 \\\\\n", + "s^{corrected}_{dW^{[l]}} = \\frac{s_{dW^{[l]}}}{1 - (\\beta_1)^t} \\\\\n", + "W^{[l]} = W^{[l]} - \\alpha \\frac{v^{corrected}_{dW^{[l]}}}{\\sqrt{s^{corrected}_{dW^{[l]}}} + \\varepsilon}\n", + "\\end{cases}$$\n", + "where:\n", + "- t counts the number of steps taken of Adam \n", + "- L is the number of layers\n", + "- $\\beta_1$ and $\\beta_2$ are hyperparameters that control the two exponentially weighted averages. \n", + "- $\\alpha$ is the learning rate\n", + "- $\\varepsilon$ is a very small number to avoid dividing by zero\n", + "\n", + "As usual, we will store all parameters in the `parameters` dictionary " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Exercise**: Initialize the Adam variables $v, s$ which keep track of the past information.\n", + "\n", + "**Instruction**: The variables $v, s$ are python dictionaries that need to be initialized with arrays of zeros. Their keys are the same as for `grads`, that is:\n", + "for $l = 1, ..., L$:\n", + "```python\n", + "v[\"dW\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"W\" + str(l+1)])\n", + "v[\"db\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"b\" + str(l+1)])\n", + "s[\"dW\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"W\" + str(l+1)])\n", + "s[\"db\" + str(l+1)] = ... #(numpy array of zeros with the same shape as parameters[\"b\" + str(l+1)])\n", + "\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: initialize_adam\n", + "\n", + "def initialize_adam(parameters) :\n", + " \"\"\"\n", + " Initializes v and s as two python dictionaries with:\n", + " - keys: \"dW1\", \"db1\", ..., \"dWL\", \"dbL\" \n", + " - values: numpy arrays of zeros of the same shape as the corresponding gradients/parameters.\n", + " \n", + " Arguments:\n", + " parameters -- python dictionary containing your parameters.\n", + " parameters[\"W\" + str(l)] = Wl\n", + " parameters[\"b\" + str(l)] = bl\n", + " \n", + " Returns: \n", + " v -- python dictionary that will contain the exponentially weighted average of the gradient.\n", + " v[\"dW\" + str(l)] = ...\n", + " v[\"db\" + str(l)] = ...\n", + " s -- python dictionary that will contain the exponentially weighted average of the squared gradient.\n", + " s[\"dW\" + str(l)] = ...\n", + " s[\"db\" + str(l)] = ...\n", + "\n", + " \"\"\"\n", + " \n", + " L = len(parameters) // 2 # number of layers in the neural networks\n", + " v = {}\n", + " s = {}\n", + " \n", + " # Initialize v, s. Input: \"parameters\". Outputs: \"v, s\".\n", + " for l in range(L):\n", + " ### START CODE HERE ### (approx. 4 lines)\n", + " v[\"dW\" + str(l+1)] = None\n", + " v[\"db\" + str(l+1)] = None\n", + " s[\"dW\" + str(l+1)] = None\n", + " s[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + " \n", + " return v, s" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "parameters = initialize_adam_test_case()\n", + "\n", + "v, s = initialize_adam(parameters)\n", + "print(\"v[\\\"dW1\\\"] = \" + str(v[\"dW1\"]))\n", + "print(\"v[\\\"db1\\\"] = \" + str(v[\"db1\"]))\n", + "print(\"v[\\\"dW2\\\"] = \" + str(v[\"dW2\"]))\n", + "print(\"v[\\\"db2\\\"] = \" + str(v[\"db2\"]))\n", + "print(\"s[\\\"dW1\\\"] = \" + str(s[\"dW1\"]))\n", + "print(\"s[\\\"db1\\\"] = \" + str(s[\"db1\"]))\n", + "print(\"s[\\\"dW2\\\"] = \" + str(s[\"dW2\"]))\n", + "print(\"s[\\\"db2\\\"] = \" + str(s[\"db2\"]))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
**v[\"dW1\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**v[\"db1\"]** [[ 0.]\n", + " [ 0.]]
**v[\"dW2\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**v[\"db2\"]** [[ 0.]\n", + " [ 0.]\n", + " [ 0.]]
**s[\"dW1\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**s[\"db1\"]** [[ 0.]\n", + " [ 0.]]
**s[\"dW2\"]** [[ 0. 0. 0.]\n", + " [ 0. 0. 0.]\n", + " [ 0. 0. 0.]]
**s[\"db2\"]** [[ 0.]\n", + " [ 0.]\n", + " [ 0.]]
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Exercise**: Now, implement the parameters update with Adam. Recall the general update rule is, for $l = 1, ..., L$: \n", + "\n", + "$$\\begin{cases}\n", + "v_{W^{[l]}} = \\beta_1 v_{W^{[l]}} + (1 - \\beta_1) \\frac{\\partial J }{ \\partial W^{[l]} } \\\\\n", + "v^{corrected}_{W^{[l]}} = \\frac{v_{W^{[l]}}}{1 - (\\beta_1)^t} \\\\\n", + "s_{W^{[l]}} = \\beta_2 s_{W^{[l]}} + (1 - \\beta_2) (\\frac{\\partial J }{\\partial W^{[l]} })^2 \\\\\n", + "s^{corrected}_{W^{[l]}} = \\frac{s_{W^{[l]}}}{1 - (\\beta_2)^t} \\\\\n", + "W^{[l]} = W^{[l]} - \\alpha \\frac{v^{corrected}_{W^{[l]}}}{\\sqrt{s^{corrected}_{W^{[l]}}}+\\varepsilon}\n", + "\\end{cases}$$\n", + "\n", + "\n", + "**Note** that the iterator `l` starts at 0 in the `for` loop while the first parameters are $W^{[1]}$ and $b^{[1]}$. You need to shift `l` to `l+1` when coding." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# GRADED FUNCTION: update_parameters_with_adam\n", + "\n", + "def update_parameters_with_adam(parameters, grads, v, s, t, learning_rate = 0.01,\n", + " beta1 = 0.9, beta2 = 0.999, epsilon = 1e-8):\n", + " \"\"\"\n", + " Update parameters using Adam\n", + " \n", + " Arguments:\n", + " parameters -- python dictionary containing your parameters:\n", + " parameters['W' + str(l)] = Wl\n", + " parameters['b' + str(l)] = bl\n", + " grads -- python dictionary containing your gradients for each parameters:\n", + " grads['dW' + str(l)] = dWl\n", + " grads['db' + str(l)] = dbl\n", + " v -- Adam variable, moving average of the first gradient, python dictionary\n", + " s -- Adam variable, moving average of the squared gradient, python dictionary\n", + " learning_rate -- the learning rate, scalar.\n", + " beta1 -- Exponential decay hyperparameter for the first moment estimates \n", + " beta2 -- Exponential decay hyperparameter for the second moment estimates \n", + " epsilon -- hyperparameter preventing division by zero in Adam updates\n", + "\n", + " Returns:\n", + " parameters -- python dictionary containing your updated parameters \n", + " v -- Adam variable, moving average of the first gradient, python dictionary\n", + " s -- Adam variable, moving average of the squared gradient, python dictionary\n", + " \"\"\"\n", + " \n", + " L = len(parameters) // 2 # number of layers in the neural networks\n", + " v_corrected = {} # Initializing first moment estimate, python dictionary\n", + " s_corrected = {} # Initializing second moment estimate, python dictionary\n", + " \n", + " # Perform Adam update on all parameters\n", + " for l in range(L):\n", + " # Moving average of the gradients. Inputs: \"v, grads, beta1\". Output: \"v\".\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " v[\"dW\" + str(l+1)] = None\n", + " v[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + "\n", + " # Compute bias-corrected first moment estimate. Inputs: \"v, beta1, t\". Output: \"v_corrected\".\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " v_corrected[\"dW\" + str(l+1)] = None\n", + " v_corrected[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + "\n", + " # Moving average of the squared gradients. Inputs: \"s, grads, beta2\". Output: \"s\".\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " s[\"dW\" + str(l+1)] = None\n", + " s[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + "\n", + " # Compute bias-corrected second raw moment estimate. Inputs: \"s, beta2, t\". Output: \"s_corrected\".\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " s_corrected[\"dW\" + str(l+1)] = None\n", + " s_corrected[\"db\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + "\n", + " # Update parameters. Inputs: \"parameters, learning_rate, v_corrected, s_corrected, epsilon\". Output: \"parameters\".\n", + " ### START CODE HERE ### (approx. 2 lines)\n", + " parameters[\"W\" + str(l+1)] = None\n", + " parameters[\"b\" + str(l+1)] = None\n", + " ### END CODE HERE ###\n", + "\n", + " return parameters, v, s" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "scrolled": false + }, + "outputs": [], + "source": [ + "parameters, grads, v, s = update_parameters_with_adam_test_case()\n", + "parameters, v, s = update_parameters_with_adam(parameters, grads, v, s, t = 2)\n", + "\n", + "print(\"W1 = \" + str(parameters[\"W1\"]))\n", + "print(\"b1 = \" + str(parameters[\"b1\"]))\n", + "print(\"W2 = \" + str(parameters[\"W2\"]))\n", + "print(\"b2 = \" + str(parameters[\"b2\"]))\n", + "print(\"v[\\\"dW1\\\"] = \" + str(v[\"dW1\"]))\n", + "print(\"v[\\\"db1\\\"] = \" + str(v[\"db1\"]))\n", + "print(\"v[\\\"dW2\\\"] = \" + str(v[\"dW2\"]))\n", + "print(\"v[\\\"db2\\\"] = \" + str(v[\"db2\"]))\n", + "print(\"s[\\\"dW1\\\"] = \" + str(s[\"dW1\"]))\n", + "print(\"s[\\\"db1\\\"] = \" + str(s[\"db1\"]))\n", + "print(\"s[\\\"dW2\\\"] = \" + str(s[\"dW2\"]))\n", + "print(\"s[\\\"db2\\\"] = \" + str(s[\"db2\"]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Expected Output**:\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
**W1** [[ 1.63178673 -0.61919778 -0.53561312]\n", + " [-1.08040999 0.85796626 -2.29409733]]
**b1** [[ 1.75225313]\n", + " [-0.75376553]]
**W2** [[ 0.32648046 -0.25681174 1.46954931]\n", + " [-2.05269934 -0.31497584 -0.37661299]\n", + " [ 1.14121081 -1.09245036 -0.16498684]]
**b2** [[-0.88529978]\n", + " [ 0.03477238]\n", + " [ 0.57537385]]
**v[\"dW1\"]** [[-0.11006192 0.11447237 0.09015907]\n", + " [ 0.05024943 0.09008559 -0.06837279]]
**v[\"db1\"]** [[-0.01228902]\n", + " [-0.09357694]]
**v[\"dW2\"]** [[-0.02678881 0.05303555 -0.06916608]\n", + " [-0.03967535 -0.06871727 -0.08452056]\n", + " [-0.06712461 -0.00126646 -0.11173103]]
**v[\"db2\"]** [[ 0.02344157]\n", + " [ 0.16598022]\n", + " [ 0.07420442]]
**s[\"dW1\"]** [[ 0.00121136 0.00131039 0.00081287]\n", + " [ 0.0002525 0.00081154 0.00046748]]
**s[\"db1\"]** [[ 1.51020075e-05]\n", + " [ 8.75664434e-04]]
**s[\"dW2\"]** [[ 7.17640232e-05 2.81276921e-04 4.78394595e-04]\n", + " [ 1.57413361e-04 4.72206320e-04 7.14372576e-04]\n", + " [ 4.50571368e-04 1.60392066e-07 1.24838242e-03]]
**s[\"db2\"]** [[ 5.49507194e-05]\n", + " [ 2.75494327e-03]\n", + " [ 5.50629536e-04]]
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You now have three working optimization algorithms (mini-batch gradient descent, Momentum, Adam). Let's implement a model with each of these optimizers and observe the difference." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5 - Model with different optimization algorithms\n", + "\n", + "Lets use the following \"moons\" dataset to test the different optimization methods. (The dataset is named \"moons\" because the data from each of the two classes looks a bit like a crescent-shaped moon.) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "train_X, train_Y = load_dataset()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We have already implemented a 3-layer neural network. You will train it with: \n", + "- Mini-batch **Gradient Descent**: it will call your function:\n", + " - `update_parameters_with_gd()`\n", + "- Mini-batch **Momentum**: it will call your functions:\n", + " - `initialize_velocity()` and `update_parameters_with_momentum()`\n", + "- Mini-batch **Adam**: it will call your functions:\n", + " - `initialize_adam()` and `update_parameters_with_adam()`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def model(X, Y, layers_dims, optimizer, learning_rate = 0.0007, mini_batch_size = 64, beta = 0.9,\n", + " beta1 = 0.9, beta2 = 0.999, epsilon = 1e-8, num_epochs = 10000, print_cost = True):\n", + " \"\"\"\n", + " 3-layer neural network model which can be run in different optimizer modes.\n", + " \n", + " Arguments:\n", + " X -- input data, of shape (2, number of examples)\n", + " Y -- true \"label\" vector (1 for blue dot / 0 for red dot), of shape (1, number of examples)\n", + " layers_dims -- python list, containing the size of each layer\n", + " learning_rate -- the learning rate, scalar.\n", + " mini_batch_size -- the size of a mini batch\n", + " beta -- Momentum hyperparameter\n", + " beta1 -- Exponential decay hyperparameter for the past gradients estimates \n", + " beta2 -- Exponential decay hyperparameter for the past squared gradients estimates \n", + " epsilon -- hyperparameter preventing division by zero in Adam updates\n", + " num_epochs -- number of epochs\n", + " print_cost -- True to print the cost every 1000 epochs\n", + "\n", + " Returns:\n", + " parameters -- python dictionary containing your updated parameters \n", + " \"\"\"\n", + "\n", + " L = len(layers_dims) # number of layers in the neural networks\n", + " costs = [] # to keep track of the cost\n", + " t = 0 # initializing the counter required for Adam update\n", + " seed = 10 # For grading purposes, so that your \"random\" minibatches are the same as ours\n", + " \n", + " # Initialize parameters\n", + " parameters = initialize_parameters(layers_dims)\n", + "\n", + " # Initialize the optimizer\n", + " if optimizer == \"gd\":\n", + " pass # no initialization required for gradient descent\n", + " elif optimizer == \"momentum\":\n", + " v = initialize_velocity(parameters)\n", + " elif optimizer == \"adam\":\n", + " v, s = initialize_adam(parameters)\n", + " \n", + " # Optimization loop\n", + " for i in range(num_epochs):\n", + " \n", + " # Define the random minibatches. We increment the seed to reshuffle differently the dataset after each epoch\n", + " seed = seed + 1\n", + " minibatches = random_mini_batches(X, Y, mini_batch_size, seed)\n", + "\n", + " for minibatch in minibatches:\n", + "\n", + " # Select a minibatch\n", + " (minibatch_X, minibatch_Y) = minibatch\n", + "\n", + " # Forward propagation\n", + " a3, caches = forward_propagation(minibatch_X, parameters)\n", + "\n", + " # Compute cost\n", + " cost = compute_cost(a3, minibatch_Y)\n", + "\n", + " # Backward propagation\n", + " grads = backward_propagation(minibatch_X, minibatch_Y, caches)\n", + "\n", + " # Update parameters\n", + " if optimizer == \"gd\":\n", + " parameters = update_parameters_with_gd(parameters, grads, learning_rate)\n", + " elif optimizer == \"momentum\":\n", + " parameters, v = update_parameters_with_momentum(parameters, grads, v, beta, learning_rate)\n", + " elif optimizer == \"adam\":\n", + " t = t + 1 # Adam counter\n", + " parameters, v, s = update_parameters_with_adam(parameters, grads, v, s,\n", + " t, learning_rate, beta1, beta2, epsilon)\n", + " \n", + " # Print the cost every 1000 epoch\n", + " if print_cost and i % 1000 == 0:\n", + " print (\"Cost after epoch %i: %f\" %(i, cost))\n", + " if print_cost and i % 100 == 0:\n", + " costs.append(cost)\n", + " \n", + " # plot the cost\n", + " plt.plot(costs)\n", + " plt.ylabel('cost')\n", + " plt.xlabel('epochs (per 100)')\n", + " plt.title(\"Learning rate = \" + str(learning_rate))\n", + " plt.show()\n", + "\n", + " return parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You will now run this 3 layer neural network with each of the 3 optimization methods.\n", + "\n", + "### 5.1 - Mini-batch Gradient descent\n", + "\n", + "Run the following code to see how the model does with mini-batch gradient descent." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "scrolled": false + }, + "outputs": [], + "source": [ + "# train 3-layer model\n", + "layers_dims = [train_X.shape[0], 5, 2, 1]\n", + "parameters = model(train_X, train_Y, layers_dims, optimizer = \"gd\")\n", + "\n", + "# Predict\n", + "predictions = predict(train_X, train_Y, parameters)\n", + "\n", + "# Plot decision boundary\n", + "plt.title(\"Model with Gradient Descent optimization\")\n", + "axes = plt.gca()\n", + "axes.set_xlim([-1.5,2.5])\n", + "axes.set_ylim([-1,1.5])\n", + "plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### 5.2 - Mini-batch gradient descent with momentum\n", + "\n", + "Run the following code to see how the model does with momentum. Because this example is relatively simple, the gains from using momemtum are small; but for more complex problems you might see bigger gains." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# train 3-layer model\n", + "layers_dims = [train_X.shape[0], 5, 2, 1]\n", + "parameters = model(train_X, train_Y, layers_dims, beta = 0.9, optimizer = \"momentum\")\n", + "\n", + "# Predict\n", + "predictions = predict(train_X, train_Y, parameters)\n", + "\n", + "# Plot decision boundary\n", + "plt.title(\"Model with Momentum optimization\")\n", + "axes = plt.gca()\n", + "axes.set_xlim([-1.5,2.5])\n", + "axes.set_ylim([-1,1.5])\n", + "plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### 5.3 - Mini-batch with Adam mode\n", + "\n", + "Run the following code to see how the model does with Adam." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# train 3-layer model\n", + "layers_dims = [train_X.shape[0], 5, 2, 1]\n", + "parameters = model(train_X, train_Y, layers_dims, optimizer = \"adam\")\n", + "\n", + "# Predict\n", + "predictions = predict(train_X, train_Y, parameters)\n", + "\n", + "# Plot decision boundary\n", + "plt.title(\"Model with Adam optimization\")\n", + "axes = plt.gca()\n", + "axes.set_xlim([-1.5,2.5])\n", + "axes.set_ylim([-1,1.5])\n", + "plot_decision_boundary(lambda x: predict_dec(parameters, x.T), train_X, train_Y)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "### 5.4 - Summary\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " **optimization method**\n", + " \n", + " **accuracy**\n", + " \n", + " **cost shape**\n", + "
\n", + " Gradient descent\n", + " \n", + " 79.7%\n", + " \n", + " oscillations\n", + "
\n", + " Momentum\n", + " \n", + " 79.7%\n", + " \n", + " oscillations\n", + "
\n", + " Adam\n", + " \n", + " 94%\n", + " \n", + " smoother\n", + "
\n", + "\n", + "Momentum usually helps, but given the small learning rate and the simplistic dataset, its impact is almost negligeable. Also, the huge oscillations you see in the cost come from the fact that some minibatches are more difficult thans others for the optimization algorithm.\n", + "\n", + "Adam on the other hand, clearly outperforms mini-batch gradient descent and Momentum. If you run the model for more epochs on this simple dataset, all three methods will lead to very good results. However, you've seen that Adam converges a lot faster.\n", + "\n", + "Some advantages of Adam include:\n", + "- Relatively low memory requirements (though higher than gradient descent and gradient descent with momentum) \n", + "- Usually works well even with little tuning of hyperparameters (except $\\alpha$)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "**References**:\n", + "\n", + "- Adam paper: https://arxiv.org/pdf/1412.6980.pdf" + ] + } + ], + "metadata": { + "coursera": { + "course_slug": "deep-neural-network", + "graded_item_id": "Ckiv2", + "launcher_item_id": "eNLYh" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.6" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/optimization_algorithms/datasets/data.mat b/optimization_algorithms/datasets/data.mat new file mode 100644 index 0000000..a0441ac Binary files /dev/null and b/optimization_algorithms/datasets/data.mat differ diff --git a/optimization_algorithms/images/Momentum.png b/optimization_algorithms/images/Momentum.png new file mode 100644 index 0000000..1052fb5 Binary files /dev/null and b/optimization_algorithms/images/Momentum.png differ diff --git a/optimization_algorithms/images/cost.jpg b/optimization_algorithms/images/cost.jpg new file mode 100644 index 0000000..91adc20 Binary files /dev/null and b/optimization_algorithms/images/cost.jpg differ diff --git a/optimization_algorithms/images/kiank_minibatch.png b/optimization_algorithms/images/kiank_minibatch.png new file mode 100644 index 0000000..382964b Binary files /dev/null and b/optimization_algorithms/images/kiank_minibatch.png differ diff --git a/optimization_algorithms/images/kiank_partition.png b/optimization_algorithms/images/kiank_partition.png new file mode 100644 index 0000000..792089f Binary files /dev/null and b/optimization_algorithms/images/kiank_partition.png differ diff --git a/optimization_algorithms/images/kiank_sgd.png b/optimization_algorithms/images/kiank_sgd.png new file mode 100644 index 0000000..99ab39e Binary files /dev/null and b/optimization_algorithms/images/kiank_sgd.png differ diff --git a/optimization_algorithms/images/kiank_shuffle.png b/optimization_algorithms/images/kiank_shuffle.png new file mode 100644 index 0000000..f01d117 Binary files /dev/null and b/optimization_algorithms/images/kiank_shuffle.png differ diff --git a/optimization_algorithms/images/opt1.gif b/optimization_algorithms/images/opt1.gif new file mode 100644 index 0000000..61db246 Binary files /dev/null and b/optimization_algorithms/images/opt1.gif differ diff --git a/optimization_algorithms/images/opt2.gif b/optimization_algorithms/images/opt2.gif new file mode 100644 index 0000000..e9d54d0 Binary files /dev/null and b/optimization_algorithms/images/opt2.gif differ diff --git a/optimization_algorithms/images/opt_momentum.png b/optimization_algorithms/images/opt_momentum.png new file mode 100644 index 0000000..dae5c87 Binary files /dev/null and b/optimization_algorithms/images/opt_momentum.png differ diff --git a/optimization_algorithms/opt_utils.py b/optimization_algorithms/opt_utils.py new file mode 100644 index 0000000..8440066 --- /dev/null +++ b/optimization_algorithms/opt_utils.py @@ -0,0 +1,260 @@ +import numpy as np +import matplotlib.pyplot as plt +import h5py +import scipy.io +import sklearn +import sklearn.datasets + +def sigmoid(x): + """ + Compute the sigmoid of x + + Arguments: + x -- A scalar or numpy array of any size. + + Return: + s -- sigmoid(x) + """ + s = 1/(1+np.exp(-x)) + return s + +def relu(x): + """ + Compute the relu of x + + Arguments: + x -- A scalar or numpy array of any size. + + Return: + s -- relu(x) + """ + s = np.maximum(0,x) + + return s + +def load_params_and_grads(seed=1): + np.random.seed(seed) + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + + dW1 = np.random.randn(2,3) + db1 = np.random.randn(2,1) + dW2 = np.random.randn(3,3) + db2 = np.random.randn(3,1) + + return W1, b1, W2, b2, dW1, db1, dW2, db2 + + +def initialize_parameters(layer_dims): + """ + Arguments: + layer_dims -- python array (list) containing the dimensions of each layer in our network + + Returns: + parameters -- python dictionary containing your parameters "W1", "b1", ..., "WL", "bL": + W1 -- weight matrix of shape (layer_dims[l], layer_dims[l-1]) + b1 -- bias vector of shape (layer_dims[l], 1) + Wl -- weight matrix of shape (layer_dims[l-1], layer_dims[l]) + bl -- bias vector of shape (1, layer_dims[l]) + + Tips: + - For example: the layer_dims for the "Planar Data classification model" would have been [2,2,1]. + This means W1's shape was (2,2), b1 was (1,2), W2 was (2,1) and b2 was (1,1). Now you have to generalize it! + - In the for loop, use parameters['W' + str(l)] to access Wl, where l is the iterative integer. + """ + + np.random.seed(3) + parameters = {} + L = len(layer_dims) # number of layers in the network + + for l in range(1, L): + parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1])* np.sqrt(2 / layer_dims[l-1]) + parameters['b' + str(l)] = np.zeros((layer_dims[l], 1)) + + assert(parameters['W' + str(l)].shape == layer_dims[l], layer_dims[l-1]) + assert(parameters['W' + str(l)].shape == layer_dims[l], 1) + + return parameters + + +def compute_cost(a3, Y): + + """ + Implement the cost function + + Arguments: + a3 -- post-activation, output of forward propagation + Y -- "true" labels vector, same shape as a3 + + Returns: + cost - value of the cost function + """ + m = Y.shape[1] + + logprobs = np.multiply(-np.log(a3),Y) + np.multiply(-np.log(1 - a3), 1 - Y) + cost = 1./m * np.sum(logprobs) + + return cost + +def forward_propagation(X, parameters): + """ + Implements the forward propagation (and computes the loss) presented in Figure 2. + + Arguments: + X -- input dataset, of shape (input size, number of examples) + parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3": + W1 -- weight matrix of shape () + b1 -- bias vector of shape () + W2 -- weight matrix of shape () + b2 -- bias vector of shape () + W3 -- weight matrix of shape () + b3 -- bias vector of shape () + + Returns: + loss -- the loss function (vanilla logistic loss) + """ + + # retrieve parameters + W1 = parameters["W1"] + b1 = parameters["b1"] + W2 = parameters["W2"] + b2 = parameters["b2"] + W3 = parameters["W3"] + b3 = parameters["b3"] + + # LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SIGMOID + z1 = np.dot(W1, X) + b1 + a1 = relu(z1) + z2 = np.dot(W2, a1) + b2 + a2 = relu(z2) + z3 = np.dot(W3, a2) + b3 + a3 = sigmoid(z3) + + cache = (z1, a1, W1, b1, z2, a2, W2, b2, z3, a3, W3, b3) + + return a3, cache + +def backward_propagation(X, Y, cache): + """ + Implement the backward propagation presented in figure 2. + + Arguments: + X -- input dataset, of shape (input size, number of examples) + Y -- true "label" vector (containing 0 if cat, 1 if non-cat) + cache -- cache output from forward_propagation() + + Returns: + gradients -- A dictionary with the gradients with respect to each parameter, activation and pre-activation variables + """ + m = X.shape[1] + (z1, a1, W1, b1, z2, a2, W2, b2, z3, a3, W3, b3) = cache + + dz3 = 1./m * (a3 - Y) + dW3 = np.dot(dz3, a2.T) + db3 = np.sum(dz3, axis=1, keepdims = True) + + da2 = np.dot(W3.T, dz3) + dz2 = np.multiply(da2, np.int64(a2 > 0)) + dW2 = np.dot(dz2, a1.T) + db2 = np.sum(dz2, axis=1, keepdims = True) + + da1 = np.dot(W2.T, dz2) + dz1 = np.multiply(da1, np.int64(a1 > 0)) + dW1 = np.dot(dz1, X.T) + db1 = np.sum(dz1, axis=1, keepdims = True) + + gradients = {"dz3": dz3, "dW3": dW3, "db3": db3, + "da2": da2, "dz2": dz2, "dW2": dW2, "db2": db2, + "da1": da1, "dz1": dz1, "dW1": dW1, "db1": db1} + + return gradients + +def predict(X, y, parameters): + """ + This function is used to predict the results of a n-layer neural network. + + Arguments: + X -- data set of examples you would like to label + parameters -- parameters of the trained model + + Returns: + p -- predictions for the given dataset X + """ + + m = X.shape[1] + p = np.zeros((1,m), dtype = np.int) + + # Forward propagation + a3, caches = forward_propagation(X, parameters) + + # convert probas to 0/1 predictions + for i in range(0, a3.shape[1]): + if a3[0,i] > 0.5: + p[0,i] = 1 + else: + p[0,i] = 0 + + # print results + + #print ("predictions: " + str(p[0,:])) + #print ("true labels: " + str(y[0,:])) + print("Accuracy: " + str(np.mean((p[0,:] == y[0,:])))) + + return p + +def load_2D_dataset(): + data = scipy.io.loadmat('datasets/data.mat') + train_X = data['X'].T + train_Y = data['y'].T + test_X = data['Xval'].T + test_Y = data['yval'].T + + plt.scatter(train_X[0, :], train_X[1, :], c=train_Y, s=40, cmap=plt.cm.Spectral); + + return train_X, train_Y, test_X, test_Y + +def plot_decision_boundary(model, X, y): + # Set min and max values and give it some padding + x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1 + y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1 + h = 0.01 + # Generate a grid of points with distance h between them + xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) + # Predict the function value for the whole grid + Z = model(np.c_[xx.ravel(), yy.ravel()]) + Z = Z.reshape(xx.shape) + # Plot the contour and training examples + plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral) + plt.ylabel('x2') + plt.xlabel('x1') + plt.scatter(X[0, :], X[1, :], c=y, cmap=plt.cm.Spectral) + plt.show() + +def predict_dec(parameters, X): + """ + Used for plotting decision boundary. + + Arguments: + parameters -- python dictionary containing your parameters + X -- input data of size (m, K) + + Returns + predictions -- vector of predictions of our model (red: 0 / blue: 1) + """ + + # Predict using forward propagation and a classification threshold of 0.5 + a3, cache = forward_propagation(X, parameters) + predictions = (a3 > 0.5) + return predictions + +def load_dataset(): + np.random.seed(3) + train_X, train_Y = sklearn.datasets.make_moons(n_samples=300, noise=.2) #300 #0.2 + # Visualize the data + plt.scatter(train_X[:, 0], train_X[:, 1], c=train_Y, s=40, cmap=plt.cm.Spectral); + train_X = train_X.T + train_Y = train_Y.reshape((1, train_Y.shape[0])) + + return train_X, train_Y \ No newline at end of file diff --git a/optimization_algorithms/testCases.py b/optimization_algorithms/testCases.py new file mode 100644 index 0000000..46feea8 --- /dev/null +++ b/optimization_algorithms/testCases.py @@ -0,0 +1,105 @@ +import numpy as np + +def update_parameters_with_gd_test_case(): + np.random.seed(1) + learning_rate = 0.01 + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + + dW1 = np.random.randn(2,3) + db1 = np.random.randn(2,1) + dW2 = np.random.randn(3,3) + db2 = np.random.randn(3,1) + + parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} + grads = {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2} + + return parameters, grads, learning_rate + +""" +def update_parameters_with_sgd_checker(function, inputs, outputs): + if function(inputs) == outputs: + print("Correct") + else: + print("Incorrect") +""" + +def random_mini_batches_test_case(): + np.random.seed(1) + mini_batch_size = 64 + X = np.random.randn(12288, 148) + Y = np.random.randn(1, 148) < 0.5 + return X, Y, mini_batch_size + +def initialize_velocity_test_case(): + np.random.seed(1) + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} + return parameters + +def update_parameters_with_momentum_test_case(): + np.random.seed(1) + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + + dW1 = np.random.randn(2,3) + db1 = np.random.randn(2,1) + dW2 = np.random.randn(3,3) + db2 = np.random.randn(3,1) + parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} + grads = {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2} + v = {'dW1': np.array([[ 0., 0., 0.], + [ 0., 0., 0.]]), 'dW2': np.array([[ 0., 0., 0.], + [ 0., 0., 0.], + [ 0., 0., 0.]]), 'db1': np.array([[ 0.], + [ 0.]]), 'db2': np.array([[ 0.], + [ 0.], + [ 0.]])} + return parameters, grads, v + +def initialize_adam_test_case(): + np.random.seed(1) + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} + return parameters + +def update_parameters_with_adam_test_case(): + np.random.seed(1) + v, s = ({'dW1': np.array([[ 0., 0., 0.], + [ 0., 0., 0.]]), 'dW2': np.array([[ 0., 0., 0.], + [ 0., 0., 0.], + [ 0., 0., 0.]]), 'db1': np.array([[ 0.], + [ 0.]]), 'db2': np.array([[ 0.], + [ 0.], + [ 0.]])}, {'dW1': np.array([[ 0., 0., 0.], + [ 0., 0., 0.]]), 'dW2': np.array([[ 0., 0., 0.], + [ 0., 0., 0.], + [ 0., 0., 0.]]), 'db1': np.array([[ 0.], + [ 0.]]), 'db2': np.array([[ 0.], + [ 0.], + [ 0.]])}) + W1 = np.random.randn(2,3) + b1 = np.random.randn(2,1) + W2 = np.random.randn(3,3) + b2 = np.random.randn(3,1) + + dW1 = np.random.randn(2,3) + db1 = np.random.randn(2,1) + dW2 = np.random.randn(3,3) + db2 = np.random.randn(3,1) + + parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2} + grads = {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2} + + return parameters, grads, v, s + \ No newline at end of file