I am trying to access the output of an intermediate layer of a pretrained keras model but I am getting an exception. My code is the following:
from keras.applications import vgg16
model = vgg16.VGG16(weights='imagenet', include_top=True)
layer_output = Model(inputs = model.input, outputs = model.layers[7].output)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-133-1b3a5460641b> in <module>
----> 1 layer_output = Model(inputs = model.input, outputs = model.layers[7].output)
~\AppData\Roaming\Python\Python37\site-packages\tensorflow_core\python\keras\engine\training.py in __init__(self, *args, **kwargs)
141
142 def __init__(self, *args, **kwargs):
--> 143 super(Model, self).__init__(*args, **kwargs)
144 _keras_api_gauge.get_cell('model').set(True)
145
~\AppData\Roaming\Python\Python37\site-packages\tensorflow_core\python\keras\engine\network.py in __init__(self, *args, **kwargs)
167 'inputs' in kwargs and 'outputs' in kwargs):
168 # Graph network
--> 169 self._init_graph_network(*args, **kwargs)
170 else:
171 # Subclassed network
~\AppData\Roaming\Python\Python37\site-packages\tensorflow_core\python\training\tracking\base.py in _method_wrapper(self, *args, **kwargs)
454 self._self_setattr_tracking = False # pylint: disable=protected-access
455 try:
--> 456 result = method(self, *args, **kwargs)
457 finally:
458 self._self_setattr_tracking = previous_value # pylint: disable=protected-access
~\AppData\Roaming\Python\Python37\site-packages\tensorflow_core\python\keras\engine\network.py in _init_graph_network(self, inputs, outputs, name, **kwargs)
273
274 self._base_init(name=name, **kwargs)
--> 275 self._validate_graph_inputs_and_outputs()
276
277 # A Network does not create weights of its own, thus it is already
~\AppData\Roaming\Python\Python37\site-packages\tensorflow_core\python\keras\engine\network.py in _validate_graph_inputs_and_outputs(self)
1350 # Check that x is an input tensor.
1351 # pylint: disable=protected-access
-> 1352 layer = x._keras_history.layer
1353 if len(layer._inbound_nodes) > 1 or (
1354 layer._inbound_nodes and layer._inbound_nodes[0].inbound_layers):
AttributeError: 'tuple' object has no attribute 'layer'
What creates the problem and how should I correct my code?
Update
The problem appears at network.py file and the particular line presented in the error message is part of a function that is inside the network.py file:
def _validate_graph_inputs_and_outputs(self):
"""Validates the inputs and outputs of a Graph Network."""
# Check for redundancy in inputs.
if len({id(i) for i in self.inputs}) != len(self.inputs):
raise ValueError('The list of inputs passed to the model '
'is redundant. '
'All inputs should only appear once.'
' Found: ' + str(self.inputs))
for x in self.inputs:
# Check that x has appropriate `_keras_history` metadata.
if not hasattr(x, '_keras_history'):
cls_name = self.__class__.__name__
raise ValueError('Input tensors to a ' + cls_name + ' ' +
'must come from `tf.keras.Input`. '
'Received: ' + str(x) +
' (missing previous layer metadata).')
# Check that x is an input tensor.
# pylint: disable=protected-access
layer = x._keras_history.layer
if len(layer._inbound_nodes) > 1 or (
layer._inbound_nodes and layer._inbound_nodes[0].inbound_layers):
cls_name = self.__class__.__name__
logging.warning(cls_name + ' inputs must come from '
'`tf.keras.Input` (thus holding past layer metadata), '
'they cannot be the output of '
'a previous non-Input layer. '
'Here, a tensor specified as '
'input to "' + self.name + '" was not an Input tensor, '
'it was generated by layer ' + layer.name + '.\n'
'Note that input tensors are '
'instantiated via `tensor = tf.keras.Input(shape)`.\n'
'The tensor that caused the issue was: ' + str(x.name))
if isinstance(x, ragged_tensor.RaggedTensor):
self._supports_ragged_inputs = True
# Check compatibility of batch sizes of Input Layers.
input_batch_sizes = [
training_utils.get_static_batch_size(x._keras_history.layer)
for x in self.inputs
]
consistent_batch_size = None
for batch_size in input_batch_sizes:
if batch_size is not None:
if (consistent_batch_size is not None and
batch_size != consistent_batch_size):
raise ValueError('The specified batch sizes of the Input Layers'
' are incompatible. Found batch sizes: {}'.format(
input_batch_sizes))
consistent_batch_size = batch_size
for x in self.outputs:
if not hasattr(x, '_keras_history'):
cls_name = self.__class__.__name__
raise ValueError('Output tensors to a ' + cls_name + ' must be '
'the output of a TensorFlow `Layer` '
'(thus holding past layer metadata). Found: ' + str(x))
x is an attribute of the Class Network defined in the same network.py file as follows:
class Network(base_layer.Layer):
"""A `Network` is a composition of layers.
`Network` is the topological form of a "model". A `Model`
is simply a `Network` with added training routines.
Two types of `Networks` exist: Graph Networks and Subclass Networks. Graph
networks are used in the Keras Functional and Sequential APIs. Subclassed
networks are used when a user subclasses the `Model` class. In general,
more Keras features are supported with Graph Networks than with Subclassed
Networks, specifically:
- Model cloning (`keras.models.clone`)
- Serialization (`model.get_config()/from_config`, `model.to_json()/to_yaml()`
- Whole-model saving (`model.save()`)
A Graph Network can be instantiated by passing two arguments to `__init__`.
The first argument is the `keras.Input` Tensors that represent the inputs
to the Network. The second argument specifies the output Tensors that
represent the outputs of this Network. Both arguments can be a nested
structure of Tensors.
Example:
```
inputs = {'x1': keras.Input(shape=(10,)), 'x2': keras.Input(shape=(1,))}
t = keras.layers.Dense(1, activation='relu')(inputs['x1'])
outputs = keras.layers.Add()([t, inputs['x2'])
network = Network(inputs, outputs)
```
A Graph Network constructed using the Functional API can also include raw
TensorFlow functions, with the exception of functions that create Variables
or assign ops.
Example:
```
inputs = keras.Input(shape=(10,))
x = keras.layers.Dense(1)(inputs)
outputs = tf.nn.relu(x)
network = Network(inputs, outputs)
```
Subclassed Networks can be instantiated via `name` and (optional) `dynamic`
keyword arguments. Subclassed Networks keep track of their Layers, and their
`call` method can be overridden. Subclassed Networks are typically created
indirectly, by subclassing the `Model` class.
Example:
```
class MyModel(keras.Model):
def __init__(self):
super(MyModel, self).__init__(name='my_model', dynamic=False)
self.layer1 = keras.layers.Dense(10, activation='relu')
def call(self, inputs):
return self.layer1(inputs)
```
Allowed args in `super().__init__`:
name: String name of the model.
dynamic: (Subclassed models only) Set this to `True` if your model should
only be run eagerly, and should not be used to generate a static
computation graph. This attribute is automatically set for Functional API
models.
trainable: Boolean, whether the model's variables should be trainable.
dtype: (Subclassed models only) Default dtype of the model's weights (
default of `None` means use the type of the first input). This attribute
has no effect on Functional API models, which do not have weights of their
own.
"""
# See tf.Module for the usage of this property.
# The key of _layer_call_argspecs is a layer. tf.Module._flatten will fail to
# flatten the key since it is trying to convert Trackable/Layer to a string.
_TF_MODULE_IGNORED_PROPERTIES = frozenset(itertools.chain(
('_layer_call_argspecs', '_compiled_trainable_state'),
base_layer.Layer._TF_MODULE_IGNORED_PROPERTIES
))