CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
leechanwoo-kor

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: leechanwoo-kor/coursera
Path: blob/main/deep-learning-specialization/course-4-convolutional-neural-network/Convolution_model_Application.ipynb
Views: 34199
Kernel: Python 3

Convolutional Neural Networks: Application

Welcome to Course 4's second assignment! In this notebook, you will:

  • Create a mood classifer using the TF Keras Sequential API

  • Build a ConvNet to identify sign language digits using the TF Keras Functional API

After this assignment you will be able to:

  • Build and train a ConvNet in TensorFlow for a binary classification problem

  • Build and train a ConvNet in TensorFlow for a multiclass classification problem

  • Explain different use cases for the Sequential and Functional APIs

To complete this assignment, you should already be familiar with TensorFlow. If you are not, please refer back to the TensorFlow Tutorial of the third week of Course 2 ("Improving deep neural networks").

Important Note on Submission to the AutoGrader

Before submitting your assignment to the AutoGrader, please make sure you are not doing the following:

  1. You have not added any extra print statement(s) in the assignment.

  2. You have not added any extra code cell(s) in the assignment.

  3. You have not changed any of the function parameters.

  4. You are not using any global variables inside your graded exercises. Unless specifically instructed to do so, please refrain from it and use the local variables instead.

  5. You are not changing the assignment code where it is not required, like creating extra variables.

If you do any of the following, you will get something like, Grader not found (or similarly unexpected) error upon submitting your assignment. Before asking for help/debugging the errors in your assignment, check for these first. If this is the case, and you don't remember the changes you have made, you can get a fresh copy of the assignment by following these instructions.

1 - Packages

As usual, begin by loading in the packages.

import math import numpy as np import h5py import matplotlib.pyplot as plt from matplotlib.pyplot import imread import scipy from PIL import Image import pandas as pd import tensorflow as tf import tensorflow.keras.layers as tfl from tensorflow.python.framework import ops from cnn_utils import * from test_utils import summary, comparator %matplotlib inline np.random.seed(1)

1.1 - Load the Data and Split the Data into Train/Test Sets

You'll be using the Happy House dataset for this part of the assignment, which contains images of peoples' faces. Your task will be to build a ConvNet that determines whether the people in the images are smiling or not -- because they only get to enter the house if they're smiling!

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_happy_dataset() # Normalize image vectors X_train = X_train_orig/255. X_test = X_test_orig/255. # Reshape Y_train = Y_train_orig.T Y_test = Y_test_orig.T print ("number of training examples = " + str(X_train.shape[0])) print ("number of test examples = " + str(X_test.shape[0])) print ("X_train shape: " + str(X_train.shape)) print ("Y_train shape: " + str(Y_train.shape)) print ("X_test shape: " + str(X_test.shape)) print ("Y_test shape: " + str(Y_test.shape))
number of training examples = 600 number of test examples = 150 X_train shape: (600, 64, 64, 3) Y_train shape: (600, 1) X_test shape: (150, 64, 64, 3) Y_test shape: (150, 1)

You can display the images contained in the dataset. Images are 64x64 pixels in RGB format (3 channels).

index = 124 plt.imshow(X_train_orig[index]) #display sample training image plt.show()
Image in a Jupyter notebook

2 - Layers in TF Keras

In the previous assignment, you created layers manually in numpy. In TF Keras, you don't have to write code directly to create layers. Rather, TF Keras has pre-defined layers you can use.

When you create a layer in TF Keras, you are creating a function that takes some input and transforms it into an output you can reuse later. Nice and easy!

3 - The Sequential API

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. Keras is a high-level abstraction built on top of TensorFlow, which allows for even more simplified and optimized model creation and training.

For the first part of this assignment, you'll create a model using TF Keras' Sequential API, which allows you to build layer by layer, and is ideal for building models where each layer has exactly one input tensor and one output tensor.

As you'll see, using the Sequential API is simple and straightforward, but is only appropriate for simpler, more straightforward tasks. Later in this notebook you'll spend some time building with a more flexible, powerful alternative: the Functional API.

3.1 - Create the Sequential Model

As mentioned earlier, the TensorFlow Keras Sequential API can be used to build simple models with layer operations that proceed in a sequential order.

You can also add layers incrementally to a Sequential model with the .add() method, or remove them using the .pop() method, much like you would in a regular Python list.

Actually, you can think of a Sequential model as behaving like a list of layers. Like Python lists, Sequential layers are ordered, and the order in which they are specified matters. If your model is non-linear or contains layers with multiple inputs or outputs, a Sequential model wouldn't be the right choice!

For any layer construction in Keras, you'll need to specify the input shape in advance. This is because in Keras, the shape of the weights is based on the shape of the inputs. The weights are only created when the model first sees some input data. Sequential models can be created by passing a list of layers to the Sequential constructor, like you will do in the next assignment.

Exercise 1 - happyModel

Implement the happyModel function below to build the following model: ZEROPAD2D -> CONV2D -> BATCHNORM -> RELU -> MAXPOOL -> FLATTEN -> DENSE. Take help from tf.keras.layers

Also, plug in the following parameters for all the steps:

Hint:

Use tfl as shorthand for tensorflow.keras.layers

