[Python] ValueError: The layer custom_res_net_6 has never been called and thus has no defined...

Discussão em 'Python' iniciado por Stack, Dezembro 7, 2024.

  1. Stack

    Stack Membro Participativo

    I have the following model

    @register_keras_serializable()
    class CustomResNet(Model):
    def __init__(self, num_classes, trained = False, **kwargs):
    super(CustomResNet, self).__init__(**kwargs)
    self.num_classes = num_classes
    print(self.num_classes)
    if trained:
    self.resnet = tf.keras.applications.ResNet50(
    include_top=False, #sem classificado
    weights='imagenet',
    input_shape=(100, 75, 3),
    )
    self.resnet.trainable = False
    else:
    self.resnet = tf.keras.applications.ResNet50(
    include_top=False, #sem classificado
    weights=None,
    input_shape=(100, 75, 3),
    )
    self.resnet.trainable = True
    self.flatten = Flatten()
    self.drop1 = tf.keras.layers.Dropout(0.3)
    self.bn1 = BatchNormalization()
    self.dense1 = Dense(256, activation='relu', kernel_regularizer = tf.keras.regularizers.l2(0.01), name = "dense1")
    self.drop2 = tf.keras.layers.Dropout(0.3)
    self.bn2 = BatchNormalization()
    self.dense2 = Dense(128, activation='relu', kernel_regularizer = tf.keras.regularizers.l2(0.01), name = "dense2")
    self.dense_out = Dense(self.num_classes, activation='softmax', name = "dense_out")


    def call(self, inputs, training=None):
    x = self.resnet(inputs)
    print(f"Shape after ResNet: {x.shape}")
    x = self.flatten(x)
    print(f"Shape after Flatten: {x.shape}")
    x = self.drop1(x)
    x = self.bn1(x)
    x = self.dense1(x)
    print(f"Shape after dense1: {x.shape}")
    x = self.drop2(x)
    x = self.bn2(x)
    x = self.dense2(x)
    print(f"Shape after dense 2: {x.shape}")
    x = self.dense_out(x)
    print(f"Shape after dense_out: {x.shape}")
    return x

    def get_config(self):
    # Include `num_classes` in the config
    config = super(CustomResNet, self).get_config() # Include base class config
    config['num_classes'] = self.num_classes
    return config

    @classmethod
    def from_config(cls, config):
    # Evita passar o mesmo argumento mais de uma vez
    return cls(**config)

    def build(self, input_shape):
    self.resnet.build(input_shape)
    super(CustomResNet, self).build(input_shape)
    self.built = True


    And the following grad-cam implementation

    import tensorflow as tf
    import numpy as np
    import matplotlib.pyplot as plt
    from tensorflow.keras.models import Model
    from tensorflow.keras.preprocessing import image

    def grad_cam(model, img_array, last_conv_layer_name, pred_index=None):
    """
    Generate a Grad-CAM heatmap for a given image.

    Args:
    - model: The trained model
    - img_array: The image to be processed (numpy array)
    - last_conv_layer_name: Name of the last convolutional layer for Grad-CAM
    - pred_index: Index of the predicted class (optional)

    Returns:
    - A heatmap that highlights important areas of the image
    """
    # Ensure the model is in inference mode
    model = model if isinstance(model, tf.keras.Model) else model.model

    # Convert img_array to tensor if needed and add batch dimension
    img_array = np.expand_dims(img_array, axis=0)

    # Retrieve the last convolutional layer
    last_conv_layer = model.get_layer('resnet50').get_layer(last_conv_layer_name)

    # Create a model that outputs the last convolutional layer and the final predictions
    grad_model = Model(
    inputs=[model.get_layer('resnet50').input],
    outputs=[last_conv_layer.output, model.get_layer('dense_out').output]
    )

    with tf.GradientTape() as tape:
    # Record the forward pass
    conv_outputs, predictions = grad_model(img_array)

    # If pred_index is None, use the predicted class index
    if pred_index is None:
    pred_index = tf.argmax(predictions[0])

    # Compute the gradient of the predicted class (class index) with respect to the last convolutional layer
    loss = predictions[:, pred_index]

    # Compute the gradient of the loss with respect to the convolutional layer outputs
    grads = tape.gradient(loss, conv_outputs)

    # Average the gradients across all the axes of the feature maps to get the importance of each channel
    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))

    # Multiply each channel in the feature map by the corresponding pooled gradient
    conv_outputs = conv_outputs[0]
    for i in range(conv_outputs.shape[-1]):
    conv_outputs[:, :, i] *= pooled_grads

    # Average the feature maps along the channels axis to get a 2D heatmap
    heatmap = np.mean(conv_outputs, axis=-1)

    # Normalize the heatmap to a range [0, 1]
    heatmap = np.maximum(heatmap, 0)
    heatmap /= np.max(heatmap)

    # Return the heatmap
    return heatmap

    def display_grad_cam(img_array, heatmap, alpha=0.4):
    """
    Display the Grad-CAM heatmap overlaid on the original image.

    Args:
    - img_array: The original image (numpy array)
    - heatmap: The Grad-CAM heatmap
    - alpha: Transparency level for overlaying the heatmap

    Returns:
    - None, but displays the image with Grad-CAM overlay
    """
    # Resize heatmap to match the size of the original image
    heatmap = np.uint8(255 * heatmap)
    heatmap = tf.image.resize(heatmap, (img_array.shape[0], img_array.shape[1]))
    heatmap = np.array(heatmap)

    # Load the image into a format that can be plotted
    img = image.array_to_img(img_array[0])

    # Display the image with the heatmap overlay
    plt.imshow(img)
    plt.imshow(heatmap, cmap='jet', alpha=alpha) # Jet colormap for better visibility
    plt.axis('off')
    plt.show()

    # Usage example:
    # Assuming `model` is your trained `CustomResNet` model and `x_test[0]` is an image from your dataset.
    # Choose the last convolutional layer name from the ResNet50 model
    last_conv_layer_name = "conv5_block3_out" # Change this if necessary based on your model

    # Run Grad-CAM
    heatmap = grad_cam(model=resnet50_geral_ft, img_array=x_test[0:1], last_conv_layer_name=last_conv_layer_name)

    # Display the result
    display_grad_cam(x_test[0:1], heatmap)


    When I run it, I got an error


    ValueError: The layer dense_out has never been called and thus has no defined output.
    ​

    Even after using a dummy input and build call. The summary of my model runs but on the output column if just shows ?

    My model initialization is the following:

    resnet50_geral_ft = CustomResNet(num_classes=14)
    resnet50_geral_ft.build(input_shape=(None, 100, 75, 3))
    resnet50_geral_ft.compile(optimizer = optimizer,loss='categorical_crossentropy', metrics=default_metrics)
    resnet50_geral_ft = load_model( checkpoint_filepath + "resnet50_geral_ft.keras", custom_objects={'CustomResNet': CustomResNet} )


    I can't find out what I am missing here.... does somebody know?

    Continue reading...

Compartilhe esta Página