Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Understanding neural nets: functional API

... understanding how each layer of a neural network changes the shape of the data as it flows through the network is a key part of truly understanding the mechanics of deep learning ~ David Foster, Generative Deep Learning

In this notebook we look at 3 ways of finding the output shape and number of parameters layer by layer:

  1. Keras’ built-in method: model.summary();

  2. our home-made method: mysummary(model);

  3. manual back-of-the-envelope calculation.

We beginning by defining our home-made method, mysummary(model). Worked examples of different network architectures, of fully connected and 2D convolution layers, will follow later.

This notebook is the function API version, which matches cell-by-cell with the companion sequential class version. Sequential class and functional API are two different ways of defining a neural network architecture in Keras.

def mysummary(model):
    PASS0 = True
    print('OUTPUT FROM mysummary(model):')
    for layer in model.layers:
        if PASS0: 
            if len(layer.input_shape)>2 and layer.input_shape[1] != layer.input_shape[2]:
                print('warning: input_shape not square')
# take layer.input_shape[1:] only if this is the first layer, which happens at the first pass
# take just [1:] because [0] is always None
            input_shape = layer.input_shape[1:]
            PASS0 = False
        param = 0
        if 'Conv2D' in str(layer.build):
            if layer.kernel_size[0] != layer.kernel_size[1]:
                print('warning: kernel size not square')
            if layer.strides[0] != layer.strides[1]:
                print('warning: strides not square')