# GRADED FUNCTION: happyModel def happyModel(): """ Implements the forward propagation for the binary classification model: ZEROPAD2D -> CONV2D -> BATCHNORM -> RELU -> MAXPOOL -> FLATTEN -> DENSE Note that for simplicity and grading purposes, you'll hard-code all the values such as the stride and kernel (filter) sizes. Normally, functions should take these values as function parameters. Arguments: None Returns: model -- TF Keras model (object containing the information for the entire training process) """ model = tf.keras.Sequential([ ## ZeroPadding2D with padding 3, input shape of 64 x 64 x 3 ## Conv2D with 32 7x7 filters and stride of ## BatchNormalization for axis 3 ## ReLU ## Max Pooling 2D with default parameters ## Flatten layer ## Dense layer with 1 unit for output & 'sigmoid' activation # YOUR CODE STARTS HERE ## ZeroPadding2D with padding 3, input shape of 64 x 64 x 3 tfl.ZeroPadding2D(padding=3, input_shape=(64,64,3)), ## Conv2D with 32 7x7 filters and stride of 1 tfl.Conv2D(32, (7,7)), ## BatchNormalization for axis 3 tfl.BatchNormalization(axis=3), ## ReLU tfl.ReLU(), ## Max Pooling 2D with default parameters tfl.MaxPool2D(), ## Flatten layer tfl.Flatten(), ## Dense layer with 1 unit for output & 'sigmoid' activation tfl.Dense(1, activation='sigmoid') # YOUR CODE ENDS HERE ]) return model
happy_model = happyModel() # Print a summary for each layer for layer in summary(happy_model): print(layer) output = [['ZeroPadding2D', (None, 70, 70, 3), 0, ((3, 3), (3, 3))], ['Conv2D', (None, 64, 64, 32), 4736, 'valid', 'linear', 'GlorotUniform'], ['BatchNormalization', (None, 64, 64, 32), 128], ['ReLU', (None, 64, 64, 32), 0], ['MaxPooling2D', (None, 32, 32, 32), 0, (2, 2), (2, 2), 'valid'], ['Flatten', (None, 32768), 0], ['Dense', (None, 1), 32769, 'sigmoid']] comparator(summary(happy_model), output)
['ZeroPadding2D', (None, 70, 70, 3), 0, ((3, 3), (3, 3))] ['Conv2D', (None, 64, 64, 32), 4736, 'valid', 'linear', 'GlorotUniform'] ['BatchNormalization', (None, 64, 64, 32), 128] ['ReLU', (None, 64, 64, 32), 0] ['MaxPooling2D', (None, 32, 32, 32), 0, (2, 2), (2, 2), 'valid'] ['Flatten', (None, 32768), 0] ['Dense', (None, 1), 32769, 'sigmoid'] All tests passed!

Now that your model is created, you can compile it for training with an optimizer and loss of your choice. When the string accuracy is specified as a metric, the type of accuracy used will be automatically converted based on the loss function used. This is one of the many optimizations built into TensorFlow that make your life easier! If you'd like to read more on how the compiler operates, check the docs here.

happy_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

It's time to check your model's parameters with the .summary() method. This will display the types of layers you have, the shape of the outputs, and how many parameters are in each layer.

