Issue with model.output call for GradCAM use on custom model

Hey all,
New to the forum! Hopefully its okay to ask for help with an issue here. Im having a big issue with selecting a convolutional layer from a keras CNN i built with a custom structure. The following code worked fine previously when using common transfer learning models such as EfficientNet or MobileNet.

    grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(layer_name).output, model.output]) # <-- Error on this line

    with tf.GradientTape() as tape:
        conv_outputs, predictions = grad_model(images)
        loss = predictions[:, class_idx]

As soon as i pass my custom model in and target a layer i get the following error :

ValueError: The layer sequential has never been called and thus has no defined output.Traceback (most recent call last):
  File "/src/gradcam.py", line 85, in <module>
    main()
  File "/src/gradcam.py", line 78, in main
    cam = compute_gradcam(model, images, class_idx, layer_name)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/src/gradcam.py", line 29, in compute_gradcam
    grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(layer_name).output, model.output])
                                                                                            ^^^^^^^^^^^^
  File "/src/ops/operation.py", line 260, in output
    return self._get_node_attribute_at_index(0, "output_tensors", "output")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/src/ops/operation.py", line 279, in _get_node_attribute_at_index
    raise ValueError(
ValueError: The layer sequential has never been called and thus has no defined output.

I have of course tried for a few weeks to resolve this issue, i have passed data into the model from my testing set which still resulted in the same error. I tried giving the model just any old noise image before calling output as an input like so to try satisfy a call to the target layer :

dummy_input = tf.random.normal([1] + list(images.shape[1:]))
model(dummy_input)

I have also rebuilt the model with explicitly different layer names than the default ‘conv2d’ naming but i believe the error isn’t in selecting the layer but in fact the ‘model.output’ call.

I have found a single Stack Overflow post regarding this exact error but it has no responses unfortunately.

I would greatly appreciate any input on this issue at all. Im ultimately trying to get the GradCAM output from my custom model and i am completely blocked by this issue. I saw some recommendations to downgrade to TF 2.15.0 so i winder if that may help at all?

Many thanks!

Hello,
The error you are encountering indicates that the custom Keras CNN model you’ve built needs to be called with input data before accessing its layers. Ensure that you are passing input data to the model before trying to access its layers. Check that the model Official Site architecture is correctly defined and compiled, and verify the shape and type of the input data. Consider downgrading TensorFlow to version 2.15.0 if needed. Providing more details about your model architecture and how you’re calling it with input data could help diagnose the issue further.

1 Like

Thanks for the response, i verified data was in fact being fed through the model before calling the function. I also verified the models architecture as well as layer names. I will try the same script with TF 2.15 however and report back. I really appreciate your help. Ill also be sure to provide more context for the script as soon as i have access to it next. All the best!

GradCAM function attached :

def compute_gradcam(model, images, class_idx, layer_name='conv2d'):
    # Dummy forward pass to initialize model layers if not already initialized
    if not model.inputs:
        dummy_input = tf.random.normal([1] + list(images.shape[1:]))
        model(dummy_input) 

    grad_model = tf.keras.models.Model([model.inputs], [model.get_layer(layer_name).output, model.output])

    with tf.GradientTape() as tape:
        conv_outputs, predictions = grad_model(images)
        loss = predictions[:, class_idx]

    grads = tape.gradient(loss, conv_outputs)

    # Compute the guided gradients
    cast_conv_outputs = tf.cast(conv_outputs > 0, "float32")
    cast_grads = tf.cast(grads > 0, "float32")
    guided_grads = cast_conv_outputs * cast_grads * grads

    # Compute the heatmap
    weights = tf.reduce_mean(guided_grads, axis=(1, 2))
    cam = tf.reduce_sum(tf.multiply(weights, conv_outputs), axis=-1)

    return cam