Convolutional Neural Network (CNN)

Project: Implementing a Dog Breed Identification Algorithm App

In this notebook file, some template code is already available to you, but you also need to implement more features to complete the project. You do not need to modify any of the given code unless explicitly requested. The title starting with '(practice)' indicates that you have the functionality you need to implement in the next section of the code. These sections are accompanied by detailed instructions, and the parts that need to be implemented are also marked with 'TODO' in the comments. Please read all the tips carefully.

In addition to implementing the code, you also need to answer some questions related to the project and code. Every question that needs to be answered will be marked with 'Question X' . Please read each question carefully and write the full answer in the 'Answer' section of the question. We will rate the items you submit based on your answers to the questions and the functionality of the code implementation.

Tip: The Code and Markdown areas can be run with the Shift + Enter shortcut. In addition, Markdown can enter edit mode by double-clicking.

The part of the project that shows _selected _ can help your project stand out, rather than just meeting the minimum requirements. If you decide to pursue a higher challenge, please complete the _select_part of the code in this notebook.


Let's get started

In this notebook, you will take the first step to developing algorithms that can be used as part of a mobile or web application. At the end of this project, your program will be able to take any image provided by the user as input. If a dog can be detected from the image, it will output a prediction for the dog breed. If the image is a human face, it predicts the kind of dog that is most similar to it. The image below shows the possible output after completing the project. (...actually we want each student's output to be different!)

Sample Dog Output

In the real world, you need to piece together a series of models to accomplish different tasks; for example, the algorithm used to predict dog species will be different from the algorithm that predicts humans. In the process of doing the project, you may encounter many failed predictions because there are no perfect algorithms and models. The imperfect solution you finally submit will definitely bring you an interesting learning experience!

Project content¶

We have divided this notebook into different steps, you can use the link below to browse this notebook.

  • Step 0 : Import the data set
  • Step 1 : Detecting faces
  • Step 2 : Detecting dogs
  • Step 3 : Create a CNN from scratch to classify dog ​​breeds
  • Step 4 : Use a CNN to distinguish the breed of the dog (using migration learning)
  • Step 5 : Create a CNN to classify the dog breed (using migration learning)
  • Step 6 : Complete your algorithm
  • Step 7 : Test your algorithm

The following questions are included in the project:


Step 0: Import the data set¶

Import dog data set¶

In the code cell below, we imported a data set of dog images. We use scikit-learn library load_filesfunction to get the number of variables:

  • train_files, valid_files, test_files- a numpy array containing the file path of the image
  • train_targets, valid_targets, test_targets- a numpy array containing the uniquely encoded classification label
  • dog_names - the type of dog corresponding to the label consisting of a string
In [1]:
From  sklearn.datasets  import  load_files        
from  keras.utils  import  np_utils 
import  numpy  as  np 
from  glob  import  glob

# define function to load train, test, and validation datasets 
def  load_dataset ( path ): 
    data  =  load_files ( path ) 
    dog_files  =  np . array ( data [ 'filenames' ]) 
    dog_targets  =  np_utils . to_categorical ( np . array ( data [ ' Target' ]),  133 ) 
    return  dog_files ,  dog_targets

# load train, test, and validation datasets 
train_files ,  train_targets  =  load_dataset ( '/data/dog_images/train' ) 
valid_files ,  valid_targets  =  load_dataset ( '/data/dog_images/valid' ) 
test_files ,  test_targets  =  load_dataset ( '/data/dog_images /test' )

# load list of dog names 
dog_names  =  [ item [ 20 : - 1 ]  for  item  in  sorted ( glob ( "/data/dog_images/train/*/" ))]

# print statistics about the dataset 
print ( 'There are %d total dog categories.'  %  len ( dog_names )) 
print ( 'There are %s total dog images. \n '  %  len ( np . hstack ([ train_files ,  valid_files ,  Test_files ]))) 
print ( 'There are %d training dog images.'  %  len ( train_files )) 
print ( 'There are %d Validation dog images.' %  len ( valid_files )) 
print ( 'There are %d test dog images.' %  len ( test_files ))
Using TensorFlow backend.
There are 133 total dog categories.
There are 8351 total dog images.

There are 6680 training dog images.
There are 835 validation dog images.
There are 836 test dog images.

Import face data set¶

In the code unit below, we introduced into the facial image data set, the path is stored in a file named human_filesarray of numpy.

In [2]:
Import  random 
random . seed ( 8675309 )


#Load  the file name of the corrupted face dataset human_files =  np . array ( glob ( "/data/lfw/*/*" )) 
random . shuffle ( human_files )

# Print dataset data 
print ( 'There are %d total human images.'  %  len ( human_files ))
There are 13233 total human images.

Step 1: Detecting face

We will use Haar feature-based cascade classifiers in OpenCV to detect faces in images. OpenCV provides a number of pre-trained face detection models that are stored in github as XML files . We have downloaded one detection model, and stores it in the haarcascadesdirectory.

In the following code unit, we will demonstrate how to use this detection model to find faces in the sample image.

In [3]:
Import  cv2                 
import  matplotlib.pyplot  as  plt                         
% matplotlib inline                               

# Extract the pre-trained face detection model 
face_cascade  =  cv2 . CascadeClassifier ( ' haarcascades /haarcascade_frontalface_alt.xml' )

# Load color (channel order is BGR) image 
img  =  cv2 . imread ( human_files [ 3 ])

# Grayscale the BGR image 
gray  =  cv2 . cvtColor ( img ,  cv2 . COLOR_BGR2GRAY )

# Find the 
faces  in the image faces =  face_cascade . detectMultiScale ( gray )

# Print the number 
of faces detected in the image print ( 'Number of faces detected:' ,  len ( faces ))

# Get the recognition box 
for  each detected face for ( x , y , w , h )  in  faces : 
    # Draw the recognition frame 
    cv2 in the face image . rectangle ( img ,( x , y ),( x + w , y + h ), ( 255 , 0 , 0 ), 2 )
    
# Convert BGR image to RGB image to print 
cv_rgb  =  cv2 . cvtColor ( img ,  cv2 . COLOR_BGR2RGB )

# Show image with the identification box 
plt . imshow ( cv_rgb ) 
plt . show ()
Number of faces detected: 1

Converting an image to a grayscale image is a common process before using any of the inspection models. detectMultiScaleFunction is used is stored in face_cascadethe data input gray image are classified.

In the code above faces, the recognized face information is saved as a numpy array. Each of the lines represents a detected face. The data includes the following four information: the first two elements x, ythe x and y coordinates representing the upper left corner of the recognition frame (refer to the figure above, pay attention to the direction of the y coordinate and our default direction). different); the element represents two identification frame extending in both directions x and y axis length w, and d.

Write a face recognizer¶

We can wrap this program as a function. The input of this function is the path of the face image . When the image contains a face, the function returns True, and vice versa False. The function definition is as follows.

In [4]:
# If the image represented by the img_path path detects a face, return "True" 
def  face_detector ( img_path ): 
    img  =  cv2 . imread ( img_path ) 
    gray  =  cv2 . cvtColor ( img ,  cv2 . COLOR_BGR2GRAY ) 
    faces  =  face_cascade . detectMultiScale ( gray ) 
    return  Len ( faces )  >  0

[Exercise] Evaluate the face detection model¶


Question 1:

In the bottom of the block, a face_detectorfunction is calculated:

  • human_filesOf the top 100 images, what is the ratio of images that can detect faces ?
  • dog_filesOf the top 100 images, what is the ratio of images that can detect faces ?

Ideally, the probability of detecting a face in a person's image should be 100%, and the probability of detecting a face in a dog image should be 0%. You will find that our algorithm is not perfect, but the results are still acceptable. We extract the file paths of the first 100 images from each data set and store them in the human_files_shortsum dog_files_short.

In [5]:
NeuralNetClassifierhuman_files_short  =  human_files [: 100 ] 
dog_files_short  =  train_files [: 100 ] 
## Do not modify the code above


## TODO: dog_files_short based human_files_short and 
test image ## in the performance of face_detector 
Human  =  0 
Dog  =  0 
for  IMG  in  NeuralNetClassifierhuman_files_short : 
    IF  face_detector ( IMG ):  Human  =  Human  + . 1 
Print ( "-> Detected {} Images of Human " . format ( human )) 
for  img  in  dog_files_short : 
    if  face_detector ( img ):  dog  = Dog  + 1 
print ( "-> Detected {} images of dog" . format ( dog ))
-> Detected 100 images of human
-> Detected 11 images of dog

Question 2:

As far as the algorithm is concerned, the key to the success of the algorithm is whether the user can provide a face image with clear facial features. So, do you think that such a requirement is reasonable for the user in actual use? If you feel unreasonable, can you think of a way to detect a face even if there are no clear facial features in the image?

Answer: It does not Sence Because the make at The Machine. Absolutely CAN BE Within last of Better in Detecting Human Faces We CAN use the Add Image Augmentation to Random Noise in at The Picture, Image Making at The Vague to the Solve the this problem...


Optional:

We recommend using opencv's face detection model in your algorithm to detect human images, but you are free to explore other methods, especially try to use deep learning to solve it :). Please use the code unit below to design and test your face monitoring algorithm. If you decide to complete this _select _ task, you need to report the performance of the algorithm on each data set.

In [6]:
## (Optional) TODO: Report the performance of another face detection algorithm on the LFW dataset 
### You can use the required number of code units at will.

Step 2: Detect dog licking

In this section, we use the pre-trained ResNet-50 model to detect dogs in the image. The first line of code below is to download the network structure parameters of the ResNet-50 model and the pre-training weights based on the ImageNet data set.

