3

I used the following code to create a CNN model using VGG16 but after creating the model, the input layer of the model disappears from the structure (see the image).

Why the input layer disappears from the structure?

vgg16_model = keras.applications.vgg16.VGG16()
model = Sequential([])
 for layer in vgg16_model.layers[:-1]:
   model.add(layer)
   model.add(Dropout(0.5))
   model.add(Dense(2, activation='softmax', name = 'prediction'))

The model structure

enter image description here

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Noran
  • 707
  • 1
  • 8
  • 19

2 Answers2

7

This is just an artifact of Keras model representation when the Sequential API is used, and it has no practical effect whatsoever: the Input layer is there implicitly, but it is not considered a layer proper and it does not show up in model.summary(). It does show up if the Functional API is used.

Consider the following two identical models, written using the two different APIs:

Sequential API

from keras.models import Sequential
from keras.layers import Dense      # notice that we don't import Input here...

model_seq = Sequential([
    Dense(64, input_shape=(784,),activation='relu'),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])    

model_seq.summary()

# result:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650       
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________

Functional API

from keras.models import Model
from keras.layers import Input, Dense  # explicitly import Input layer

inputs = Input(shape=(784,))
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)

model_func = Model(inputs=inputs, outputs=predictions)

model_func.summary()

    # result:

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 784)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650       
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________

These two models are identical; the fact that the Input layer does not show up explicitly in model.summary() when the Sequential API is used does not mean anything regarding the functionality of the model. EDIT: As Daniel Möller correctly points out in the comment below, it is not even a real layer, doing nothing besides defining the input shape (notice its 0 training parameters in model_func.summary above).

In other words, no worries...

This relevant thread might be useful, too: Keras Sequential model input layer

desertnaut
  • 57,590
  • 26
  • 140
  • 166
  • 3
    In addition, the input layer isn't really a layer. It does nothing besides defining the shape of an input. A layer "performs operations" on data. The input is just data. – Daniel Möller Feb 02 '19 at 21:47
  • 1
    @DanielMöller indeed - thanks for the useful input (added to the answer w/ credit) – desertnaut Feb 02 '19 at 21:55
1

You need to add an InputLayer explicitly...

Sample Code:

vgg16_model = keras.applications.vgg16.VGG16()
model = Sequential()
inp = InputLayer(input_shape=(224, 224, 3))
model.add(inp)

for layer in vgg16_model.layers[:-1]:
    model.add(layer)

for layer in model.layers:
    layer.trainable = False

model.add(Dense(2, activation='softmax'))
model.summary()

Output:

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 8194      
=================================================================
Total params: 134,268,738
Trainable params: 8,194
Non-trainable params: 134,260,544