happy_model.summary()
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= zero_padding2d (ZeroPadding2 (None, 70, 70, 3) 0 _________________________________________________________________ conv2d (Conv2D) (None, 64, 64, 32) 4736 _________________________________________________________________ batch_normalization (BatchNo (None, 64, 64, 32) 128 _________________________________________________________________ re_lu (ReLU) (None, 64, 64, 32) 0 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 32, 32, 32) 0 _________________________________________________________________ flatten (Flatten) (None, 32768) 0 _________________________________________________________________ dense (Dense) (None, 1) 32769 ================================================================= Total params: 37,633 Trainable params: 37,569 Non-trainable params: 64 _________________________________________________________________

3.2 - Train and Evaluate the Model

After creating the model, compiling it with your choice of optimizer and loss function, and doing a sanity check on its contents, you are now ready to build!

Simply call .fit() to train. That's it! No need for mini-batching, saving, or complex backpropagation computations. That's all been done for you, as you're using a TensorFlow dataset with the batches specified already. You do have the option to specify epoch number or minibatch size if you like (for example, in the case of an un-batched dataset).

happy_model.fit(X_train, Y_train, epochs=10, batch_size=16)
Epoch 1/10 38/38 [==============================] - 4s 95ms/step - loss: 0.9591 - accuracy: 0.7983 Epoch 2/10 38/38 [==============================] - 3s 89ms/step - loss: 0.2149 - accuracy: 0.9050 Epoch 3/10 38/38 [==============================] - 3s 90ms/step - loss: 0.2550 - accuracy: 0.9017 Epoch 4/10 38/38 [==============================] - 3s 92ms/step - loss: 0.1538 - accuracy: 0.9567 Epoch 5/10 38/38 [==============================] - 3s 90ms/step - loss: 0.1145 - accuracy: 0.9617 Epoch 6/10 38/38 [==============================] - 3s 90ms/step - loss: 0.1186 - accuracy: 0.9717 Epoch 7/10 38/38 [==============================] - 3s 92ms/step - loss: 0.0666 - accuracy: 0.9783 Epoch 8/10 38/38 [==============================] - 3s 90ms/step - loss: 0.1700 - accuracy: 0.9450 Epoch 9/10 38/38 [==============================] - 3s 89ms/step - loss: 0.0986 - accuracy: 0.9600 Epoch 10/10 38/38 [==============================] - 3s 92ms/step - loss: 0.1766 - accuracy: 0.9300
<tensorflow.python.keras.callbacks.History at 0x7f5129ab6a90>

After that completes, just use .evaluate() to evaluate against your test set. This function will print the value of the loss function and the performance metrics specified during the compilation of the model. In this case, the binary_crossentropy and the accuracy respectively.

happy_model.evaluate(X_test, Y_test)
5/5 [==============================] - 0s 34ms/step - loss: 0.1904 - accuracy: 0.9400
[0.19040469825267792, 0.9399999976158142]

Easy, right? But what if you need to build a model with shared layers, branches, or multiple inputs and outputs? This is where Sequential, with its beautifully simple yet limited functionality, won't be able to help you.

Next up: Enter the Functional API, your slightly more complex, highly flexible friend.

4 - The Functional API

Welcome to the second half of the assignment, where you'll use Keras' flexible Functional API to build a ConvNet that can differentiate between 6 sign language digits.

The Functional API can handle models with non-linear topology, shared layers, as well as layers with multiple inputs or outputs. Imagine that, where the Sequential API requires the model to move in a linear fashion through its layers, the Functional API allows much more flexibility. Where Sequential is a straight line, a Functional model is a graph, where the nodes of the layers can connect in many more ways than one.

In the visual example below, the one possible direction of the movement Sequential model is shown in contrast to a skip connection, which is just one of the many ways a Functional model can be constructed. A skip connection, as you might have guessed, skips some layer in the network and feeds the output to a later layer in the network. Don't worry, you'll be spending more time with skip connections very soon!

4.1 - Load the SIGNS Dataset

As a reminder, the SIGNS dataset is a collection of 6 signs representing numbers from 0 to 5.

# Loading the data (signs) X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_signs_dataset()

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.

# Example of an image from the dataset index = 9 plt.imshow(X_train_orig[index]) print ("y = " + str(np.squeeze(Y_train_orig[:, index])))
y = 4
Image in a Jupyter notebook

4.2 - Split the Data into Train/Test Sets

In Course 2, you 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.

To get started, let's examine the shapes of your data.

X_train = X_train_orig/255. X_test = X_test_orig/255. Y_train = convert_to_one_hot(Y_train_orig, 6).T Y_test = convert_to_one_hot(Y_test_orig, 6).T print ("number of training examples = " + str(X_train.shape[0])) print ("number of test examples = " + str(X_test.shape[0])) print ("X_train shape: " + str(X_train.shape)) print ("Y_train shape: " + str(Y_train.shape)) print ("X_test shape: " + str(X_test.shape)) print ("Y_test shape: " + str(Y_test.shape))
number of training examples = 1080 number of test examples = 120 X_train shape: (1080, 64, 64, 3) Y_train shape: (1080, 6) X_test shape: (120, 64, 64, 3) Y_test shape: (120, 6)

4.3 - Forward Propagation

In TensorFlow, there are built-in functions that implement the convolution steps for you. By now, you should be familiar with how TensorFlow builds computational graphs. In the Functional API, you create a graph of layers. This is what allows such great flexibility.

However, the following model could also be defined using the Sequential API since the information flow is on a single line. But don't deviate. What we want you to learn is to use the functional API.

Begin building your graph of layers by creating an input node that functions as a callable object:

  • input_img = tf.keras.Input(shape=input_shape):

Then, create a new node in the graph of layers by calling a layer on the input_img object:

  • tf.keras.layers.Conv2D(filters= ... , kernel_size= ... , padding='same')(input_img): Read the full documentation on Conv2D.

  • tf.keras.layers.MaxPool2D(pool_size=(f, f), strides=(s, s), padding='same'): MaxPool2D() downsamples your input using a window of size (f, f) and strides of size (s, s) to carry out max pooling over each window. For max pooling, you usually operate on a single example at a time and a single channel at a time. Read the full documentation on MaxPool2D.

  • tf.keras.layers.ReLU(): computes the elementwise ReLU of Z (which can be any shape). You can read the full documentation on ReLU.

  • tf.keras.layers.Flatten(): given a tensor "P", this function takes each training (or test) example in the batch and flattens it into a 1D vector.

    • If a tensor P has the shape (batch_size,h,w,c), it returns a flattened tensor with shape (batch_size, k), where k=h×w×ck=h \times w \times c. "k" equals the product of all the dimension sizes other than the first dimension.

    • For example, given a tensor with dimensions [100, 2, 3, 4], it flattens the tensor to be of shape [100, 24], where 24 = 2 * 3 * 4. You can read the full documentation on Flatten.

  • tf.keras.layers.Dense(units= ... , activation='softmax')(F): given the flattened input F, it returns the output computed using a fully connected layer. You can read the full documentation on Dense.

In the last function above (tf.keras.layers.Dense()), 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.

Lastly, before creating the model, you'll need to define the output using the last of the function's compositions (in this example, a Dense layer):

  • outputs = tf.keras.layers.Dense(units=6, activation='softmax')(F)

Window, kernel, filter, pool

The words "kernel" and "filter" are used to refer to the same thing. The word "filter" accounts for the amount of "kernels" that will be used in a single convolution layer. "Pool" is the name of the operation that takes the max or average value of the kernels.

This is why the parameter pool_size refers to kernel_size, and you use (f,f) to refer to the filter size.

Pool size and kernel size refer to the same thing in different objects - They refer to the shape of the window where the operation takes place.

Exercise 2 - convolutional_model

Implement the convolutional_model function below to build the following model: CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> DENSE. Use the functions above!

Also, plug in the following parameters for all the steps:

  • Conv2D: Use 8 4 by 4 filters, stride 1, padding is "SAME"

  • ReLU

  • MaxPool2D: Use an 8 by 8 filter size and an 8 by 8 stride, padding is "SAME"

  • Conv2D: Use 16 2 by 2 filters, stride 1, padding is "SAME"

  • ReLU

  • MaxPool2D: Use a 4 by 4 filter size and a 4 by 4 stride, padding is "SAME"

  • Flatten the previous output.

  • Fully-connected (Dense) layer: Apply a fully connected layer with 6 neurons and a softmax activation.

# GRADED FUNCTION: convolutional_model def convolutional_model(input_shape): """ Implements the forward propagation for the model: CONV2D -> RELU -> MAXPOOL -> CONV2D -> RELU -> MAXPOOL -> FLATTEN -> DENSE Note that for simplicity and grading purposes, you'll hard-code some values such as the stride and kernel (filter) sizes. Normally, functions should take these values as function parameters. Arguments: input_img -- input dataset, of shape (input_shape) Returns: model -- TF Keras model (object containing the information for the entire training process) """ input_img = tf.keras.Input(shape=input_shape) ## CONV2D: 8 filters 4x4, stride of 1, padding 'SAME' # Z1 = None ## RELU # A1 = None ## MAXPOOL: window 8x8, stride 8, padding 'SAME' # P1 = None ## CONV2D: 16 filters 2x2, stride 1, padding 'SAME' # Z2 = None ## RELU # A2 = None ## MAXPOOL: window 4x4, stride 4, padding 'SAME' # P2 = None ## FLATTEN # F = None ## Dense layer ## 6 neurons in output layer. Hint: one of the arguments should be "activation='softmax'" # outputs = None # YOUR CODE STARTS HERE ## CONV2D: 8 filters 4x4, stride of 1, padding 'SAME' Z1 = tfl.Conv2D(8, 4, activation='linear', padding="same", strides=1)(input_img) ## RELU A1 = tfl.ReLU()(Z1) ## MAXPOOL: window 8x8, stride 8, padding 'SAME' P1 = tfl.MaxPool2D(pool_size=(8, 8), strides=8, padding="same")(A1) ## CONV2D: 16 filters 2x2, stride 1, padding 'SAME' Z2 = tfl.Conv2D(16, 2, activation='linear', strides=1, padding="same")(P1) ## RELU A2 = tfl.ReLU()(Z2) ## MAXPOOL: window 4x4, stride 4, padding 'SAME' P2 = tfl.MaxPool2D(pool_size=(4, 4), strides=4, padding="same")(A2) ## FLATTEN F = tfl.Flatten()(P2) ## Dense layer ## 6 neurons in output layer. Hint: one of the arguments should be "activation='softmax'" outputs = tfl.Dense(6, activation='softmax')(F) # YOUR CODE ENDS HERE model = tf.keras.Model(inputs=input_img, outputs=outputs) return model
conv_model = convolutional_model((64, 64, 3)) conv_model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) conv_model.summary() output = [['InputLayer', [(None, 64, 64, 3)], 0], ['Conv2D', (None, 64, 64, 8), 392, 'same', 'linear', 'GlorotUniform'], ['ReLU', (None, 64, 64, 8), 0], ['MaxPooling2D', (None, 8, 8, 8), 0, (8, 8), (8, 8), 'same'], ['Conv2D', (None, 8, 8, 16), 528, 'same', 'linear', 'GlorotUniform'], ['ReLU', (None, 8, 8, 16), 0], ['MaxPooling2D', (None, 2, 2, 16), 0, (4, 4), (4, 4), 'same'], ['Flatten', (None, 64), 0], ['Dense', (None, 6), 390, 'softmax']] comparator(summary(conv_model), output)
Model: "functional_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 64, 64, 3)] 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 64, 64, 8) 392 _________________________________________________________________ re_lu_1 (ReLU) (None, 64, 64, 8) 0 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 8, 8, 8) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 8, 8, 16) 528 _________________________________________________________________ re_lu_2 (ReLU) (None, 8, 8, 16) 0 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 2, 2, 16) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 64) 0 _________________________________________________________________ dense_1 (Dense) (None, 6) 390 ================================================================= Total params: 1,310 Trainable params: 1,310 Non-trainable params: 0 _________________________________________________________________ All tests passed!