# strides defaults to 1 and padding defaults to none in Keras
# when strides=1, output dimensions are therefore reduced by 2
# when user specificies strides>1, output dimensions are then reduced by that user-specified factor
            if layer.strides[0]==1 and layer.strides[1]==1 and layer.padding=='valid':
                output_shape = int(input_shape[0] - 2), int(input_shape[1] - 2), layer.filters
            else:
                output_shape = int(input_shape[0] // layer.strides[0]), int(input_shape[1] // layer.strides[1]), layer.filters
# the number of parameters from a conv2d layer depends on 
# - the shape of conv2d kernel
# - the number of channels of the previous layer (or the input data, if it's the first layer)
# - the number of conv2d filters 
# the one in the 'plus one' is for the bias
            param = (layer.kernel_size[0] * layer.kernel_size[1] * layer.input_shape[3] + 1 ) * layer.filters
        elif 'MaxPooling2D'in str(layer.build):
            if layer.pool_size[0] != layer.pool_size[1]:
                print('warning: pool size not square')
# maxpooling reduces output_shape[:2] by the user-specified pool sizes, without changing output_shape[2]
            output_shape = int(input_shape[0] / layer.pool_size[0]), int(input_shape[1] / layer.pool_size[1]), input_shape[2]
        elif 'Flatten' in str(layer.build):
            output_shape = (input_shape[0] * input_shape[1] * input_shape[2], )
        elif 'Dropout' in str(layer.build) or 'input' in str(layer.build):
            output_shape = input_shape
        elif 'Dense' in str(layer.build):
# output_shape from dense is the user-specified units
            output_shape = (layer.units, )
# the number of parameters is units multiplied by (input shape plus 1), where 1 is for the bias
            param = (input_shape[0] + 1) * layer.units
# verify that our formulae produce the same output as those calculated internally by Keras
        assert output_shape == layer.output_shape[1:], (output_shape, layer.output_shape[1:])
        assert param == layer.count_params()
        print('{:29s}(None, '.format(layer.name), end='')
        for t in output_shape[:-1]:
            print(t, end=', ')
# some alignment cosmetics for printing
        print('{})'.format(output_shape[-1]), end='')
        if len(output_shape)==1:
            print(' ', end='')
        print(' '*(20 - len(str(output_shape))), param)
        input_shape = output_shape

from keras import models, layers
Using TensorFlow backend.

Worked examples

In each cell that follows, we define a network architecture using functional API, and proceed to

  1. call Keras’ built-in method: model.summary();

  2. call mysummary(model) which we just defined;

  3. markup inline with our manual back-of-the-envelop calculation of the output shape and number of parameters layer by layer.

input_layer = layers.Input(shape=(784,))
x = layers.Dense(32)(input_layer)
# Output dimension of a dense layer is the user-defined units, which is 32 in this case
# Number of parameters = (784 + 1) * 32 = 25120
output_layer = layers.Dense(32)(x)
# Output dimension is again 32
# Number of parameters = (32 + 1) * 32 = 1056, where the first '32' is from layer dense_1, and the second '32' is from current layer, dense_2
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 784)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 32)                25120     
_________________________________________________________________
dense_2 (Dense)              (None, 32)                1056      
=================================================================
Total params: 26,176
Trainable params: 26,176
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_1                      (None, 784)                0
dense_1                      (None, 32)                 25120
dense_2                      (None, 32)                 1056
input_layer = layers.Input(shape=(10000,))
# activations affect neither the output dimensions nor the number of parameters
x = layers.Dense(16, activation='relu')(input_layer)
# Output shape = (None, user-specified units) = (None, 16)
# Number of parameters = (10000 + 1) * 16 = 160016
x = layers.Dense(16, activation='relu')(x)
# Output shape = (None, user-specified units) = (None, 16)
# Number of parameters = (16 + 1) * 16 = 272, where the first '16' is from layer dense_3 and the second '16' is from the current layer, dense_4
output_layer = layers.Dense(1, activation='sigmoid')(x)
# Output shape = (None, user-specified units) = (None, 1)
# Number of parameters = (16 + 1) * 1 = 17, where the 16 is from the current layer, dense_5, itself
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_2 (InputLayer)         (None, 10000)             0         
_________________________________________________________________
dense_3 (Dense)              (None, 16)                160016    
_________________________________________________________________
dense_4 (Dense)              (None, 16)                272       
_________________________________________________________________
dense_5 (Dense)              (None, 1)                 17        
=================================================================
Total params: 160,305
Trainable params: 160,305
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_2                      (None, 10000)              0
dense_3                      (None, 16)                 160016
dense_4                      (None, 16)                 272
dense_5                      (None, 1)                  17
input_layer = layers.Input(shape=(10000,))
x = layers.Dense(64, activation='relu')(input_layer)
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (10000 + 1) * 64 = 640064
x = layers.Dense(64, activation='relu')(x)
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (64 + 1) * 64 = 4160, where the first 64 is from layer dense_6 and the second '64' is from the current layer, dense_7
output_layer = layers.Dense(46, activation='softmax')(x)
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (64 + 1) * 46 = 2990
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_3 (InputLayer)         (None, 10000)             0         
_________________________________________________________________
dense_6 (Dense)              (None, 64)                640064    
_________________________________________________________________
dense_7 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_8 (Dense)              (None, 46)                2990      
=================================================================
Total params: 647,214
Trainable params: 647,214
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_3                      (None, 10000)              0
dense_6                      (None, 64)                 640064
dense_7                      (None, 64)                 4160
dense_8                      (None, 46)                 2990
input_layer = layers.Input(shape=(28 * 28,))
x = layers.Dense(512, activation='relu')(input_layer)
# Output shape = (None, user-specified units) = (None, 512)
# Number of parameters = (28*28 + 1) * 512 = 401920
output_layer = layers.Dense(10, activation='softmax')(x)
# Output dimension = (None, user-specified units) = (None, 10)
# Number of parameters = (512 + 1) * 10 = 5130
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_4 (InputLayer)         (None, 784)               0         
_________________________________________________________________
dense_9 (Dense)              (None, 512)               401920    
_________________________________________________________________
dense_10 (Dense)             (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_4                      (None, 784)                0
dense_9                      (None, 512)                401920
dense_10                     (None, 10)                 5130
input_layer = layers.Input(shape=(28, 28, 1))
x = layers.Conv2D(32, (3, 3), activation='relu')(input_layer)
# Output shape = (None, 28-2, 28-2, 32)
# Number of parameters = (3*3*1 + 1) * 32 = 320
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
# Output shape = (None, 26-2, 26-2, 64
# Number of parameters = (3*3*32 + 1) * 64 = 18496
output_layer = layers.Conv2D(64, (3, 3), activation='relu')(x)
# Output shape = (None, 24-2, 24-2, 64
# Number of parameters = (3*3*64 + 1) * 64 = 36928
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_5 (InputLayer)         (None, 28, 28, 1)         0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 22, 22, 64)        36928     
=================================================================
Total params: 55,744
Trainable params: 55,744
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_5                      (None, 28, 28, 1)          0
conv2d_1                     (None, 26, 26, 32)         320
conv2d_2                     (None, 24, 24, 64)         18496
conv2d_3                     (None, 22, 22, 64)         36928
input_layer = layers.Input(shape=(28, 28, 1))
x = layers.Conv2D(32, (3, 3), activation='relu')(input_layer)
# Output shape =  (None, 28-2, 28-2, 32)
# Number of parameters = (3*3*1 + 1) * 32 = 320
x = layers.MaxPooling2D(2, 2)(x)
# Output dimensions = 26/2, 26/2, 32
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
# Output shape = (None, 13-2, 13-2, 64)
# Number of parameters = (3*3*32 + 1) * 64 = 18496
x = layers.MaxPooling2D(2, 2)(x)
# Output dimensions = floor(11/2), floor(11/2), 64
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
# Output shape = (None, 5-2, 5-2, 64)
# Number of parameters = (3*3*64 + 1) * 64 = 36928
x = layers.Flatten()(x)
# Output shape = (None, 3 * 3 * 64) = (None, 576)
x = layers.Dense(64, activation='relu')(x)
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (576 + 1) * 64 = 36928
output_layer = layers.Dense(10, activation='relu')(x)
# Output shape = (None, user-specified units) = (None, 10)
# Number of parameters = (64 + 1) * 10 = 650
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_6 (InputLayer)         (None, 28, 28, 1)         0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 13, 13, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 11, 11, 64)        18496     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 3, 3, 64)          36928     
_________________________________________________________________
flatten_1 (Flatten)          (None, 576)               0         
_________________________________________________________________
dense_11 (Dense)             (None, 64)                36928     
_________________________________________________________________
dense_12 (Dense)             (None, 10)                650       
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_6                      (None, 28, 28, 1)          0
conv2d_4                     (None, 26, 26, 32)         320
max_pooling2d_1              (None, 13, 13, 32)         0
conv2d_5                     (None, 11, 11, 64)         18496
max_pooling2d_2              (None, 5, 5, 64)           0
conv2d_6                     (None, 3, 3, 64)           36928
flatten_1                    (None, 576)                0
dense_11                     (None, 64)                 36928
dense_12                     (None, 10)                 650
input_layer = layers.Input(shape=(32, 32, 3))
x = layers.Flatten()(input_layer)
# Output shape = (None, 32 * 32 * 3)
x = layers.Dense(200, activation='relu')(x)
# Output shape = (None, user-defined units) = (None, 200)
# Number of parameters = (3072 + 1 ) * 200 = 614600
x = layers.Dense(150, activation='relu')(x)
# Output shape = (None, user-defined units) = (None, 150)
# Number of parameters = (200 + 1) * 150 = 30150
output_layer = layers.Dense(10, activation='softmax')(x)
# Output shape = (None, user-defined units) = (None, 10)
# Number of parameters = (150 + 1) * 10 = 1510
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_7 (InputLayer)         (None, 32, 32, 3)         0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 3072)              0         
_________________________________________________________________
dense_13 (Dense)             (None, 200)               614600    
_________________________________________________________________
dense_14 (Dense)             (None, 150)               30150     
_________________________________________________________________
dense_15 (Dense)             (None, 10)                1510      
=================================================================
Total params: 646,260
Trainable params: 646,260
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_7                      (None, 32, 32, 3)          0
flatten_2                    (None, 3072)               0
dense_13                     (None, 200)                614600
dense_14                     (None, 150)                30150
dense_15                     (None, 10)                 1510
input_layer = layers.Input(shape=(32, 32, 3))
x = layers.Conv2D(10, (4, 4), strides = 2, padding = 'same')(input_layer)
# Output shape = (None, 32/2, 32/2, 10)
# Number of parameters = ( 4*4*3 + 1 ) * 10
x = layers.Conv2D(20, (3, 3), strides = 2, padding = 'same')(x)
# Output shape = (None, 16/2, 16/2, 20)
# Number of parameters = ( 3*3*10 + 1 ) * 20
x = layers.Flatten()(x)
# Output shape = (None, 8 * 8 * 20)
output_layer = layers.Dense(10, activation='softmax')(x)
# Output shape = (None, user-defined units) = (None, 10)
# Number of parameters = ( 1280 + 1 ) * 10
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_8 (InputLayer)         (None, 32, 32, 3)         0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 16, 16, 10)        490       
_________________________________________________________________
conv2d_8 (Conv2D)            (None, 8, 8, 20)          1820      
_________________________________________________________________
flatten_3 (Flatten)          (None, 1280)              0         
_________________________________________________________________
dense_16 (Dense)             (None, 10)                12810     
=================================================================
Total params: 15,120
Trainable params: 15,120
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_8                      (None, 32, 32, 3)          0
conv2d_7                     (None, 16, 16, 10)         490
conv2d_8                     (None, 8, 8, 20)           1820
flatten_3                    (None, 1280)               0
dense_16                     (None, 10)                 12810
input_layer = layers.Input(shape=(150, 150, 3))
x = layers.Conv2D(32, (3, 3), activation='relu')(input_layer)
# Output shape = (None, 150-2, 150-2, 32)
# Number of parameters = (3*3*3 + 1) * 32 = 896
x = layers.MaxPooling2D(2, 2)(x)                       
# Output shape = (None, 148/2, 148/2, 32) 
x = layers.Conv2D(64, (3, 3), activation='relu')(x)                            
# Output shape = (None, 74-2, 74-2, 64)
# Number of parameters = (3*3*32 + 1) * 64 = 18496
x = layers.MaxPooling2D(2, 2)(x)
# Output shape = (None, 72/2, 72/2, 64)
x = layers.Conv2D(128, (3, 3), activation='relu')(x)
# Output shape = (None, 36-2, 36-2, 128)
# Number of parameters = (3*3*64 + 1) * 128 = 73856
x = layers.MaxPooling2D(2, 2)(x)
# Output shape = (None, 34/2, 34/2, 128)
x = layers.Conv2D(128, (3, 3), activation='relu')(x)
# Output shape = (None, 17-2, 17-2, 128)
# Number of parameters = (3*3*128 + 1) * 128 = 147584
x = layers.MaxPooling2D(2, 2)(x)
# Output shape = (None, floor(15/2), floor(15/2), 128)
x = layers.Flatten()(x)
# Output shape = (None, 7 * 7 * 128) = (None, 6272)
x = layers.Dropout(.5)(x)
# Output shape unchanged
x = layers.Dense(512, activation='relu')(x)
# Output shape = (None, user-specified units) = (None, 512)
# Number of parameters = (6272 + 1) * 512 = 3211776
output_layer = layers.Dense(1, activation='sigmoid')(x)
# Output shape = (None, user-specified units) = (None, 1)
# Number of parameters = (512 + 1) * 1 = 513
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_9 (InputLayer)         (None, 150, 150, 3)       0         
_________________________________________________________________
conv2d_9 (Conv2D)            (None, 148, 148, 32)      896       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 74, 74, 32)        0         
_________________________________________________________________
conv2d_10 (Conv2D)           (None, 72, 72, 64)        18496     
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_11 (Conv2D)           (None, 34, 34, 128)       73856     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 17, 17, 128)       0         
_________________________________________________________________
conv2d_12 (Conv2D)           (None, 15, 15, 128)       147584    
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 7, 7, 128)         0         
_________________________________________________________________
flatten_4 (Flatten)          (None, 6272)              0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 6272)              0         
_________________________________________________________________
dense_17 (Dense)             (None, 512)               3211776   
_________________________________________________________________
dense_18 (Dense)             (None, 1)                 513       
=================================================================
Total params: 3,453,121
Trainable params: 3,453,121
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_9                      (None, 150, 150, 3)        0
conv2d_9                     (None, 148, 148, 32)       896
max_pooling2d_3              (None, 74, 74, 32)         0
conv2d_10                    (None, 72, 72, 64)         18496
max_pooling2d_4              (None, 36, 36, 64)         0
conv2d_11                    (None, 34, 34, 128)        73856
max_pooling2d_5              (None, 17, 17, 128)        0
conv2d_12                    (None, 15, 15, 128)        147584
max_pooling2d_6              (None, 7, 7, 128)          0
flatten_4                    (None, 6272)               0
dropout_1                    (None, 6272)               0
dense_17                     (None, 512)                3211776
dense_18                     (None, 1)                  513
# VGG16 coded manually
input_layer = layers.Input(shape=(150, 150, 3))
x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2d_1')(input_layer)
x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2d_2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_max_pooling2d')(x)
x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2d_1')(x)
x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2d_2')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_max_pooling2d')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_1')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_2')(x)
x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_max_pooling2d')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_3')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_max_pooling2d')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_1')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_2')(x)
x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_3')(x)
output_layer = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_max_pooling2d')(x)
'''
x = layers.Flatten()(x)
x = layers.Dense(4096, activation='relu')(x)
x = layers.Dense(4096, activation='relu')(x)
output_layer = layers.Dense(10, activation='softmax')(x)
'''
model = models.Model(input_layer, output_layer)
model.summary()
mysummary(model)
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_10 (InputLayer)        (None, 150, 150, 3)       0         
_________________________________________________________________
block1_conv2d_1 (Conv2D)     (None, 150, 150, 64)      1792      
_________________________________________________________________
block1_conv2d_2 (Conv2D)     (None, 150, 150, 64)      36928     
_________________________________________________________________
block1_max_pooling2d (MaxPoo (None, 75, 75, 64)        0         
_________________________________________________________________
block2_conv2d_1 (Conv2D)     (None, 75, 75, 128)       73856     
_________________________________________________________________
block2_conv2d_2 (Conv2D)     (None, 75, 75, 128)       147584    
_________________________________________________________________
block2_max_pooling2d (MaxPoo (None, 37, 37, 128)       0         
_________________________________________________________________
block3_conv2d_1 (Conv2D)     (None, 37, 37, 256)       295168    
_________________________________________________________________
block3_conv2d_2 (Conv2D)     (None, 37, 37, 256)       590080    
_________________________________________________________________
block3_conv2d_3 (Conv2D)     (None, 37, 37, 256)       590080    
_________________________________________________________________
block3_max_pooling2d (MaxPoo (None, 18, 18, 256)       0         
_________________________________________________________________
block4_conv2d_1 (Conv2D)     (None, 18, 18, 512)       1180160   
_________________________________________________________________
block4_conv2d_2 (Conv2D)     (None, 18, 18, 512)       2359808   
_________________________________________________________________
block4_conv2d_3 (Conv2D)     (None, 18, 18, 512)       2359808   
_________________________________________________________________
block4_max_pooling2d (MaxPoo (None, 9, 9, 512)         0         
_________________________________________________________________
block5_conv2d_1 (Conv2D)     (None, 9, 9, 512)         2359808   
_________________________________________________________________
block5_conv2d_2 (Conv2D)     (None, 9, 9, 512)         2359808   
_________________________________________________________________
block5_conv2d_3 (Conv2D)     (None, 9, 9, 512)         2359808   
_________________________________________________________________
block5_max_pooling2d (MaxPoo (None, 4, 4, 512)         0         
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_10                     (None, 150, 150, 3)        0
block1_conv2d_1              (None, 150, 150, 64)       1792
block1_conv2d_2              (None, 150, 150, 64)       36928
block1_max_pooling2d         (None, 75, 75, 64)         0
block2_conv2d_1              (None, 75, 75, 128)        73856
block2_conv2d_2              (None, 75, 75, 128)        147584
block2_max_pooling2d         (None, 37, 37, 128)        0
block3_conv2d_1              (None, 37, 37, 256)        295168
block3_conv2d_2              (None, 37, 37, 256)        590080
block3_conv2d_3              (None, 37, 37, 256)        590080
block3_max_pooling2d         (None, 18, 18, 256)        0
block4_conv2d_1              (None, 18, 18, 512)        1180160
block4_conv2d_2              (None, 18, 18, 512)        2359808
block4_conv2d_3              (None, 18, 18, 512)        2359808
block4_max_pooling2d         (None, 9, 9, 512)          0
block5_conv2d_1              (None, 9, 9, 512)          2359808
block5_conv2d_2              (None, 9, 9, 512)          2359808
block5_conv2d_3              (None, 9, 9, 512)          2359808
block5_max_pooling2d         (None, 4, 4, 512)          0