ImageNet This is currently a very popular data set that is often used to test algorithms related to computer vision tasks such as image classification. It contains more than 10 million URLs, each linked to an image of an object corresponding to 1000 categories . When you enter an image, the ResNet-50 model returns a prediction of the object in the image.

In [7]:
From  keras.applications.resnet50  import  ResNet50

# Define ResNet50 model 
ResNet50_model  =  ResNet50 ( weights = ' imagenet ' )
Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5
102858752/102853048 [=================================================================

Data preprocessing

  • When using TensorFlow as the backend, in Keras, the CNN input is a 4-dimensional array (also known as a 4-dimensional tensor) with dimensions in dimensions (nb_samples, rows, columns, channels). Wherein nb_samplesrepresents the total number of images (or samples), rows, columns, and channelsthe number of lines, respectively, representing an image, the number of columns and number of channels.
  • Below path_to_tensorfunction realize a file path character string type color image as input and returns a four-dimensional tensor, as input Keras CNN. Because our input image is a color image, they have the three channels ( channelsas 3).
    1. The function first reads an image and then scales it to a 224×224 image.
    2. Subsequently, the image is adjusted to have a tensor of 4 dimensions.
    3. For any input image, the dimensions of the last returned tensor are: (1, 224, 224, 3).
  • paths_to_tensorThe function takes a numpy array of strings of image paths as input and returns a 4-dimensional tensor with dimensions of each dimension (nb_samples, 224, 224, 3). Here, nb_samplesis the number of samples or the number of images in the data of the provided image path. You can also nb_samplesbe understood as a three-dimensional data set the number of tensors (each represented by a three-dimensional tensor different images.
In [8]:
From  keras.preprocessing  import  image                   
from  tqdm  import  tqdm

Def  path_to_tensor ( img_path ): 
    # Load RGB images with PIL as PIL.Image.Image type 
    img  =  image . load_img ( img_path ,  target_size = ( 224 ,  224 )) 
    # Convert PIL.Image.Image type to format (224, 224, 3) 3-dimensional tensor 
    x  =  image . img_to_array ( img ) 
    # Convert the 3-dimensional tensor into a 4-dimensional tensor of the form (1, 224, 224, 3) and return 
    return  np . expand_dims ( x ,  Axis = 0 )

Def  paths_to_tensor ( img_paths ): 
    list_of_tensors  =  [ path_to_tensor ( img_path )  for  img_path  in  tqdm ( img_paths )] 
    return  np . vstack ( list_of_tensors )

Prediction based on ResNet-50 architecture

For the four-dimensional tensors obtained through the above steps, some additional processing is required before inputting them to the ResNet-50 network, or other similar pre-training models in Keras:

  1. First, the channel order of these images is RGB, and we need to rearrange their channel order to BGR.
  2. Second, the input to the pre-training model is subjected to an additional normalization process. Therefore, we also want to normalize these tensors here, that is, subtract the pixel mean [103.939, 116.779, 123.68](in RGB mode, calculated from all ImageNet images) for all pixels of all images .

Import preprocess_inputfunction implements these features. If you are very interested, you can here to see preprocess_inputthe code.

After implementing the image processing part, we can use the model to make predictions. By this step predictto implement a method, which returns an i-th vector element of a vector represents the probability that the i-th image belongs ImageNet categories. This is done by the ResNet50_predict_labelsimplemented function.

By taking the argmax function on the predicted vector (finding the subscript number with the largest probability value), we can get an integer, which is the class of the object predicted by the model. Further according to this list , we can know that which specific breed of dog.

In [9]:
From  keras.applications.resnet50  import  preprocess_input ,  decode_predictions 
def  ResNet50_predict_labels ( img_path ): 
    # return the predicted vector of the image of the img_path path 
    img  =  preprocess_input ( img_path )  # I cannot use directory because I don't know where udacity stores the files 
    # img = preprocess_input (path_to_tensor (img_path)) 
    return  NP . the argmax ( ResNet50_model . Predict ( IMG ))

Complete the dog detection model¶

In the study list , you will notice that the dog category corresponding number is 151-268. Therefore, when checking the model pre-trained dogs comprising determining whether the image, we only need to check as to ResNet50_predict_labelswhether a function returns a value between 151 and 268 (comprising a section endpoint).

We do this through these ideas below dog_detectorfunction, if it is detected from the image into the dog returns True, otherwise it returns False.

In [10]:
Def  dog_detector ( img_path ): 
    prediction  =  ResNet50_predict_labels ( img_path ) 
    return  (( prediction  <=  268 )  &  ( prediction  >=  151 )) 

[Job] Evaluation of dog detection model¶


Question 3:

In the bottom of the block, a dog_detectorfunction is calculated:

  • human_files_shortWhat percentage of the dog is detected in the image?
  • dog_files_shortWhat percentage of the dog is detected in the image?
In [11]:
### TODO: Test the performance of the dog_detector function in human_files_short and dog_files_short 
human_count  =  0 
dogs_count  =  0


humans  =  paths_to_tensor ( NeuralNetClassifierhuman_files_short ) 
Dogs  =  paths_to_tensor ( dog_files_short ) 
for  Human  in  humans : # (224, 244,. 3) 
    Human  =  NP . expand_dims ( Human ,  Axis = 0 )  # the I CAN Not use Directory Because the I do Not know WHERE Udacity 
    Stores the files if  dog_detector ( human ):  human_count = human_count + 1 
for  dog In  dogs : 
    dog  =  np . expand_dims ( dog ,  axis = 0 )  # I cannot use directory because I don't know where udacity stores the files 
    if  dog_detector ( dog ):  dogs_count = dogs_count + 1

Print ( "Error: {} / {} " . format ( human_count + 1e-10 ,  dogs_count + 1e-10 ))
100%|██████████| 100/100 [00:00<00:00, 360.82it/s]
100%|██████████| 100/100 [00:00<00:00, 103.81it/s]
Error: 1e-10/100.0000000001

Step 3: Create a CNN from the beginning to classify the dog breed¶

Now we have implemented a function that recognizes humans and dogs in the image. But we need a further way to identify the dog's category. In this step, you need to implement a convolutional neural network to classify the breed of the dog. You need to implement your convolutional neural network from scratch (at this stage, you can't use migration learning), and you need to achieve more than 1% test set accuracy. In the five steps of this project, you also have the opportunity to use migration learning to achieve a model with greatly improved accuracy.

When adding a convolutional layer, be careful not to add too many (trainable) layers. More parameters mean longer training time, which means you are more likely to need a GPU to speed up the training process. Fortunately, Keras provides the functions needed to easily predict the time it takes to spend each iteration (epoch). You can infer the training time required for your algorithm.

It is worth noting that categorizing the image of a dog is a challenging task. Because even a normal person, it is difficult to distribute the Leytan and Welsh Springer Spaniel.

Brittany Welsh Springer Spaniel

It is not difficult to find that other dog breeds have small inter-class differences (such as Golden Retriever and American Water Hound).

Curly-Coated Retriever American Water Spaniel

Similarly, labradors are available in yellow, brown and black. Then the vision-based algorithm you design will have to overcome this higher inter-class difference to achieve the ability to classify these same-color dogs into the same breed.

Yellow Labrador Brown Labrador (Chocolate Labrador) Black Labrador

We also mentioned that the random classification will give a very low result: regardless of the slight imbalance of the variety, the probability of randomly guessing the correct variety is 1/133, and the corresponding accuracy is less than 1%.

Remember that in the field of deep learning, practice is much higher than theory. Try a lot of different frameworks, trust your instincts! Of course, have fun!

Data preprocessing

By dividing the pixel value of each image by 255, we normalized the image.

In [12]:
From  PIL  import  ImageFile                             
ImageFile . LOAD_TRUNCATED_IMAGES  =  True                 

# Keras data preprocessing process 
train_tensors  =  paths_to_tensor ( train_files ) . astype ( 'float32' ) / 255 
valid_tensors  =  paths_to_tensor ( valid_files ) . astype ( 'float32' ) / 255 
test_tensors  =  paths_to_tensor ( test_files ) . astype ( 'float32' ) / 255
100%|██████████| 6680/6680 [01:14<00:00, 89.12it/s] 
100%|██████████| 835/835 [00:08<00:00, 98.94it/s] 
100%|██████████| 836/836 [00:08<00:00, 99.81it/s] 

[Training] model architecture

Create a convolutional neural network to classify dog ​​breeds. In the end, you execute a block of code model.summary()to output summary information about your model.

We have already imported some of the required Python libraries for you, and you can import them yourself if needed. If you are having trouble with the process, here is a little hint for you - the model can achieve more than 1% test accuracy in 5 epoch and can be trained quickly on the CPU.

Sample CNN


Question 4:

In the code block below, try to use Keras to build the architecture of the convolutional network and answer related questions.

  1. You can try to build a model of a convolutional network yourself, then you need to answer the specific steps you took to build the convolutional network (what layers are used) and why.
  2. You can also build a convolutional network according to the steps suggested in the figure above, so please explain why the above architecture can perform well on this issue.

Reply:

Functions of each layer:

  • Conv2D: To detect spacial area
  • MaxPooling: To reduce the number of weights needed (compress layer)
  • Batch Normalization: Normalize the data so that the model can fit the data better (the intuition is that the normalization create more space between data pointss so that the classification can be better. although normalizations don't change the result the riotically, they do help in practice. )
  • Activation(relu): relu guarantee that the zero-gradient problems don't exist. It is also zero centered to avoid zig-zag into global minimum.
  • GlobalAveragePooling: the same function as MaxPooling (reduce weights needed)
  • Dense: final calculation without spacial properties and classification into 133 categories.
In [13]:
From  keras.layers  import  Conv2D ,  MaxPooling2D ,  GlobalAveragePooling2D ,  BatchNormalization ,  Activation 
from  keras.layers  import  Dropout ,  Flatten ,  Dense 
from  keras.models  import  Sequential

Print  
model  =  Sequential ()

Model . the Add ( Conv2D ( 16 ,  ( . 3 ,  . 3 ),  input_shape = ( 224 , 224 , . 3 ), Activation = None ,  padding = "Valid" )) 
Model . the Add ( MaxPooling2D (( 2 ,  2 ))) 
Model . Add ( BatchNormalization ()) 
model . add ( Activation ( 'relu')) 
Model . The Add ( Conv2D ( 32 ,  ( . 3 ,  . 3 ),  Activation = None ,  padding = "Valid" )) 
Model . The Add ( MaxPooling2D (( 2 ,  2 ))) 
Model . The Add ( BatchNormalization ()) 
Model . Add ( Activation ( 'relu' )) 
model . add ( Conv2D ( 64,  ( 3 ,  3 ),  activation = None ,  padding = "valid" )) 
model . add ( MaxPooling2D (( 2 ,  2 ))) 
model . add ( BatchNormalization ()) 
model . add ( Activation ( 'relu' )) 
Model . add ( Conv2D ( 128 ,  ( 3 ,  3 ),  activation =None ,  padding = "valid" )) 
model . add ( MaxPooling2D (( 2 ,  2 ))) 
model . add ( BatchNormalization ( ) ) 
model . add ( Activation ( 'relu' )) 
model . add ( GlobalAveragePooling2D ( data_format = None ))) 
model . add ( Dense ( 128 ,  activation ='relu' )) 
model . add ( Dense ( 133 ,  activation = 'softmax' ))

### TODO: Define your network architecture
                 
Model . summary ()
_________________________________________________________________
Layer (type) Output Shape Param #   
=========================================================== ===============
Conv2d_1 (Conv2D) (None, 222, 222, 16) 448       
_________________________________________________________________
Max_pooling2d_2 (MaxPooling2 (None, 111, 111, 16) 0         
_________________________________________________________________
Batch_normalization_1 (Batch (None, 111, 111, 16) 64        
_________________________________________________________________
Activation_50 (Activation) (None, 111, 111, 16) 0         
_________________________________________________________________
Conv2d_2 (Conv2D) (None, 109, 109, 32) 4640      
_________________________________________________________________
Max_pooling2d_3 (MaxPooling2 (None, 54, 54, 32) 0         
_________________________________________________________________
Batch_normalization_2 (Batch (None, 54, 54, 32) 128       
_________________________________________________________________
Activation_51 (Activation) (None, 54, 54, 32) 0         
_________________________________________________________________
Conv2d_3 (Conv2D) (None, 52, 52, 64) 18496     
_________________________________________________________________
Max_pooling2d_4 (MaxPooling2 (None, 26, 26, 64) 0         
_________________________________________________________________
Batch_normalization_3 (Batch (None, 26, 26, 64) 256       
_________________________________________________________________
Activation_52 (Activation) (None, 26, 26, 64) 0         
_________________________________________________________________
Conv2d_4 (Conv2D) (None, 24, 24, 128) 73856     
_________________________________________________________________
Max_pooling2d_5 (MaxPooling2 (None, 12, 12, 128) 0         
_________________________________________________________________
Batch_normalization_4 (Batch (None, 12, 12, 128) 512       
_________________________________________________________________
Activation_53 (Activation) (None, 12, 12, 128) 0         
_________________________________________________________________
Global_average_pooling2d_1 ( (None, 128) 0         
_________________________________________________________________
Dense_1 (Dense) (None, 128) 16512     
_________________________________________________________________
Dense_2 (Dense) (None, 133) 17157     
=========================================================== ===============
Total params: 132,069
Trainable params: 131,589
Non-trainable params: 480
_________________________________________________________________
In [14]:
## Compile model 
model . compile ( optimizer = 'rmsprop' ,  loss = 'categorical_crossentropy' ,  metrics = [ 'accuracy' ])

[Exercise] training model¶


Question 5:

Train the model in the code unit below. Use model checkpointing to store the model with the lowest validation set loss.

Topics can be: You can also do the training set data enhancement , to optimize the performance of the model.

In [15]:
From  keras.callbacks  import  ModelCheckpoint  

### TODO: Set the number of epochs for the training model

Epochs  =  5

### Do not modify the code below

checkpointer  =  ModelCheckpoint ( filepath = 'saved_models / weights.best.from_scratch.hdf5' ,  
                               verbose = . 1 ,  save_best_only = True )

Model . fit ( train_tensors ,  train_targets ,  
          validation_data = ( valid_tensors ,  valid_targets ), 
          epochs = epochs ,  batch_size = 20 ,  callbacks = [ checkpointer ],  verbose = 1 )
Train on 6680 samples, validate on 835 samples
Epoch 1/5
6660/6680 [============================>.] - ETA: 0s - loss: 4.7177 - acc: 0.0281Epoch 00001: Val_loss improved from inf to 4.84216, saving model to saved_models/weights.best.from_scratch.hdf5
6680/6680 [=============================== - 28s 4ms/step - loss: 4.7170 - acc: 0.0280 - val_loss : 4.8422 - val_acc: 0.0287
Epoch 2/5
6660/6680 [============================>.] - ETA: 0s - loss: 4.3129 - acc: 0.0626Epoch 00002: Val_loss improved from 4.84216 to 4.39909, saving model to saved_models/weights.best.from_scratch.hdf5
6680/6680 [=============================== - 27s 4ms/step - loss: 4.3119 - acc: 0.0629 - val_loss : 4.3991 - val_acc: 0.0695
Epoch 3/5
6660/6680 [============================>.] - ETA: 0s - loss: 4.0237 - acc: 0.0847Epoch 00003: Val_loss did not improve
6680/6680 [================================ 27= 4ms/step - loss: 4.0236 - acc: 0.0847 - val_loss : 4.4282 - val_acc: 0.0707
Epoch 4/5
6660/6680 [============================>.] - ETA: 0s - loss: 3.8235 - acc: 0.1066Epoch 00004: Val_loss improved from 4.39909 to 4.11185, saving model to saved_models/weights.best.from_scratch.hdf5
6680/6680 [=============================== - 27s 4ms/step - loss: 3.8239 - acc: 0.1066 - val_loss : 4.1119 - val_acc: 0.0838
Epoch 5/5
6660/6680 [============================>] - ETA: 0s - loss: 3.6321 - acc: 0.1350Epoch 00005: Val_loss did not improve
6680/6680 [================================ 27= 4ms/step - loss: 3.6327 - acc: 0.1350 - val_loss : 4.1317 - val_acc: 0.0946
Out[15]:
<keras.callbacks.History at 0x7fb899dc4be0>
In [16]:
## Load the model with the best validation loss

Model . load_weights ( 'saved_models/weights.best.from_scratch.hdf5' )

Test model¶

Try your model on the test data set of the dog image. Ensure test accuracy is greater than 1%.

In [17]:
# Get the test data set index predicted image for each dog breeds 
dog_breed_predictions  =  [ NP . The argmax ( Model . Predict ( NP . Expand_dims ( Tensor ,  Axis = 0 )))  for  Tensor  in  test_tensors ]

# Test report accuracy 
test_accuracy  =  100 * NP . SUM ( NP . Array ( dog_breed_predictions ) == NP . The argmax ( test_targets ,  Axis = . 1 )) / len ( dog_breed_predictions ) 
Print ( 'the Test Accuracy: % .4f %% '  %  Test_accuracy )
Test accuracy: 9.2105%

Step 4: Use a CNN to distinguish the breed of the dog¶

Using the Transfer Learning approach can help us significantly reduce training time without compromising accuracy. In the following steps, you can try to use training to train your own CNN.

Get the feature vector extracted from the image (Bottleneck Features)

In [18]:
Bottleneck_features  =  np . load ( '/data/bottleneck_features/DogVGG16Data.npz' ) 
train_VGG16  =  bottleneck_features [ 'train' ] 
valid_VGG16  =  bottleneck_features [ 'valid' ] 
test_VGG16  =  bottleneck_features [ 'test' ]

Model architecture

The model uses the pre-trained VGG-16 model as a fixed image feature extractor, where the output of the last layer of the VGG-16 convolutional layer is directly imported into our model. We only need to add a global average pooling layer and a fully connected layer, where the fully connected layer uses the softmax activation function, which contains one node for each dog type.

In [19]:
VGG16_model  =  Sequential () 
VGG16_model . add ( GlobalAveragePooling2D ( input_shape = train_VGG16 . shape [ 1 :])) 
VGG16_model . add ( Dense ( 133 ,  activation = 'softmax' ))

VGG16_model . summary ()
_________________________________________________________________
Layer (type) Output Shape Param #   
=========================================================== ===============
Global_average_pooling2d_2 ( (None, 512) 0         
_________________________________________________________________
Dense_3 (Dense) (None, 133) 68229     
=========================================================== ===============
Total params: 68,229
Trainable params: 68,229
Non-trainable params: 0
_________________________________________________________________
In [20]:
## Compiling the model

VGG16_model . compile ( loss = 'categorical_crossentropy' ,  optimizer = 'rmsprop' ,  metrics = [ 'accuracy' ])
In [21]:
## Training Model

checkpointer  =  ModelCheckpoint ( filepath = 'saved_models / weights.best.VGG16.hdf5' ,  
                               verbose = . 1 ,  save_best_only = True )

VGG16_model . fit ( train_VGG16 ,  train_targets ,  
          validation_data = ( valid_VGG16 ,  valid_targets ), 
          epochs = 20 ,  batch_size = 20 ,  callbacks = [ checkpointer ],  verbose = 1 )
Train on 6680 samples, validate on 835 samples
Epoch 1/20
6480/6680 [============================>] - ETA: 0s - loss: 12.3670 - acc: 0.1296Epoch 00001: Val_loss improved from inf to 10.83074, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================================================================================ : 10.8307 - val_acc: 0.2216
Epoch 2/20
6480/6680 [============================>.] - ETA: 0s - loss: 10.1562 - acc: 0.2878Epoch 00002: Val_loss improved from 10.83074 to 10.14428, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [=============================================================================================================== : 10.1443 - val_acc: 0.2671
Epoch 3/20
6520/6680 [============================>.] - ETA: 0s - loss: 9.5866 - acc: 0.3538Epoch 00003: Val_loss improved from 10.14428 to 9.84419, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [=========================================================================================================== : 9.8442 - val_acc: 0.3138
Epoch 4/20
6660/6680 [============================>.] - ETA: 0s - loss: 9.3600 - acc: 0.3785Epoch 00004: Val_loss improved from 9.84419 to 9.61646, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================================================================================ : 9.6165 - val_acc: 0.3365
Epoch 5/20
6560/6680 [============================>.] - ETA: 0s - loss: 9.2345 - acc: 0.3986Epoch 00005: Val_loss improved from 9.61646 to 9.60222, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [=============================================================================================================== : 9.6022 - val_acc: 0.3425
Epoch 6/20
6640/6680 [============================>] - ETA: 0s - loss: 9.1239 - acc: 0.4086Epoch 00006: Val_loss improved from 9.60222 to 9.32880, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================================================================== : 9.3288 - val_acc: 0.3569
Epoch 7/20
6640/6680 [============================>.] - ETA: 0s - loss: 8.9798 - acc: 0.4230Epoch 00007: Val_loss improved from 9.32880 to 9.28944, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [========================================================================================================== : 9.2894 - val_acc: 0.3581
Epoch 8/20
6620/6680 [============================>.] - ETA: 0s - loss: 8.7492 - acc: 0.4344Epoch 00008: Val_loss improved from 9.28944 to 9.01291, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [===================================================================================================== : 9.0129 - val_acc: 0.3844
Epoch 9/20
6540/6680 [============================>.] - ETA: 0s - loss: 8.5204 - acc: 0.4518Epoch 00009: Val_loss improved from 9.01291 to 8.87106, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [=========================================================================================================== : 8.8711 - val_acc: 0.4000
Epoch 10/20
6580/6680 [============================>.] - ETA: 0s - loss: 8.4413 - acc: 0.4617Epoch 00010: Val_loss did not improve
6680/6680 [===================================================================================================== : 8.9213 - val_acc: 0.3868
Epoch 11/20
6480/6680 [============================>.] - ETA: 0s - loss: 8.3984 - acc: 0.4662Epoch 00011: Val_loss improved from 8.87106 to 8.86277, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================================================================================ : 8.8628 - val_acc: 0.3964
Epoch 12/20
6640/6680 [============================>.] - ETA: 0s - loss: 8.3165 - acc: 0.4714Epoch 00012: Val_loss improved from 8.86277 to 8.82876, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================================================================================ : 8.8288 - val_acc: 0.4024
Epoch 13/20
6500/6680 [============================>.] - ETA: 0s - loss: 8.2208 - acc: 0.4752Epoch 00013: Val_loss improved from 8.82876 to 8.69286, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [=============================================================================================================== : 8.6929 - val_acc: 0.4000
Epoch 14/20
6500/6680 [============================>.] - ETA: 0s - loss: 8.1403 - acc: 0.4854Epoch 00014: Val_loss improved from 8.69286 to 8.67098, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [======================================================= 287us/step - loss: 8.1342 - acc: 0.4856 - val_loss : 8.6710 - val_acc: 0.4024
Epoch 15/20
6580/6680 [============================>.] - ETA: 0s - loss: 8.0924 - acc: 0.4916Epoch 00015: Val_loss improved from 8.67098 to 8.60113, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [============================================================================================ : 8.6011 - val_acc: 0.4072
Epoch 16/20
6660/6680 [============================>.] - ETA: 0s - loss: 8.0591 - acc: 0.4935Epoch 00016: Val_loss did not improve
6680/6680 [================================================================================================================== : 8.6584 - val_acc: 0.4132
Epoch 17/20
6600/6680 [============================>.] - ETA: 0s - loss: 8.0435 - acc: 0.4950Epoch 00017: Val_loss did not improve
6680/6680 [============================================================================================== : 8.6576 - val_acc: 0.4156
Epoch 18/20
6500/6680 [============================>.] - ETA: 0s - loss: 8.0554 - acc: 0.4965Epoch 00018: Val_loss did not improve
6680/6680 [==============================] - 2s 295us/step - loss: 8.0391 - acc: 0.4973 - val_loss : 8.6481 - val_acc: 0.4144
Epoch 19/20
6540/6680 [============================>.] - ETA: 0s - loss: 7.9809 - acc: 0.4983Epoch 00019: Val_loss improved from 8.60113 to 8.50764, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================================ 293us/step - loss: 7.9802 - acc: 0.4985 - val_loss : 8.5076 - val_acc: 0.4287
Epoch 20/20
6500/6680 [============================>] - ETA: 0s - loss: 7.8698 - acc: 0.5054Epoch 00020: Val_loss improved from 8.50764 to 8.39838, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [================================ 2= 279us/step - loss: 7.8668 - acc: 0.5054 - val_loss : 8.3984 - val_acc: 0.4275
Out[21]:
<keras.callbacks.History at 0x7fb8776d0160>
In [22]:
## Load the model with the best validation loss

VGG16_model . load_weights ( 'saved_models/weights.best.VGG16.hdf5' )

Test model¶

Now, we can test how effective this CNN is in identifying the breed in the dog image test data set. We print out the test accuracy below.

In [23]:
# Get the test data set index predicted image for each dog breeds 
VGG16_predictions  =  [ NP . The argmax ( VGG16_model . Predict ( NP . Expand_dims ( Feature ,  Axis = 0 )))  for  Feature  in  test_VGG16 ]

# Test report accuracy 
test_accuracy  =  100 * NP . SUM ( NP . Array ( VGG16_predictions ) == NP . The argmax ( test_targets ,  Axis = . 1 )) / len ( VGG16_predictions ) 
Print ( 'the Test Accuracy: % .4f %% '  %  Test_accuracy )
Test accuracy: 41.5072%

Use the model to predict dog breeds¶

In [24]:
From  extract_bottleneck_features  import  *

DEF  VGG16_predict_breed ( img_path ): 
    # extracted bottleneck characterized 
    bottleneck_feature  =  extract_VGG16 ( path_to_tensor ( img_path )) 
    # obtain prediction vector 
    predicted_vector  =  VGG16_model . Predict ( bottleneck_feature ) 
    # Returns species model prediction dog 
    return  dog_names [ NP . the argmax ( predicted_vector )]

Step 5: Create a CNN to classify the breed of the dog (using migration learning)

Now you will use migration learning to build a CNN that will identify the dog breed from the image. Your CNN must have an accuracy of at least 60% on the test set.

In step 4, we used migration learning to create a CNN using a feature vector based on VGG-16 extraction. In this section, you must use another pre-training model to build a CNN. To make this task easier to implement, we have pre-trained several networks available in keras in advance:

These files are named as:

Dog{network}Data.npz

Which {network}may be VGG19, Resnet50, InceptionV3or Xceptiona of. Choose a top network architecture, they have been stored in the directory /data/bottleneck_features/in.

[Exercise] Get the feature vector of the model¶

In the code block below, extract the training, test, and validation set corresponding to the bottleneck feature by running the code below.

bottleneck_features = np.load('/data/bottleneck_features/Dog{network}Data.npz')
train_{network} = bottleneck_features['train']
valid_{network} = bottleneck_features['valid']
test_{network} = bottleneck_features['test']
In [25]:
### TODO: Get the bottleneck feature from another pre-trained CNN 
bottleneck_features  =  np . load ( '/data/bottleneck_features/DogResnet50Data.npz' ) 
train_Resnet50  =  bottleneck_features [ 'train' ] 
valid_Resnet50  =  bottleneck_features [ 'valid' ] 
test_Resnet50  =  Bottleneck_features [ 'test' ]

[Training] model architecture

Create a CNN to classify dog ​​breeds. At the end of your code unit block, output the structure of the network by running the following code:

    <your model's name>.summary()


Question 6:

Try Keras in the code block below to build the final network architecture, answer the steps and steps you take to implement the final CNN architecture, and describe why you used the network architecture during the migration learning process.

Reply:

How to transfer:

- (1): create a model
- (2): add GlobalAveragePooling to reduce weights between layers
- (3): add Dense layer to preform classification

Why trasnfer learning:

1. Transfer learning reduce the training time by freezing weight
2. Transfer learning reduce the computational power needed by freezing weight
3. Transfered models are easier to get to global minimum because Resnet50 is already trained on imagenet, which means it has a great ability to detect features. It is easier for our classifier to classify things on generated features by Resnet than to extract features and then classify by itself.
In [26]:
### TODO: Define your framework 
Resnet50  =  Sequential () 
Resnet50 . add ( GlobalAveragePooling2D ( input_shape = train_Resnet50 . shape [ 1 :])) 
Resnet50 . add ( Dense ( 133 ,  activation = 'softmax' ))

Resnet50 . summary ()
_________________________________________________________________
Layer (type) Output Shape Param #   
=========================================================== ===============
Global_average_pooling2d_3 ( (None, 2048) 0         
_________________________________________________________________
Dense_4 (Dense) (None, 133) 272517    
=========================================================== ===============
Total params: 272,517
Trainable params: 272,517
Non-trainable params: 0
_________________________________________________________________
In [27]:
### TODO: Compile model 
Resnet50 . compile ( loss = 'categorical_crossentropy' ,  optimizer = 'rmsprop' ,  metrics = [ 'accuracy' ])

[Exercise] training model¶

Question 7:

Train your model in the code unit below. Use model checkpointing to store the model with the lowest validation set loss.

Of course, you can also carry out the training set data enhancement in order to optimize the performance of the model, but this step is not necessary.

In [28]:
### TODO: Training model 
checkpointer  =  ModelCheckpoint ( filepath = 'saved_models/weights.best.Resnet50.hdf5' ,  
                               verbose = 1 ,  save_best_only = True )

Resnet50 . fit ( train_Resnet50 ,  train_targets ,  
          validation_data = ( valid_Resnet50 ,  valid_targets ), 
          epochs = 20 ,  batch_size = 32 ,  callbacks = [ checkpointer ],  verbose = 1 )
Train on 6680 samples, validate on 835 samples
Epoch 1/20
6592/6680 [============================>.] - ETA: 0s - loss: 1.7790 - acc: 0.5731Epoch 00001: Val_loss improved from inf to 0.89267, saving model to saved_models/weights.best.Resnet50.hdf5
6680/6680 [======================================================================================================== : 0.8927 - val_acc: 0.7186
Epoch 2/20
6624/6680 [============================>.] - ETA: 0s - loss: 0.4567 - acc: 0.8601Epoch 00002: Val_loss improved from 0.89267 to 0.72599, saving model to saved_models/weights.best.Resnet50.hdf5
6680/6680 [=============================================================================================================== : 0.7260 - val_acc: 0.7617
Epoch 3/20
6592/6680 [============================>.] - ETA: 0s - loss: 0.2608 - acc: 0.9196Epoch 00003: Val_loss improved from 0.72599 to 0.61686, saving model to saved_models/weights.best.Resnet50.hdf5
6680/6680 [================================================================================================================= : 0.6169 - val_acc: 0.8120
Epoch 4/20
6368/6680 [===========================>..] - ETA: 0s - loss: 0.1641 - acc: 0.9529Epoch 00004: Val_loss improved from 0.61686 to 0.61020, saving model to saved_models/weights.best.Resnet50.hdf5
6680/6680 [=========================================================================================================== : 0.6102 - val_acc: 0.8228
Epoch 5/20
6496/6680 [============================>.] - ETA: 0s - loss: 0.1079 - acc: 0.9697Epoch 00005: Val_loss did not improve
6680/6680 [============================================================================================================== : 0.6646 - val_acc: 0.8108
Epoch 6/20
6368/6680 [===========================>..] - ETA: 0s - loss: 0.0730 - acc: 0.9788Epoch 00006: Val_loss did not improve
6680/6680 [========================================================== 167us/step - loss: 0.0728 - acc: 0.9792 - val_loss : 0.6233 - val_acc: 0.8180
Epoch 7/20
6592/6680 [============================>.] - ETA: 0s - loss: 0.0535 - acc: 0.9859Epoch 00007: Val_loss did not improve
6680/6680 [==============================] - 1s 162us/step - loss: 0.0532 - acc: 0.9861 - val_loss : 0.6672 - val_acc: 0.8144
Epoch 8/20
6592/6680 [============================>.] - ETA: 0s - loss: 0.0375 - acc: 0.9909Epoch 00008: Val_loss did not improve
6680/6680 [============================================================================================================= : 0.6589 - val_acc: 0.8228
Epoch 9/20
6336/6680 [===========================>..] - ETA: 0s - loss: 0.0262 - acc: 0.9959Epoch 00009: Val_loss did not improve
6680/6680 [=========================================================================================================== : 0.7014 - val_acc: 0.8228
Epoch 10/20
6656/6680 [============================>.] - ETA: 0s - loss: 0.0200 - acc: 0.9962Epoch 00010: Val_loss did not improve
6680/6680 [================================================================================================================= : 0.6954 - val_acc: 0.8240
Epoch 11/20
6496/6680 [============================>.] - ETA: 0s - loss: 0.0161 - acc: 0.9969Epoch 00011: Val_loss did not improve
6680/6680 [==============================] - 1s 165us/step - loss: 0.0161 - acc: 0.9969 - val_loss : 0.6944 - val_acc: 0.8263
Epoch 12/20
6592/6680 [============================>.] - ETA: 0s - loss: 0.0132 - acc: 0.9977Epoch 00012: Val_loss did not improve
6680/6680 [============================================================================================================== : 0.7255 - val_acc: 0.8335
Epoch 13/20
6336/6680 [===========================>..] - ETA: 0s - loss: 0.0094 - acc: 0.9986Epoch 00013: Val_loss did not improve
6680/6680 [================================================================================================================== : 0.7757 - val_acc: 0.8263
Epoch 14/20
6368/6680 [===========================>..] - ETA: 0s - loss: 0.0083 - acc: 0.9984Epoch 00014: Val_loss did not improve
6680/6680 [==============================] - 1s 157us/step - loss: 0.0082 - acc: 0.9985 - val_loss : 0.7456 - val_acc: 0.8299
Epoch 15/20
6656/6680 [============================>.] - ETA: 0s - loss: 0.0069 - acc: 0.9980Epoch 00015: Val_loss did not improve
6680/6680 [=============================================================================================================== : 0.8275 - val_acc: 0.8275
Epoch 16/20
6656/6680 [============================>.] - ETA: 0s - loss: 0.0062 - acc: 0.9986Epoch 00016: Val_loss did not improve
6680/6680 [=============================================================================================================== : 0.7916 - val_acc: 0.8263
Epoch 17/20
6368/6680 [===========================>..] - ETA: 0s - loss: 0.0057 - acc: 0.9984Epoch 00017: Val_loss did not improve
6680/6680 [==============================] - 1s 157us/step - loss: 0.0063 - acc: 0.9984 - val_loss : 0.8113 - val_acc: 0.8371
Epoch 18/20
6368/6680 [===========================>..] - ETA: 0s - loss: 0.0037 - acc: 0.9989Epoch 00018: Val_loss did not improve
6680/6680 [=================================================================== 159us/step - loss: 0.0041 - acc: 0.9987 - val_loss : 0.8556 - val_acc: 0.8216
Epoch 19/20
6656/6680 [============================>.] - ETA: 0s - loss: 0.0051 - acc: 0.9985Epoch 00019: Val_loss did not improve
6680/6680 [========================================================================================================== : 0.9006 - val_acc: 0.8120
Epoch 20/20
6496/6680 [============================>.] - ETA: 0s - loss: 0.0046 - acc: 0.9994Epoch 00020: Val_loss did not improve
6680/6680 [========================================================================================================== : 0.8716 - val_acc: 0.8275
Out[28]:
<keras.callbacks.History at 0x7fb8c0099a20>
In [29]:
### TODO: Load the model weight with the best validation loss 
Resnet50 . load_weights ( 'saved_models/weights.best.Resnet50.hdf5' )

[Exercise] test model¶

Question 8:

Try your model on the test data set of the dog image. Ensure test accuracy is greater than 60%.

In [30]:
### TODO: calculated on classification accuracy test set 
Print ( test_Resnet50 . Shape ) 
Resnet50_predictions  =  [ NP . The argmax ( Resnet50 . Predict ( NP . Expand_dims ( Feature ,  Axis = 0 )))  for  Feature  in  test_Resnet50 ]

test_accuracy  =  100 * NP . SUM ( NP . Array ( Resnet50_predictions ) == NP . the argmax ( test_targets ,  Axis = . 1 )) / len ( Resnet50_predictions ) 
Print ( 'the Test Accuracy: % .4f %% '  %  test_accuracy )
(836, 1, 1, 2048)
Test accuracy: 80.0239%

[Exercise] Use the model to test the breed of the dog¶

Implement a function whose input is the image path, the function is to predict the category of the corresponding image, and the output is the dog category ( Affenpinscher, Afghan_houndetc.) predicted by your model .

Similar to the simulation function in step 5, your function should contain the following three steps:

  1. Load image features based on selected models (bottleneck features)
  2. Enter image features into your model and return a prediction vector. Note that using the argmax function on this vector returns the sequence number of the dog type.
  3. Defined in step 0 dog_namesarray to return the corresponding dog category name.

Image feature extraction procedure used in the function can be extract_bottleneck_features.pyfound in. At the same time, they should have been imported in the previous code block. The CNN chosen your network, you can use the extract_{network}function to obtain corresponding image features, wherein {network}on behalf of VGG19, Resnet50, InceptionV3, or Xceptiona of.


Question 9:

In [41]:
### TODO: Write a function that takes the path of the image as input 
### and then returns the dog breed predicted by this model 
from  keras.applications.imagenet_utils  import  decode_predictions 
from  keras.models  import  Model

Net  =  ResNet50 ( weights = ' imagenet ' ) 
net . summary () 
intermediate_layer_model  =  Model ( inputs = net . input , 
                                 outputs = net . get_layer ( "avg_pool" ) . output ) 
print ( train_tensors . shape ) 
# standard Resnet 
# for x In train_tensors: 
# x = preprocess_input(x.copy()) 
# preds = submit(x, net) 
# print (preds)
Def  extract_Resnet50 ( tensor ): 
    from  keras.applications.resnet50  import  ResNet50 ,  preprocess_input 
    return  ResNet50 ( weights = ' imagenet ' ,  include_top = False ) . predict ( preprocess_input ( tensor ))

Def  predict ( x ): 
    x  =  preprocess_input ( x . copy ()) 
    x  =  np . expand_dims ( x ,  axis = 0 ) 
    # intermediate_output = intermediate_layer_model.predict(x) 
    intermediate_output  =  extract_Resnet50 ( x ) 
    preds  =  Resnet50 . predict ( intermediate_output ) 
    OUT  =  NP . the argmax ( preds )
    # print(decode_predictions(out, top=5)) 
    return  out
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to                     
=========================================================== =========================================================
Input_40 (InputLayer) (None, 224, 224, 3) 0                                            
__________________________________________________________________________________________________
Conv1 (Conv2D) (None, 112, 112, 64) 9472 input_40[0][0]                   
__________________________________________________________________________________________________
Bn_conv1 (BatchNormalization) (None, 112, 112, 64) 256 conv1[0][0]                      
__________________________________________________________________________________________________
Activation_1916 (Activation) (None, 112, 112, 64) 0 bn_conv1[0][0]                   
__________________________________________________________________________________________________
Max_pooling2d_44 (MaxPooling2D) (None, 55, 55, 64) 0 activation_1916[0][0]            
__________________________________________________________________________________________________
Res2a_branch2a (Conv2D) (None, 55, 55, 64) 4160 max_pooling2d_44[0][0]           
__________________________________________________________________________________________________
Bn2a_branch2a (BatchNormalizati (None, 55, 55, 64) 256 res2a_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1917 (Activation) (None, 55, 55, 64) 0 bn2a_branch2a[0][0]              
__________________________________________________________________________________________________
Res2a_branch2b (Conv2D) (None, 55, 55, 64) 36928 activation_1917[0][0]            
__________________________________________________________________________________________________
Bn2a_branch2b (BatchNormalizati (None, 55, 55, 64) 256 res2a_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1918 (Activation) (None, 55, 55, 64) 0 bn2a_branch2b[0][0]              
__________________________________________________________________________________________________
Res2a_branch2c (Conv2D) (None, 55, 55, 256) 16640 activation_1918[0][0]            
__________________________________________________________________________________________________
Res2a_branch1 (Conv2D) (None, 55, 55, 256) 16640 max_pooling2d_44[0][0]           
__________________________________________________________________________________________________
Bn2a_branch2c (BatchNormalizati (None, 55, 55, 256) 1024 res2a_branch2c[0][0]             
__________________________________________________________________________________________________
Bn2a_branch1 (BatchNormalizatio (None, 55, 55, 256) 1024 res2a_branch1[0][0]              
__________________________________________________________________________________________________
Add_625 (Add) (None, 55, 55, 256) 0 bn2a_branch2c[0][0]              
                                                                 Bn2a_branch1[0][0]               
__________________________________________________________________________________________________
Activation_1919 (Activation) (None, 55, 55, 256) 0 add_625[0][0]                    
__________________________________________________________________________________________________
Res2b_branch2a (Conv2D) (None, 55, 55, 64) 16448 activation_1919[0][0]            
__________________________________________________________________________________________________
Bn2b_branch2a (BatchNormalizati (None, 55, 55, 64) 256 res2b_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1920 (Activation) (None, 55, 55, 64) 0 bn2b_branch2a[0][0]              
__________________________________________________________________________________________________
Res2b_branch2b (Conv2D) (None, 55, 55, 64) 36928 activation_1920[0][0]            
__________________________________________________________________________________________________
Bn2b_branch2b (BatchNormalizati (None, 55, 55, 64) 256 res2b_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1921 (Activation) (None, 55, 55, 64) 0 bn2b_branch2b[0][0]              
__________________________________________________________________________________________________
Res2b_branch2c (Conv2D) (None, 55, 55, 256) 16640 activation_1921[0][0]            
__________________________________________________________________________________________________
Bn2b_branch2c (BatchNormalizati (None, 55, 55, 256) 1024 res2b_branch2c[0][0]             
__________________________________________________________________________________________________
Add_626 (Add) (None, 55, 55, 256) 0 bn2b_branch2c[0][0]              
                                                                 Activation_1919[0][0]            
__________________________________________________________________________________________________
Activation_1922 (Activation) (None, 55, 55, 256) 0 add_626[0][0]                    
__________________________________________________________________________________________________
Res2c_branch2a (Conv2D) (None, 55, 55, 64) 16448 activation_1922[0][0]            
__________________________________________________________________________________________________
Bn2c_branch2a (BatchNormalizati (None, 55, 55, 64) 256 res2c_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1923 (Activation) (None, 55, 55, 64) 0 bn2c_branch2a[0][0]              
__________________________________________________________________________________________________
Res2c_branch2b (Conv2D) (None, 55, 55, 64) 36928 activation_1923[0][0]            
__________________________________________________________________________________________________
Bn2c_branch2b (BatchNormalizati (None, 55, 55, 64) 256 res2c_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1924 (Activation) (None, 55, 55, 64) 0 bn2c_branch2b[0][0]              
__________________________________________________________________________________________________
Res2c_branch2c (Conv2D) (None, 55, 55, 256) 16640 activation_1924[0][0]            
__________________________________________________________________________________________________
Bn2c_branch2c (BatchNormalizati (None, 55, 55, 256) 1024 res2c_branch2c[0][0]             
__________________________________________________________________________________________________
Add_627 (Add) (None, 55, 55, 256) 0 bn2c_branch2c[0][0]              
                                                                 Activation_1922[0][0]            
__________________________________________________________________________________________________
Activation_1925 (Activation) (None, 55, 55, 256) 0 add_627[0][0]                    
__________________________________________________________________________________________________
Res3a_branch2a (Conv2D) (None, 28, 28, 128) 32896 activation_1925[0][0]            
__________________________________________________________________________________________________
Bn3a_branch2a (BatchNormalizati (None, 28, 28, 128) 512 res3a_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1926 (Activation) (None, 28, 28, 128) 0 bn3a_branch2a[0][0]              
__________________________________________________________________________________________________
Res3a_branch2b (Conv2D) (None, 28, 28, 128) 147584 activation_1926[0][0]            
__________________________________________________________________________________________________
Bn3a_branch2b (BatchNormalizati (None, 28, 28, 128) 512 res3a_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1927 (Activation) (None, 28, 28, 128) 0 bn3a_branch2b[0][0]              
__________________________________________________________________________________________________
Res3a_branch2c (Conv2D) (None, 28, 28, 512) 66048 activation_1927[0][0]            
__________________________________________________________________________________________________
Res3a_branch1 (Conv2D) (None, 28, 28, 512) 131584 activation_1925[0][0]            
__________________________________________________________________________________________________
Bn3a_branch2c (BatchNormalizati (None, 28, 28, 512) 2048 res3a_branch2c[0][0]             
__________________________________________________________________________________________________
Bn3a_branch1 (BatchNormalizatio (None, 28, 28, 512) 2048 res3a_branch1[0][0]              
__________________________________________________________________________________________________
Add_628 (Add) (None, 28, 28, 512) 0 bn3a_branch2c[0][0]              
                                                                 Bn3a_branch1[0][0]               
__________________________________________________________________________________________________
Activation_1928 (Activation) (None, 28, 28, 512) 0 add_628[0][0]                    
__________________________________________________________________________________________________
Res3b_branch2a (Conv2D) (None, 28, 28, 128) 65664 activation_1928[0][0]            
__________________________________________________________________________________________________
Bn3b_branch2a (BatchNormalizati (None, 28, 28, 128) 512 res3b_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1929 (Activation) (None, 28, 28, 128) 0 bn3b_branch2a[0][0]              
__________________________________________________________________________________________________
Res3b_branch2b (Conv2D) (None, 28, 28, 128) 147584 activation_1929[0][0]            
__________________________________________________________________________________________________
Bn3b_branch2b (BatchNormalizati (None, 28, 28, 128) 512 res3b_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1930 (Activation) (None, 28, 28, 128) 0 bn3b_branch2b[0][0]              
__________________________________________________________________________________________________
Res3b_branch2c (Conv2D) (None, 28, 28, 512) 66048 activation_1930[0][0]            
__________________________________________________________________________________________________
Bn3b_branch2c (BatchNormalizati (None, 28, 28, 512) 2048 res3b_branch2c[0][0]             
__________________________________________________________________________________________________
Add_629 (Add) (None, 28, 28, 512) 0 bn3b_branch2c[0][0]              
                                                                 Activation_1928[0][0]            
__________________________________________________________________________________________________
Activation_1931 (Activation) (None, 28, 28, 512) 0 add_629[0][0]                    
__________________________________________________________________________________________________
Res3c_branch2a (Conv2D) (None, 28, 28, 128) 65664 activation_1931[0][0]            
__________________________________________________________________________________________________
Bn3c_branch2a (BatchNormalizati (None, 28, 28, 128) 512 res3c_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1932 (Activation) (None, 28, 28, 128) 0 bn3c_branch2a[0][0]              
__________________________________________________________________________________________________
Res3c_branch2b (Conv2D) (None, 28, 28, 128) 147584 activation_1932[0][0]            
__________________________________________________________________________________________________
Bn3c_branch2b (BatchNormalizati (None, 28, 28, 128) 512 res3c_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1933 (Activation) (None, 28, 28, 128) 0 bn3c_branch2b[0][0]              
__________________________________________________________________________________________________
Res3c_branch2c (Conv2D) (None, 28, 28, 512) 66048 activation_1933[0][0]            
__________________________________________________________________________________________________
Bn3c_branch2c (BatchNormalizati (None, 28, 28, 512) 2048 res3c_branch2c[0][0]             
__________________________________________________________________________________________________
Add_630 (Add) (None, 28, 28, 512) 0 bn3c_branch2c[0][0]              
                                                                 Activation_1931[0][0]            
__________________________________________________________________________________________________
Activation_1934 (Activation) (None, 28, 28, 512) 0 add_630[0][0]                    
__________________________________________________________________________________________________
Res3d_branch2a (Conv2D) (None, 28, 28, 128) 65664 activation_1934[0][0]            
__________________________________________________________________________________________________
Bn3d_branch2a (BatchNormalizati (None, 28, 28, 128) 512 res3d_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1935 (Activation) (None, 28, 28, 128) 0 bn3d_branch2a[0][0]              
__________________________________________________________________________________________________
Res3d_branch2b (Conv2D) (None, 28, 28, 128) 147584 activation_1935[0][0]            
__________________________________________________________________________________________________
Bn3d_branch2b (BatchNormalizati (None, 28, 28, 128) 512 res3d_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1936 (Activation) (None, 28, 28, 128) 0 bn3d_branch2b[0][0]              
__________________________________________________________________________________________________
Res3d_branch2c (Conv2D) (None, 28, 28, 512) 66048 activation_1936[0][0]            
__________________________________________________________________________________________________
Bn3d_branch2c (BatchNormalizati (None, 28, 28, 512) 2048 res3d_branch2c[0][0]             
__________________________________________________________________________________________________
Add_631 (Add) (None, 28, 28, 512) 0 bn3d_branch2c[0][0]              
                                                                 Activation_1934[0][0]            
__________________________________________________________________________________________________
Activation_1937 (Activation) (None, 28, 28, 512) 0 add_631[0][0]                    
__________________________________________________________________________________________________
Res4a_branch2a (Conv2D) (None, 14, 14, 256) 131328 activation_1937[0][0]            
__________________________________________________________________________________________________
Bn4a_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4a_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1938 (Activation) (None, 14, 14, 256) 0 bn4a_branch2a[0][0]              
__________________________________________________________________________________________________
Res4a_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1938[0][0]            
__________________________________________________________________________________________________
Bn4a_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4a_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1939 (Activation) (None, 14, 14, 256) 0 bn4a_branch2b[0][0]              
__________________________________________________________________________________________________
Res4a_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1939[0][0]            
__________________________________________________________________________________________________
Res4a_branch1 (Conv2D) (None, 14, 14, 1024) 525312 activation_1937[0][0]            
__________________________________________________________________________________________________
Bn4a_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4a_branch2c[0][0]             
__________________________________________________________________________________________________
Bn4a_branch1 (BatchNormalizatio (None, 14, 14, 1024) 4096 res4a_branch1[0][0]              
__________________________________________________________________________________________________
Add_632 (Add) (None, 14, 14, 1024) 0 bn4a_branch2c[0][0]              
                                                                 Bn4a_branch1[0][0]               
__________________________________________________________________________________________________
Activation_1940 (Activation) (None, 14, 14, 1024) 0 add_632[0][0]                    
__________________________________________________________________________________________________
Res4b_branch2a (Conv2D) (None, 14, 14, 256) 262400 activation_1940[0][0]            
__________________________________________________________________________________________________
Bn4b_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4b_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1941 (Activation) (None, 14, 14, 256) 0 bn4b_branch2a[0][0]              
__________________________________________________________________________________________________
Res4b_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1941[0][0]            
__________________________________________________________________________________________________
Bn4b_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4b_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1942 (Activation) (None, 14, 14, 256) 0 bn4b_branch2b[0][0]              
__________________________________________________________________________________________________
Res4b_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1942[0][0]            
__________________________________________________________________________________________________
Bn4b_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4b_branch2c[0][0]             
__________________________________________________________________________________________________
Add_633 (Add) (None, 14, 14, 1024) 0 bn4b_branch2c[0][0]              
                                                                 Activation_1940[0][0]            
__________________________________________________________________________________________________
Activation_1943 (Activation) (None, 14, 14, 1024) 0 add_633[0][0]                    
__________________________________________________________________________________________________
Res4c_branch2a (Conv2D) (None, 14, 14, 256) 262400 activation_1943[0][0]            
__________________________________________________________________________________________________
Bn4c_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4c_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1944 (Activation) (None, 14, 14, 256) 0 bn4c_branch2a[0][0]              
__________________________________________________________________________________________________
Res4c_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1944[0][0]            
__________________________________________________________________________________________________
Bn4c_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4c_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1945 (Activation) (None, 14, 14, 256) 0 bn4c_branch2b[0][0]              
__________________________________________________________________________________________________
Res4c_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1945[0][0]            
__________________________________________________________________________________________________
Bn4c_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4c_branch2c[0][0]             
__________________________________________________________________________________________________
Add_634 (Add) (None, 14, 14, 1024) 0 bn4c_branch2c[0][0]              
                                                                 Activation_1943[0][0]            
__________________________________________________________________________________________________
Activation_1946 (Activation) (None, 14, 14, 1024) 0 add_634[0][0]                    
__________________________________________________________________________________________________
Res4d_branch2a (Conv2D) (None, 14, 14, 256) 262400 activation_1946[0][0]            
__________________________________________________________________________________________________
Bn4d_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4d_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1947 (Activation) (None, 14, 14, 256) 0 bn4d_branch2a[0][0]              
__________________________________________________________________________________________________
Res4d_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1947[0][0]            
__________________________________________________________________________________________________
Bn4d_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4d_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1948 (Activation) (None, 14, 14, 256) 0 bn4d_branch2b[0][0]              
__________________________________________________________________________________________________
Res4d_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1948[0][0]            
__________________________________________________________________________________________________
Bn4d_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4d_branch2c[0][0]             
__________________________________________________________________________________________________
Add_635 (Add) (None, 14, 14, 1024) 0 bn4d_branch2c[0][0]              
                                                                 Activation_1946[0][0]            
__________________________________________________________________________________________________
Activation_1949 (Activation) (None, 14, 14, 1024) 0 add_635[0][0]                    
__________________________________________________________________________________________________
Res4e_branch2a (Conv2D) (None, 14, 14, 256) 262400 activation_1949[0][0]            
__________________________________________________________________________________________________
Bn4e_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4e_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1950 (Activation) (None, 14, 14, 256) 0 bn4e_branch2a[0][0]              
__________________________________________________________________________________________________
Res4e_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1950[0][0]            
__________________________________________________________________________________________________
Bn4e_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4e_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1951 (Activation) (None, 14, 14, 256) 0 bn4e_branch2b[0][0]              
__________________________________________________________________________________________________
Res4e_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1951[0][0]            
__________________________________________________________________________________________________
Bn4e_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4e_branch2c[0][0]             
__________________________________________________________________________________________________
Add_636 (Add) (None, 14, 14, 1024) 0 bn4e_branch2c[0][0]              
                                                                 Activation_1949[0][0]            
__________________________________________________________________________________________________
Activation_1952 (Activation) (None, 14, 14, 1024) 0 add_636[0][0]                    
__________________________________________________________________________________________________
Res4f_branch2a (Conv2D) (None, 14, 14, 256) 262400 activation_1952[0][0]            
__________________________________________________________________________________________________
Bn4f_branch2a (BatchNormalizati (None, 14, 14, 256) 1024 res4f_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1953 (Activation) (None, 14, 14, 256) 0 bn4f_branch2a[0][0]              
__________________________________________________________________________________________________
Res4f_branch2b (Conv2D) (None, 14, 14, 256) 590080 activation_1953[0][0]            
__________________________________________________________________________________________________
Bn4f_branch2b (BatchNormalizati (None, 14, 14, 256) 1024 res4f_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1954 (Activation) (None, 14, 14, 256) 0 bn4f_branch2b[0][0]              
__________________________________________________________________________________________________
Res4f_branch2c (Conv2D) (None, 14, 14, 1024) 263168 activation_1954[0][0]            
__________________________________________________________________________________________________
Bn4f_branch2c (BatchNormalizati (None, 14, 14, 1024) 4096 res4f_branch2c[0][0]             
__________________________________________________________________________________________________
Add_637 (Add) (None, 14, 14, 1024) 0 bn4f_branch2c[0][0]              
                                                                 Activation_1952[0][0]            
__________________________________________________________________________________________________
Activation_1955 (Activation) (None, 14, 14, 1024) 0 add_637[0][0]                    
__________________________________________________________________________________________________
Res5a_branch2a (Conv2D) (None, 7, 7, 512) 524800 activation_1955[0][0]            
__________________________________________________________________________________________________
Bn5a_branch2a (BatchNormalizati (None, 7, 7, 512) 2048 res5a_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1956 (Activation) (None, 7, 7, 512) 0 bn5a_branch2a[0][0]              
__________________________________________________________________________________________________
Res5a_branch2b (Conv2D) (None, 7, 7, 512) 2359808 activation_1956[0][0]            
__________________________________________________________________________________________________
Bn5a_branch2b (BatchNormalizati (None, 7, 7, 512) 2048 res5a_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1957 (Activation) (None, 7, 7, 512) 0 bn5a_branch2b[0][0]              
__________________________________________________________________________________________________
Res5a_branch2c (Conv2D) (None, 7, 7, 2048) 1050624 activation_1957[0][0]            
__________________________________________________________________________________________________
Res5a_branch1 (Conv2D) (None, 7, 7, 2048) 2099200 activation_1955[0][0]            
__________________________________________________________________________________________________
Bn5a_branch2c (BatchNormalizati (None, 7, 7, 2048) 8192 res5a_branch2c[0][0]             
__________________________________________________________________________________________________
Bn5a_branch1 (BatchNormalizatio (None, 7, 7, 2048) 8192 res5a_branch1[0][0]              
__________________________________________________________________________________________________
Add_638 (Add) (None, 7, 7, 2048) 0 bn5a_branch2c[0][0]              
                                                                 Bn5a_branch1[0][0]               
__________________________________________________________________________________________________
Activation_1958 (Activation) (None, 7, 7, 2048) 0 add_638[0][0]                    
__________________________________________________________________________________________________
Res5b_branch2a (Conv2D) (None, 7, 7, 512) 1049088 activation_1958[0][0]            
__________________________________________________________________________________________________
Bn5b_branch2a (BatchNormalizati (None, 7, 7, 512) 2048 res5b_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1959 (Activation) (None, 7, 7, 512) 0 bn5b_branch2a[0][0]              
__________________________________________________________________________________________________
Res5b_branch2b (Conv2D) (None, 7, 7, 512) 2359808 activation_1959[0][0]            
__________________________________________________________________________________________________
Bn5b_branch2b (BatchNormalizati (None, 7, 7, 512) 2048 res5b_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1960 (Activation) (None, 7, 7, 512) 0 bn5b_branch2b[0][0]              
__________________________________________________________________________________________________
Res5b_branch2c (Conv2D) (None, 7, 7, 2048) 1050624 activation_1960[0][0]            
__________________________________________________________________________________________________
Bn5b_branch2c (BatchNormalizati (None, 7, 7, 2048) 8192 res5b_branch2c[0][0]             
__________________________________________________________________________________________________
Add_639 (Add) (None, 7, 7, 2048) 0 bn5b_branch2c[0][0]              
                                                                 Activation_1958[0][0]            
__________________________________________________________________________________________________
Activation_1961 (Activation) (None, 7, 7, 2048) 0 add_639[0][0]                    
__________________________________________________________________________________________________
Res5c_branch2a (Conv2D) (None, 7, 7, 512) 1049088 activation_1961[0][0]            
__________________________________________________________________________________________________
Bn5c_branch2a (BatchNormalizati (None, 7, 7, 512) 2048 res5c_branch2a[0][0]             
__________________________________________________________________________________________________
Activation_1962 (Activation) (None, 7, 7, 512) 0 bn5c_branch2a[0][0]              
__________________________________________________________________________________________________
Res5c_branch2b (Conv2D) (None, 7, 7, 512) 2359808 activation_1962[0][0]            
__________________________________________________________________________________________________
Bn5c_branch2b (BatchNormalizati (None, 7, 7, 512) 2048 res5c_branch2b[0][0]             
__________________________________________________________________________________________________
Activation_1963 (Activation) (None, 7, 7, 512) 0 bn5c_branch2b[0][0]              
__________________________________________________________________________________________________
Res5c_branch2c (Conv2D) (None, 7, 7, 2048) 1050624 activation_1963[0][0]            
__________________________________________________________________________________________________
Bn5c_branch2c (BatchNormalizati (None, 7, 7, 2048) 8192 res5c_branch2c[0][0]             
__________________________________________________________________________________________________
Add_640 (Add) (None, 7, 7, 2048) 0 bn5c_branch2c[0][0]              
                                                                 Activation_1961[0][0]            
__________________________________________________________________________________________________
Activation_1964 (Activation) (None, 7, 7, 2048) 0 add_640[0][0]                    
__________________________________________________________________________________________________
Avg_pool (AveragePooling2D) (None, 1, 1, 2048) 0 activation_1964[0][0]            
__________________________________________________________________________________________________
Flatten_4 (Flatten) (None, 2048) 0 avg_pool[0][0]                   
__________________________________________________________________________________________________
Fc1000 (Dense) (None, 1000) 2049000 flatten_4[0][0]                  
=========================================================== =========================================================
Total params: 25,636,712
Trainable params: 25,583,592
Non-trainable params: 53,120
__________________________________________________________________________________________________
(6680, 224, 224, 3)

Step 6: Complete your algorithm

Implement an algorithm whose input is the path of the image, which distinguishes whether the image contains a person, a dog, or both, and then:

  • If a dog is detected from the image, the predicted variety is returned.
  • If a person is detected from the image , the most similar dog breed is returned.
  • If neither of them can be detected in the image, an error message is output.

We welcome you to write the function in humans and detect the image of the dog yourself, you can freely use to complete the above face_detectorand dog_detectorfunction. You need to use your CNN in step 5 to predict the dog breed.

The sample output of the algorithm is provided below, but you are free to design your own model!

Sample Human Output

Question 10:

Complete your code in the code block below.


In [39]:
### TODO: Design your algorithm 
### Freely use the required number of code units 
from  IPython.display  import  clear_output 
import  tqdm

Def  get_name ( id ): 
    if  id  >=  len ( dog_names ):  raise  Exception ( 'Where is my dog?' ) 
    return  dog_names [ id ] . split ( "." ,  1 )[ 1 ]

i  =  2  # running without GPU, super slow. You can adjust the test image as you like. 
np . random . shuffle ( humans ) 
for  i ,  x  in  enumerate ( humans [: i ]): 
    prediction  =  predict ( x ) 
    name  =  get_name ( int ( prediction )) 
    clear_output () 
    print ( "My name is {} : {} " . format( i ,  name ))


i  =  2  # running without GPU, super slow. You can adjust the test image as you like. 
np . random . shuffle ( dogs ) 
for  i ,  x  in  enumerate ( dogs [: i ]): 
    prediction  =  predict ( x ) 
    name  =  get_name ( int ( prediction )) 
    clear_output () 
    print ( "My name is {} : {} " . format( i ,  name ))
My name is 0: Labrador_retriever

Step 7: Test your algorithm

In this section, you will try your new algorithm! What type of dog do you think the algorithm looks like? If you have a dog, can it accurately predict your dog's breed? If you have a cat, will it mistake your cat for a dog?

Question 11:

Write code below and test your algorithm with at least 6 real-world images. You can use any photo, but please use at least two human images (with the consent of the parties) and two dogs. Please also answer the following questions:

  1. Is the output better than you expected:)? Or worse: (?
  2. Make at least three ideas for improving your model.
In [45]:
## TODO: On your computer, in step 6, run your algorithm on at least 6 images. 
## Freely use the required number of code units 
from  keras.preprocessing  import  image 
import  matplotlib.pyplot  as  plt

From  PIL  import  Image 
import  urllib.request 
import  io 
from  tqdm  import  tqdm

URL  =  [ 'https://s3.amazonaws.com/cdn-origin-etr.akc.org/wp-content/uploads/2017/11/12233437/Entlebucher-Mountain-Dog-On-White-01.jpg' , 
      'https://pre00.deviantart.net/827b/th/pre/f/2018/147/b/2/img_20180526_134216_20180526220640765_by_regnoart-dccq3ey.jpg' , 
      'https://c8.alamy.com/comp/ABXTB4/ dog-wirehaired-parson-jack-russell-terrier-profile-pr-224-ABXTB4.jpg' , 
      'https://ragom.org/sites/default/files/styles/dog_bio_hero_309/public/images/dogs/2015/ Twix_15-224/Twix15224b1.jpg?itok=D08C-hju' , 
      'https://upload.wikimedia.org/wikipedia/commons/thumb/5/56/Donald_Trump_official_portrait.jpg/220px-Donald_Trump_official_portrait.jpg' ,
      'https://d1u5p3l4wpay3k.cloudfront.net/fallout_gamepedia/thumb/9/94/Mao.jpg/251px-Mao.jpg?version=b5a173a0cc381c1db1e68c0de759f8d9' , 
      'https://i.vimeocdn.com/portrait/11854029_300x300' , 
      'http://p9.pstatp.com/large/1852/4456914283' ,]




Fig = plt . figure ( figsize = ( 8 ,  8 ))

Row  =  3 
col  =  4 
for  i ,  url  in  enumerate ( tqdm ( URL )): 
    with  urllib . request . urlopen ( url )  as  url : 
        f  =  io . BytesIO ( url . read ()) 
    img  =  Image . open ( f ) 
    img  =  img . resize (( 224 , 224 ), Image . ANTIALIAS )
    
    IMG  =  Image . img_to_array ( IMG ) 
    Fig . add_subplot ( Row ,  COL ,  I + . 1 ) 
    PLT . imshow ( IMG  /  255. ) 
    X  =  IMG 
    OUT  =  Predict ( X ) 
    PLT . title ( get_name ( OUT )) 
PLT . Show ()
100%|██████████| 8/8 [03:31<00:00, 26.65s/it]
  1. The result is bad since the model thinks every dog ​​is a Bull_terrier
  2. There are some problems of this model
  3. Firstly, it cannot handle adversarial inputs since our model only trained without augmentation. We can augmente data (flip, rotate, and add random noise)
  4. Secondly, the model may think cats are dogs because there are only dogs in our training sample. We can add more categories.
  5. Thirdly, the prediction need a lot of time to generate on giant network and has a potential of overfitting. We can add weight decade.

Note: When you have written all the code and answered all the questions. You can export your iPython Notebook as an HTML file. You can do this in the menu bar by exporting File -> Download as -> HTML (.html) as the job submission for this HTML and this iPython notebook.

Original text