Both the Sequential and Functional APIs return a TF Keras model object. The only difference is how inputs are handled inside the object model!

4.4 - Train the Model

train_dataset = tf.data.Dataset.from_tensor_slices((X_train, Y_train)).batch(64) test_dataset = tf.data.Dataset.from_tensor_slices((X_test, Y_test)).batch(64) history = conv_model.fit(train_dataset, epochs=100, validation_data=test_dataset)
Epoch 1/100 17/17 [==============================] - 2s 106ms/step - loss: 1.7989 - accuracy: 0.1630 - val_loss: 1.7856 - val_accuracy: 0.1917 Epoch 2/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7892 - accuracy: 0.1722 - val_loss: 1.7805 - val_accuracy: 0.2417 Epoch 3/100 17/17 [==============================] - 2s 106ms/step - loss: 1.7843 - accuracy: 0.2046 - val_loss: 1.7761 - val_accuracy: 0.2917 Epoch 4/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7785 - accuracy: 0.2370 - val_loss: 1.7714 - val_accuracy: 0.3000 Epoch 5/100 17/17 [==============================] - 2s 95ms/step - loss: 1.7721 - accuracy: 0.2620 - val_loss: 1.7643 - val_accuracy: 0.3250 Epoch 6/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7622 - accuracy: 0.3139 - val_loss: 1.7528 - val_accuracy: 0.3250 Epoch 7/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7491 - accuracy: 0.3611 - val_loss: 1.7403 - val_accuracy: 0.3500 Epoch 8/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7327 - accuracy: 0.3935 - val_loss: 1.7244 - val_accuracy: 0.3750 Epoch 9/100 17/17 [==============================] - 2s 100ms/step - loss: 1.7114 - accuracy: 0.4148 - val_loss: 1.7054 - val_accuracy: 0.3750 Epoch 10/100 17/17 [==============================] - 2s 100ms/step - loss: 1.6854 - accuracy: 0.4454 - val_loss: 1.6799 - val_accuracy: 0.3750 Epoch 11/100 17/17 [==============================] - 2s 100ms/step - loss: 1.6518 - accuracy: 0.4648 - val_loss: 1.6489 - val_accuracy: 0.4000 Epoch 12/100 17/17 [==============================] - 2s 105ms/step - loss: 1.6110 - accuracy: 0.4713 - val_loss: 1.6108 - val_accuracy: 0.4167 Epoch 13/100 17/17 [==============================] - 2s 101ms/step - loss: 1.5635 - accuracy: 0.4889 - val_loss: 1.5695 - val_accuracy: 0.4167 Epoch 14/100 17/17 [==============================] - 2s 100ms/step - loss: 1.5086 - accuracy: 0.5056 - val_loss: 1.5204 - val_accuracy: 0.4250 Epoch 15/100 17/17 [==============================] - 2s 101ms/step - loss: 1.4503 - accuracy: 0.5065 - val_loss: 1.4715 - val_accuracy: 0.4083 Epoch 16/100 17/17 [==============================] - 2s 100ms/step - loss: 1.3949 - accuracy: 0.5139 - val_loss: 1.4252 - val_accuracy: 0.4333 Epoch 17/100 17/17 [==============================] - 2s 100ms/step - loss: 1.3431 - accuracy: 0.5130 - val_loss: 1.3806 - val_accuracy: 0.4417 Epoch 18/100 17/17 [==============================] - 2s 95ms/step - loss: 1.2984 - accuracy: 0.5222 - val_loss: 1.3437 - val_accuracy: 0.4333 Epoch 19/100 17/17 [==============================] - 2s 95ms/step - loss: 1.2561 - accuracy: 0.5315 - val_loss: 1.3033 - val_accuracy: 0.4667 Epoch 20/100 17/17 [==============================] - 2s 100ms/step - loss: 1.2181 - accuracy: 0.5454 - val_loss: 1.2707 - val_accuracy: 0.4750 Epoch 21/100 17/17 [==============================] - 2s 100ms/step - loss: 1.1829 - accuracy: 0.5611 - val_loss: 1.2370 - val_accuracy: 0.4833 Epoch 22/100 17/17 [==============================] - 2s 100ms/step - loss: 1.1488 - accuracy: 0.5815 - val_loss: 1.2033 - val_accuracy: 0.4833 Epoch 23/100 17/17 [==============================] - 2s 100ms/step - loss: 1.1179 - accuracy: 0.5926 - val_loss: 1.1735 - val_accuracy: 0.5000 Epoch 24/100 17/17 [==============================] - 2s 96ms/step - loss: 1.0874 - accuracy: 0.6000 - val_loss: 1.1427 - val_accuracy: 0.5083 Epoch 25/100 17/17 [==============================] - 2s 100ms/step - loss: 1.0578 - accuracy: 0.6167 - val_loss: 1.1146 - val_accuracy: 0.5083 Epoch 26/100 17/17 [==============================] - 2s 106ms/step - loss: 1.0301 - accuracy: 0.6333 - val_loss: 1.0866 - val_accuracy: 0.5583 Epoch 27/100 17/17 [==============================] - 2s 100ms/step - loss: 1.0036 - accuracy: 0.6426 - val_loss: 1.0621 - val_accuracy: 0.5667 Epoch 28/100 17/17 [==============================] - 2s 100ms/step - loss: 0.9779 - accuracy: 0.6546 - val_loss: 1.0362 - val_accuracy: 0.6000 Epoch 29/100 17/17 [==============================] - 2s 100ms/step - loss: 0.9543 - accuracy: 0.6639 - val_loss: 1.0140 - val_accuracy: 0.5917 Epoch 30/100 17/17 [==============================] - 2s 100ms/step - loss: 0.9324 - accuracy: 0.6741 - val_loss: 0.9925 - val_accuracy: 0.6083 Epoch 31/100 17/17 [==============================] - 2s 101ms/step - loss: 0.9106 - accuracy: 0.6796 - val_loss: 0.9721 - val_accuracy: 0.6250 Epoch 32/100 17/17 [==============================] - 2s 100ms/step - loss: 0.8904 - accuracy: 0.6852 - val_loss: 0.9536 - val_accuracy: 0.6333 Epoch 33/100 17/17 [==============================] - 2s 100ms/step - loss: 0.8708 - accuracy: 0.6972 - val_loss: 0.9343 - val_accuracy: 0.6333 Epoch 34/100 17/17 [==============================] - 2s 100ms/step - loss: 0.8532 - accuracy: 0.7065 - val_loss: 0.9173 - val_accuracy: 0.6417 Epoch 35/100 17/17 [==============================] - 2s 95ms/step - loss: 0.8350 - accuracy: 0.7167 - val_loss: 0.8998 - val_accuracy: 0.6583 Epoch 36/100 17/17 [==============================] - 2s 100ms/step - loss: 0.8185 - accuracy: 0.7222 - val_loss: 0.8846 - val_accuracy: 0.6583 Epoch 37/100 17/17 [==============================] - 2s 101ms/step - loss: 0.8026 - accuracy: 0.7278 - val_loss: 0.8688 - val_accuracy: 0.6750 Epoch 38/100 17/17 [==============================] - 2s 100ms/step - loss: 0.7879 - accuracy: 0.7306 - val_loss: 0.8548 - val_accuracy: 0.6750 Epoch 39/100 17/17 [==============================] - 2s 100ms/step - loss: 0.7734 - accuracy: 0.7398 - val_loss: 0.8403 - val_accuracy: 0.6667 Epoch 40/100 17/17 [==============================] - 2s 100ms/step - loss: 0.7595 - accuracy: 0.7417 - val_loss: 0.8262 - val_accuracy: 0.6750 Epoch 41/100 17/17 [==============================] - 2s 106ms/step - loss: 0.7459 - accuracy: 0.7509 - val_loss: 0.8127 - val_accuracy: 0.6833 Epoch 42/100 17/17 [==============================] - 2s 101ms/step - loss: 0.7323 - accuracy: 0.7556 - val_loss: 0.7993 - val_accuracy: 0.6917 Epoch 43/100 17/17 [==============================] - 2s 100ms/step - loss: 0.7202 - accuracy: 0.7639 - val_loss: 0.7876 - val_accuracy: 0.6833 Epoch 44/100 17/17 [==============================] - 2s 100ms/step - loss: 0.7080 - accuracy: 0.7648 - val_loss: 0.7756 - val_accuracy: 0.6917 Epoch 45/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6964 - accuracy: 0.7667 - val_loss: 0.7654 - val_accuracy: 0.6917 Epoch 46/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6851 - accuracy: 0.7769 - val_loss: 0.7547 - val_accuracy: 0.7083 Epoch 47/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6748 - accuracy: 0.7778 - val_loss: 0.7461 - val_accuracy: 0.7083 Epoch 48/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6646 - accuracy: 0.7833 - val_loss: 0.7359 - val_accuracy: 0.7083 Epoch 49/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6551 - accuracy: 0.7852 - val_loss: 0.7276 - val_accuracy: 0.7083 Epoch 50/100 17/17 [==============================] - 2s 106ms/step - loss: 0.6457 - accuracy: 0.7889 - val_loss: 0.7189 - val_accuracy: 0.7083 Epoch 51/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6366 - accuracy: 0.7898 - val_loss: 0.7113 - val_accuracy: 0.7083 Epoch 52/100 17/17 [==============================] - 2s 105ms/step - loss: 0.6272 - accuracy: 0.7954 - val_loss: 0.7023 - val_accuracy: 0.7083 Epoch 53/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6189 - accuracy: 0.7972 - val_loss: 0.6953 - val_accuracy: 0.7083 Epoch 54/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6104 - accuracy: 0.8000 - val_loss: 0.6874 - val_accuracy: 0.7083 Epoch 55/100 17/17 [==============================] - 2s 100ms/step - loss: 0.6028 - accuracy: 0.7991 - val_loss: 0.6803 - val_accuracy: 0.7083 Epoch 56/100 17/17 [==============================] - 2s 101ms/step - loss: 0.5950 - accuracy: 0.8028 - val_loss: 0.6733 - val_accuracy: 0.7083 Epoch 57/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5880 - accuracy: 0.8028 - val_loss: 0.6667 - val_accuracy: 0.7083 Epoch 58/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5806 - accuracy: 0.8037 - val_loss: 0.6597 - val_accuracy: 0.7167 Epoch 59/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5736 - accuracy: 0.8056 - val_loss: 0.6533 - val_accuracy: 0.7167 Epoch 60/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5668 - accuracy: 0.8093 - val_loss: 0.6471 - val_accuracy: 0.7167 Epoch 61/100 17/17 [==============================] - 2s 101ms/step - loss: 0.5601 - accuracy: 0.8130 - val_loss: 0.6408 - val_accuracy: 0.7167 Epoch 62/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5537 - accuracy: 0.8148 - val_loss: 0.6349 - val_accuracy: 0.7167 Epoch 63/100 17/17 [==============================] - 2s 101ms/step - loss: 0.5475 - accuracy: 0.8167 - val_loss: 0.6294 - val_accuracy: 0.7250 Epoch 64/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5415 - accuracy: 0.8194 - val_loss: 0.6236 - val_accuracy: 0.7250 Epoch 65/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5356 - accuracy: 0.8231 - val_loss: 0.6186 - val_accuracy: 0.7250 Epoch 66/100 17/17 [==============================] - 2s 105ms/step - loss: 0.5298 - accuracy: 0.8250 - val_loss: 0.6134 - val_accuracy: 0.7333 Epoch 67/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5241 - accuracy: 0.8259 - val_loss: 0.6085 - val_accuracy: 0.7333 Epoch 68/100 17/17 [==============================] - 2s 101ms/step - loss: 0.5188 - accuracy: 0.8259 - val_loss: 0.6034 - val_accuracy: 0.7417 Epoch 69/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5130 - accuracy: 0.8296 - val_loss: 0.5982 - val_accuracy: 0.7500 Epoch 70/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5076 - accuracy: 0.8315 - val_loss: 0.5944 - val_accuracy: 0.7583 Epoch 71/100 17/17 [==============================] - 2s 100ms/step - loss: 0.5028 - accuracy: 0.8315 - val_loss: 0.5890 - val_accuracy: 0.7417 Epoch 72/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4975 - accuracy: 0.8370 - val_loss: 0.5849 - val_accuracy: 0.7417 Epoch 73/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4925 - accuracy: 0.8389 - val_loss: 0.5799 - val_accuracy: 0.7417 Epoch 74/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4872 - accuracy: 0.8407 - val_loss: 0.5766 - val_accuracy: 0.7417 Epoch 75/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4825 - accuracy: 0.8417 - val_loss: 0.5730 - val_accuracy: 0.7417 Epoch 76/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4776 - accuracy: 0.8444 - val_loss: 0.5689 - val_accuracy: 0.7500 Epoch 77/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4726 - accuracy: 0.8481 - val_loss: 0.5642 - val_accuracy: 0.7417 Epoch 78/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4682 - accuracy: 0.8481 - val_loss: 0.5613 - val_accuracy: 0.7500 Epoch 79/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4636 - accuracy: 0.8491 - val_loss: 0.5575 - val_accuracy: 0.7500 Epoch 80/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4591 - accuracy: 0.8509 - val_loss: 0.5545 - val_accuracy: 0.7667 Epoch 81/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4548 - accuracy: 0.8565 - val_loss: 0.5508 - val_accuracy: 0.7667 Epoch 82/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4505 - accuracy: 0.8583 - val_loss: 0.5482 - val_accuracy: 0.7667 Epoch 83/100 17/17 [==============================] - 2s 105ms/step - loss: 0.4465 - accuracy: 0.8611 - val_loss: 0.5445 - val_accuracy: 0.7667 Epoch 84/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4423 - accuracy: 0.8630 - val_loss: 0.5424 - val_accuracy: 0.7667 Epoch 85/100 17/17 [==============================] - 2s 105ms/step - loss: 0.4383 - accuracy: 0.8630 - val_loss: 0.5390 - val_accuracy: 0.7667 Epoch 86/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4346 - accuracy: 0.8639 - val_loss: 0.5366 - val_accuracy: 0.7667 Epoch 87/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4307 - accuracy: 0.8639 - val_loss: 0.5347 - val_accuracy: 0.7667 Epoch 88/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4268 - accuracy: 0.8648 - val_loss: 0.5312 - val_accuracy: 0.7667 Epoch 89/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4229 - accuracy: 0.8657 - val_loss: 0.5293 - val_accuracy: 0.7667 Epoch 90/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4195 - accuracy: 0.8667 - val_loss: 0.5261 - val_accuracy: 0.7583 Epoch 91/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4155 - accuracy: 0.8694 - val_loss: 0.5243 - val_accuracy: 0.7583 Epoch 92/100 17/17 [==============================] - 2s 101ms/step - loss: 0.4120 - accuracy: 0.8685 - val_loss: 0.5198 - val_accuracy: 0.7667 Epoch 93/100 17/17 [==============================] - 2s 100ms/step - loss: 0.4083 - accuracy: 0.8741 - val_loss: 0.5185 - val_accuracy: 0.7667 Epoch 94/100 17/17 [==============================] - 2s 106ms/step - loss: 0.4049 - accuracy: 0.8750 - val_loss: 0.5143 - val_accuracy: 0.7667 Epoch 95/100 17/17 [==============================] - 2s 101ms/step - loss: 0.4014 - accuracy: 0.8787 - val_loss: 0.5127 - val_accuracy: 0.7833 Epoch 96/100 17/17 [==============================] - 2s 100ms/step - loss: 0.3978 - accuracy: 0.8806 - val_loss: 0.5079 - val_accuracy: 0.7833 Epoch 97/100 17/17 [==============================] - 2s 101ms/step - loss: 0.3947 - accuracy: 0.8796 - val_loss: 0.5072 - val_accuracy: 0.7833 Epoch 98/100 17/17 [==============================] - 2s 100ms/step - loss: 0.3914 - accuracy: 0.8806 - val_loss: 0.5033 - val_accuracy: 0.7833 Epoch 99/100 17/17 [==============================] - 2s 105ms/step - loss: 0.3883 - accuracy: 0.8787 - val_loss: 0.5025 - val_accuracy: 0.7833 Epoch 100/100 17/17 [==============================] - 2s 100ms/step - loss: 0.3850 - accuracy: 0.8815 - val_loss: 0.4984 - val_accuracy: 0.7833

