1

I have loaded, extended, trained a VGG16 network via Keras, then saved it to disk:

from keras.applications import VGG16
from keras import models

conv_base = VGG16(weights="imagenet", include_top=False)
model = models.Sequential()
model.add(conv_base)
...
model.compile(...)
model.fit(...)
model.save("saved_model.h5")

In another script I load that trained model again:

from keras.models import load_model

model_vgg16 = load_model("saved_model.h5")
model_fails = model_vgg16.get_layer("vgg16")
model_fails.input

That last line leads to the following exception:

AttributeError: Layer vgg16 has multiple inbound nodes, hence the notion of "layer input" is ill-defined. Use `get_input_at(node_index)` instead.

However, when I do the same for the VGG16 net directly, then it works fine:

from keras.applications import VGG16
from keras.models import load_model

model_works = VGG16(weights='imagenet', include_top=False)
model_works.input

That last line does not lead to an error. So my question is:
How can I access the (input) layer of a saved and then re-loaded Keras model?

today
  • 32,602
  • 8
  • 95
  • 115
Matthias
  • 9,817
  • 14
  • 66
  • 125

2 Answers2

1

My approach would be to first print the name of all layers of the model and then call the layer by it's name.

For example :

from keras.models import load_model
model_vgg16 = load_model("saved_model.h5")
mdoel_vgg16.summary()

Note down the name of the desired layer and then get the input or output of the layer

layer_input = model_vgg16.get_layer('vgg16').get_layer(layer_name).input
Chandan M S
  • 391
  • 1
  • 6
1

After adding the VGG16 model to your custom model, it would have two input nodes: one is the original input node which is accessible using conv_base.get_input_at(0), and another input node which is created for the input from your custom model which would be accessible using conv_base.get_input_at(1) (this is actually the input of the model and is equivalent to model.input). The difference between a node and a layer in Keras has been explained in detail in this answer.

today
  • 32,602
  • 8
  • 95
  • 115
  • Thanks, but how can I know that `get_input_at(1)` would be equal to `model.input` in my case? – Matthias May 15 '19 at 12:25
  • @Matthias It is indeed because that's the input tensor of the model. You can verify it using `assert conv_base.get_input_at(1) is model.input`. – today May 15 '19 at 12:28
  • I believe that - it's just, how would I have found out if you didn't tell me? Where can I see that index #1 but not #0 is the input of the model? – Matthias May 15 '19 at 12:36
  • @Matthias Well, after you create the VGG model, i.e. `conv_base = VGG16(...)`, there is only one input node with index 0. In other words, `conv_base.get_input_at(1)` would raise an error. After you add `conv_base` to your custom model as its base, an input tensor is internally created which would represent the input tensor of the model (i.e. `model.input`) and would be connected to `conv_base` as its second input node with index 1. Therefore, we would have `conv_base.get_input_at(1) is model.input` evaluate to `True`. – today May 15 '19 at 14:30