Understanding neural nets: sequential class
... 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:
Keras’ built-in method: model.summary();
our home-made method: mysummary(model);
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 sequential class version, which matches cell-by-cell with the companion function API 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, layersUsing TensorFlow backend.
Worked examples¶
In each cell that follows, we define a network architecture using the sequential class, and proceed to
call Keras’ built-in method: model.summary();
call mysummary(model) which we just defined;
markup inline with our manual back-of-the-envelop calculation of the output shape and number of parameters layer by layer.
model = models.Sequential()
model.add(layers.Dense(32, input_shape=(784,)))
# Output dimension of a dense layer is the user-defined units, which is 32 in this case
# Number of parameters = (784 + 1) * 32 = 25120
model.add(layers.Dense(32))
# 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.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
dense_1 (None, 32) 25120
dense_2 (None, 32) 1056
model = models.Sequential()
# activations affect neither the output dimensions nor the number of parameters
model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
# Output shape = (None, user-specified units) = (None, 16)
# Number of parameters = (10000 + 1) * 16 = 160016
model.add(layers.Dense(16, activation='relu'))
# 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
model.add(layers.Dense(1, activation='sigmoid'))
# 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.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
dense_3 (None, 16) 160016
dense_4 (None, 16) 272
dense_5 (None, 1) 17
model = models.Sequential()
model.add(layers.Dense(64, activation='relu', input_shape=(10000,)))
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (10000 + 1) * 64 = 640064
model.add(layers.Dense(64, activation='relu'))
# 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
model.add(layers.Dense(46, activation='softmax'))
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (64 + 1) * 46 = 2990
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
dense_6 (None, 64) 640064
dense_7 (None, 64) 4160
dense_8 (None, 46) 2990
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
# Output shape = (None, user-specified units) = (None, 512)
# Number of parameters = (28*28 + 1) * 512 = 401920
model.add(layers.Dense(10, activation='softmax'))
# Output dimension = (None, user-specified units) = (None, 10)
# Number of parameters = (512 + 1) * 10 = 5130
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
dense_9 (None, 512) 401920
dense_10 (None, 10) 5130
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
# Output shape = (None, 28-2, 28-2, 32)
# Number of parameters = (3*3*1 + 1) * 32 = 320
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Output shape = (None, 26-2, 26-2, 64
# Number of parameters = (3*3*32 + 1) * 64 = 18496
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Output shape = (None, 24-2, 24-2, 64
# Number of parameters = (3*3*64 + 1) * 64 = 36928
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
conv2d_1 (None, 26, 26, 32) 320
conv2d_2 (None, 24, 24, 64) 18496
conv2d_3 (None, 22, 22, 64) 36928
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
# Output shape = (None, 28-2, 28-2, 32)
# Number of parameters = (3*3*1 + 1) * 32 = 320
model.add(layers.MaxPooling2D(2, 2))
# Output dimensions = 26/2, 26/2, 32
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Output shape = (None, 13-2, 13-2, 64)
# Number of parameters = (3*3*32 + 1) * 64 = 18496
model.add(layers.MaxPooling2D(2, 2))
# Output dimensions = floor(11/2), floor(11/2), 64
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Output shape = (None, 5-2, 5-2, 64)
# Number of parameters = (3*3*64 + 1) * 64 = 36928
model.add(layers.Flatten())
# Output shape = (None, 3 * 3 * 64) = (None, 576)
model.add(layers.Dense(64, activation='relu'))
# Output shape = (None, user-specified units) = (None, 64)
# Number of parameters = (576 + 1) * 64 = 36928
model.add(layers.Dense(10, activation='relu'))
# Output shape = (None, user-specified units) = (None, 10)
# Number of parameters = (64 + 1) * 10 = 650
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
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
model = models.Sequential()
model.add(layers.InputLayer(input_shape=(32, 32, 3)))
model.add(layers.Flatten())
# Output shape = (None, 32 * 32 * 3)
model.add(layers.Dense(200, activation='relu'))
# Output shape = (None, user-defined units) = (None, 200)
# Number of parameters = (3072 + 1 ) * 200 = 614600
model.add(layers.Dense(150, activation='relu'))
# Output shape = (None, user-defined units) = (None, 150)
# Number of parameters = (200 + 1) * 150 = 30150
model.add(layers.Dense(10, activation='softmax'))
# Output shape = (None, user-defined units) = (None, 10)
# Number of parameters = (150 + 1) * 10 = 1510
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
flatten_2 (None, 3072) 0
dense_13 (None, 200) 614600
dense_14 (None, 150) 30150
dense_15 (None, 10) 1510
model = models.Sequential()
model.add(layers.Conv2D(10, (4, 4), strides = 2, padding = 'same', input_shape=(32, 32, 3)))
# Output shape = (None, 32/2, 32/2, 10)
# Number of parameters = ( 4*4*3 + 1 ) * 10
model.add(layers.Conv2D(20, (3, 3), strides = 2, padding = 'same'))
# Output shape = (None, 16/2, 16/2, 20)
# Number of parameters = ( 3*3*10 + 1 ) * 20
model.add(layers.Flatten())
# Output shape = (None, 8 * 8 * 20)
model.add(layers.Dense(10, activation='softmax'))
# Output shape = (None, user-defined units) = (None, 10)
# Number of parameters = ( 1280 + 1 ) * 10
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
conv2d_7 (None, 16, 16, 10) 490
conv2d_8 (None, 8, 8, 20) 1820
flatten_3 (None, 1280) 0
dense_16 (None, 10) 12810
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))
# Output shape = (None, 150-2, 150-2, 32)
# Number of parameters = (3*3*3 + 1) * 32 = 896
model.add(layers.MaxPooling2D(2, 2))
# Output shape = (None, 148/2, 148/2, 32)
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
# Output shape = (None, 74-2, 74-2, 64)
# Number of parameters = (3*3*32 + 1) * 64 = 18496
model.add(layers.MaxPooling2D(2, 2))
# Output shape = (None, 72/2, 72/2, 64)
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
# Output shape = (None, 36-2, 36-2, 128)
# Number of parameters = (3*3*64 + 1) * 128 = 73856
model.add(layers.MaxPooling2D(2, 2))
# Output shape = (None, 34/2, 34/2, 128)
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
# Output shape = (None, 17-2, 17-2, 128)
# Number of parameters = (3*3*128 + 1) * 128 = 147584
model.add(layers.MaxPooling2D(2, 2))
# Output shape = (None, floor(15/2), floor(15/2), 128)
model.add(layers.Flatten())
# Output shape = (None, 7 * 7 * 128) = (None, 6272)
model.add(layers.Dropout(.5))
# Output shape unchanged
model.add(layers.Dense(512, activation='relu'))
# Output shape = (None, user-specified units) = (None, 512)
# Number of parameters = (6272 + 1) * 512 = 3211776
model.add(layers.Dense(1, activation='sigmoid'))
# Output shape = (None, user-specified units) = (None, 1)
# Number of parameters = (512 + 1) * 1 = 513
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
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
model = models.Sequential()
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2d_1', input_shape=(150, 150, 3)))
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2d_2'))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_max_pooling2d'))
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2d_1'))
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2d_2'))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_max_pooling2d'))
model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_1'))
model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_2'))
model.add(layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2d_3'))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_max_pooling2d'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_1'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_2'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2d_3'))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_max_pooling2d'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_1'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_2'))
model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2d_3'))
model.add(layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_max_pooling2d'))
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
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):
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
# VGG16 loaded directly from keras
from keras.applications import VGG16
model = VGG16(weights='imagenet',
include_top=False,
input_shape=(150, 150, 3))
model.summary()
mysummary(model)_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_2 (InputLayer) (None, 150, 150, 3) 0
_________________________________________________________________
block1_conv1 (Conv2D) (None, 150, 150, 64) 1792
_________________________________________________________________
block1_conv2 (Conv2D) (None, 150, 150, 64) 36928
_________________________________________________________________
block1_pool (MaxPooling2D) (None, 75, 75, 64) 0
_________________________________________________________________
block2_conv1 (Conv2D) (None, 75, 75, 128) 73856
_________________________________________________________________
block2_conv2 (Conv2D) (None, 75, 75, 128) 147584
_________________________________________________________________
block2_pool (MaxPooling2D) (None, 37, 37, 128) 0
_________________________________________________________________
block3_conv1 (Conv2D) (None, 37, 37, 256) 295168
_________________________________________________________________
block3_conv2 (Conv2D) (None, 37, 37, 256) 590080
_________________________________________________________________
block3_conv3 (Conv2D) (None, 37, 37, 256) 590080
_________________________________________________________________
block3_pool (MaxPooling2D) (None, 18, 18, 256) 0
_________________________________________________________________
block4_conv1 (Conv2D) (None, 18, 18, 512) 1180160
_________________________________________________________________
block4_conv2 (Conv2D) (None, 18, 18, 512) 2359808
_________________________________________________________________
block4_conv3 (Conv2D) (None, 18, 18, 512) 2359808
_________________________________________________________________
block4_pool (MaxPooling2D) (None, 9, 9, 512) 0
_________________________________________________________________
block5_conv1 (Conv2D) (None, 9, 9, 512) 2359808
_________________________________________________________________
block5_conv2 (Conv2D) (None, 9, 9, 512) 2359808
_________________________________________________________________
block5_conv3 (Conv2D) (None, 9, 9, 512) 2359808
_________________________________________________________________
block5_pool (MaxPooling2D) (None, 4, 4, 512) 0
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________
OUTPUT FROM mysummary(model):
input_2 (None, 150, 150, 3) 0
block1_conv1 (None, 150, 150, 64) 1792
block1_conv2 (None, 150, 150, 64) 36928
block1_pool (None, 75, 75, 64) 0
block2_conv1 (None, 75, 75, 128) 73856
block2_conv2 (None, 75, 75, 128) 147584
block2_pool (None, 37, 37, 128) 0
block3_conv1 (None, 37, 37, 256) 295168
block3_conv2 (None, 37, 37, 256) 590080
block3_conv3 (None, 37, 37, 256) 590080
block3_pool (None, 18, 18, 256) 0
block4_conv1 (None, 18, 18, 512) 1180160
block4_conv2 (None, 18, 18, 512) 2359808
block4_conv3 (None, 18, 18, 512) 2359808
block4_pool (None, 9, 9, 512) 0
block5_conv1 (None, 9, 9, 512) 2359808
block5_conv2 (None, 9, 9, 512) 2359808
block5_conv3 (None, 9, 9, 512) 2359808
block5_pool (None, 4, 4, 512) 0