5 - History Object

The history object is an output of the .fit() operation, and provides a record of all the loss and metric values in memory. It's stored as a dictionary that you can retrieve at history.history:

history.history
{'loss': [1.7989144325256348, 1.7891560792922974, 1.7842702865600586, 1.778518557548523, 1.772133708000183, 1.7621873617172241, 1.749057412147522, 1.7327356338500977, 1.7113999128341675, 1.6853621006011963, 1.6517916917800903, 1.610998272895813, 1.5634512901306152, 1.5086487531661987, 1.4503470659255981, 1.3949010372161865, 1.3430707454681396, 1.298369288444519, 1.2561233043670654, 1.2181111574172974, 1.1828659772872925, 1.1487951278686523, 1.117924451828003, 1.0874396562576294, 1.057821273803711, 1.0300756692886353, 1.0035520792007446, 0.9779444932937622, 0.9542796015739441, 0.9324339032173157, 0.9105756282806396, 0.8904469013214111, 0.8707838654518127, 0.8531739711761475, 0.8350361585617065, 0.8185321688652039, 0.8026479482650757, 0.7878644466400146, 0.773383617401123, 0.7594670057296753, 0.7459146976470947, 0.7323085069656372, 0.7201607823371887, 0.7080439925193787, 0.6964110732078552, 0.6851458549499512, 0.6747690439224243, 0.6646021604537964, 0.6550962328910828, 0.6457048654556274, 0.6366205215454102, 0.6272122859954834, 0.6188613176345825, 0.6104218363761902, 0.6027931571006775, 0.5949563980102539, 0.5880468487739563, 0.580645740032196, 0.573578417301178, 0.5668042898178101, 0.5600858926773071, 0.5536690354347229, 0.5474683046340942, 0.5415499210357666, 0.5355502367019653, 0.5297889113426208, 0.5241089463233948, 0.5187758207321167, 0.5130355954170227, 0.507627010345459, 0.5028172731399536, 0.4974748492240906, 0.4925089478492737, 0.487232506275177, 0.4824568033218384, 0.47763749957084656, 0.4726051688194275, 0.4682239294052124, 0.4635813534259796, 0.45913389325141907, 0.4548090696334839, 0.4505236744880676, 0.4464985728263855, 0.44228169322013855, 0.4383247196674347, 0.43463993072509766, 0.4306638538837433, 0.4267973303794861, 0.42290329933166504, 0.4194900095462799, 0.41548237204551697, 0.41202741861343384, 0.40833747386932373, 0.4049009382724762, 0.4013715982437134, 0.39778146147727966, 0.3946622312068939, 0.3913869261741638, 0.38830047845840454, 0.38496559858322144], 'accuracy': [0.16296295821666718, 0.17222222685813904, 0.20462962985038757, 0.2370370328426361, 0.2620370388031006, 0.31388887763023376, 0.3611111044883728, 0.39351850748062134, 0.4148148000240326, 0.4453703761100769, 0.46481481194496155, 0.4712963104248047, 0.4888888895511627, 0.5055555701255798, 0.5064814686775208, 0.5138888955116272, 0.5129629373550415, 0.5222222208976746, 0.5314815044403076, 0.5453703999519348, 0.5611110925674438, 0.5814814567565918, 0.5925925970077515, 0.6000000238418579, 0.6166666746139526, 0.6333333253860474, 0.6425926089286804, 0.654629647731781, 0.6638888716697693, 0.6740740537643433, 0.6796296238899231, 0.6851851940155029, 0.6972222328186035, 0.7064814567565918, 0.7166666388511658, 0.7222222089767456, 0.7277777791023254, 0.730555534362793, 0.739814817905426, 0.7416666746139526, 0.7509258985519409, 0.7555555701255798, 0.7638888955116272, 0.7648147940635681, 0.7666666507720947, 0.7768518328666687, 0.7777777910232544, 0.7833333611488342, 0.7851851582527161, 0.7888888716697693, 0.789814829826355, 0.7953703999519348, 0.7972221970558167, 0.800000011920929, 0.7990740537643433, 0.8027777671813965, 0.8027777671813965, 0.8037037253379822, 0.8055555820465088, 0.8092592358589172, 0.8129629492759705, 0.8148148059844971, 0.8166666626930237, 0.8194444179534912, 0.8231481313705444, 0.824999988079071, 0.8259259462356567, 0.8259259462356567, 0.8296296000480652, 0.8314814567565918, 0.8314814567565918, 0.8370370268821716, 0.8388888835906982, 0.8407407402992249, 0.8416666388511658, 0.8444444537162781, 0.8481481671333313, 0.8481481671333313, 0.8490740656852722, 0.8509259223937988, 0.8564814925193787, 0.8583333492279053, 0.8611111044883728, 0.8629629611968994, 0.8629629611968994, 0.8638888597488403, 0.8638888597488403, 0.864814817905426, 0.8657407164573669, 0.8666666746139526, 0.8694444298744202, 0.8685185313224792, 0.8740741014480591, 0.875, 0.8787037134170532, 0.8805555701255798, 0.8796296119689941, 0.8805555701255798, 0.8787037134170532, 0.8814814686775208], 'val_loss': [1.7856144905090332, 1.7804617881774902, 1.776122808456421, 1.771400809288025, 1.7642936706542969, 1.7527847290039062, 1.7402528524398804, 1.7243703603744507, 1.7053555250167847, 1.6798704862594604, 1.6488817930221558, 1.6107673645019531, 1.5694950819015503, 1.520423412322998, 1.4715018272399902, 1.4251976013183594, 1.3806309700012207, 1.3437237739562988, 1.3033310174942017, 1.2706949710845947, 1.2370191812515259, 1.203312635421753, 1.1734745502471924, 1.142680048942566, 1.1146303415298462, 1.086640477180481, 1.0621098279953003, 1.0362051725387573, 1.0139626264572144, 0.9925010204315186, 0.9720594882965088, 0.9536229372024536, 0.9343011379241943, 0.9173216223716736, 0.8997840881347656, 0.8846386671066284, 0.8687933683395386, 0.8547564148902893, 0.8402615785598755, 0.826163113117218, 0.8127169013023376, 0.7993418574333191, 0.7875939607620239, 0.7755884528160095, 0.7654262781143188, 0.7546941041946411, 0.7461259961128235, 0.7359120845794678, 0.7276450991630554, 0.718937337398529, 0.7113309502601624, 0.7023329138755798, 0.6952577829360962, 0.6873821020126343, 0.680339515209198, 0.6732890009880066, 0.666693925857544, 0.6597186923027039, 0.6533462405204773, 0.6470500230789185, 0.6407832503318787, 0.6349100470542908, 0.6294156908988953, 0.623634934425354, 0.6185827851295471, 0.613397479057312, 0.6084662675857544, 0.6034286618232727, 0.5982228517532349, 0.594354510307312, 0.5889933705329895, 0.5849465727806091, 0.5799427032470703, 0.576630175113678, 0.5730154514312744, 0.568905234336853, 0.5642030835151672, 0.5613271594047546, 0.5575486421585083, 0.5544562935829163, 0.5507809519767761, 0.5482295155525208, 0.5444628596305847, 0.5424461364746094, 0.5390364527702332, 0.536613404750824, 0.5346909165382385, 0.5312168002128601, 0.5293229818344116, 0.5261161923408508, 0.5243378281593323, 0.5197811722755432, 0.5184519290924072, 0.5143011808395386, 0.5127176642417908, 0.5079487562179565, 0.5071864724159241, 0.5033307671546936, 0.5024778246879578, 0.49844932556152344], 'val_accuracy': [0.19166666269302368, 0.24166665971279144, 0.2916666567325592, 0.30000001192092896, 0.32499998807907104, 0.32499998807907104, 0.3499999940395355, 0.375, 0.375, 0.375, 0.4000000059604645, 0.4166666567325592, 0.4166666567325592, 0.42500001192092896, 0.40833333134651184, 0.4333333373069763, 0.4416666626930237, 0.4333333373069763, 0.46666666865348816, 0.4749999940395355, 0.4833333194255829, 0.4833333194255829, 0.5, 0.5083333253860474, 0.5083333253860474, 0.5583333373069763, 0.5666666626930237, 0.6000000238418579, 0.5916666388511658, 0.6083333492279053, 0.625, 0.6333333253860474, 0.6333333253860474, 0.6416666507720947, 0.6583333611488342, 0.6583333611488342, 0.675000011920929, 0.675000011920929, 0.6666666865348816, 0.675000011920929, 0.6833333373069763, 0.6916666626930237, 0.6833333373069763, 0.6916666626930237, 0.6916666626930237, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7083333134651184, 0.7166666388511658, 0.7166666388511658, 0.7166666388511658, 0.7166666388511658, 0.7166666388511658, 0.7250000238418579, 0.7250000238418579, 0.7250000238418579, 0.7333333492279053, 0.7333333492279053, 0.7416666746139526, 0.75, 0.7583333253860474, 0.7416666746139526, 0.7416666746139526, 0.7416666746139526, 0.7416666746139526, 0.7416666746139526, 0.75, 0.7416666746139526, 0.75, 0.75, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7583333253860474, 0.7583333253860474, 0.7666666507720947, 0.7666666507720947, 0.7666666507720947, 0.7833333611488342, 0.7833333611488342, 0.7833333611488342, 0.7833333611488342, 0.7833333611488342, 0.7833333611488342]}

Now visualize the loss over time using history.history:

# The history.history["loss"] entry is a dictionary with as many values as epochs that the # model was trained on. df_loss_acc = pd.DataFrame(history.history) df_loss= df_loss_acc[['loss','val_loss']] df_loss.rename(columns={'loss':'train','val_loss':'validation'},inplace=True) df_acc= df_loss_acc[['accuracy','val_accuracy']] df_acc.rename(columns={'accuracy':'train','val_accuracy':'validation'},inplace=True) df_loss.plot(title='Model loss',figsize=(12,8)).set(xlabel='Epoch',ylabel='Loss') df_acc.plot(title='Model Accuracy',figsize=(12,8)).set(xlabel='Epoch',ylabel='Accuracy')
[Text(0, 0.5, 'Accuracy'), Text(0.5, 0, 'Epoch')]
Image in a Jupyter notebookImage in a Jupyter notebook

Congratulations! You've finished the assignment and built two models: One that recognizes smiles, and another that recognizes SIGN language with almost 80% accuracy on the test set. In addition to that, you now also understand the applications of two Keras APIs: Sequential and Functional. Nicely done!

By now, you know a bit about how the Functional API works and may have glimpsed the possibilities. In your next assignment, you'll really get a feel for its power when you get the opportunity to build a very deep ConvNet, using ResNets!

6 - Bibliography

You're always encouraged to read the official documentation. To that end, you can find the docs for the Sequential and Functional APIs here:

https://www.tensorflow.org/guide/keras/sequential_model

https://www.tensorflow.org/guide/keras/functional