pythontensorflowkerasdeep-learningconv-neural-network

ValueError: The layer sequential_4 has never been called and thus has no defined input


I have built a CNN model with the following layers:

def build_trainable_cnn(input_shape, num_classes):
    """
    Create a CNN model for feature extraction
    
    Parameters:
    input_shape: shape of input features (e.g., (500, 13) for MFCCs)
    
    Returns:
    model: CNN model
    """
    model = models.Sequential()
    model.add(layers.Input(shape=input_shape)) 
    
    # First convolutional block
    model.add(layers.Conv1D(64, 3, padding='same', activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D(pool_size=2))
    model.add(layers.Dropout(0.05))
    
    # Second convolutional block
    model.add(layers.Conv1D(128, 3, padding='same', activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D(pool_size=2))
    model.add(layers.Dropout(0.05))
    
    # Third convolutional block
    model.add(layers.Conv1D(128, 3, padding='same', activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D(pool_size=2))
    model.add(layers.Dropout(0.05))
    
    # Fourth convolutional block
    model.add(layers.Conv1D(128, 3, padding='same', activation='relu'))
    model.add(layers.BatchNormalization())
    model.add(layers.MaxPooling1D(pool_size=2))
    model.add(layers.Dropout(0.05))
    
    # Flatten layer to get 1D feature vector
    model.add(layers.Flatten())
    model.add(layers.Dense(256, activation='relu'))
    model.add(layers.Dropout(0.05))
    
    # Classification head
    model.add(layers.Dense(num_classes, activation='softmax'))
    
    return model

This is how I load my data:

mfcc_data = np.load("/kaggle/working/mfcc_features.npy")  # shape: (segments, 500, 13)
logmel_data = np.load("/kaggle/working/logmel_features.npy")  # shape: (segments, 500, 26)

this is how I trained it:

NUM_CLASSES = 3
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.optimizers import Adam

model_mfcc = build_trainable_cnn(input_shape=(500, 13), num_classes=NUM_CLASSES)

model_mfcc.compile(optimizer=Adam(1e-4), 
              loss='sparse_categorical_crossentropy', 
              metrics=['accuracy'])

model_mfcc.fit(mfcc_data, labels, 
          epochs=30,
          batch_size=32)

and now I want to extract features from the Dense layer:

# Extract features from the Dense(256) layer (before final classification)
feature_extractor = models.Model(inputs=[model_mfcc.input], outputs=[model_mfcc.layers[-3].output])
# Save it
feature_extractor.save("cnn_feature_extractor_mfcc.h5")

But it's not working and I keep getting the error in the title. I tried the following code but still no change in error:

# Ensure model is built
model_mfcc.build(input_shape=(None, 500, 13))
# Call the model on dummy input to ensure it's initialized (if not already done)
_ = model_mfcc(np.zeros((1, 500, 13)))

Solution

  • Instead of relying on model_mfcc.input, which might not be properly initialized, especially in a Sequential model, you should try one of the following:

    1. Refactor your model to use the Functional API, which gives you full control over layers and connections. This ensures you can always access intermediate outputs.
    from tensorflow.keras import layers, models, Input
    
    def build_trainable_cnn(input_shape, num_classes):
        inputs = Input(shape=input_shape)
    
        x = layers.Conv1D(64, 3, padding='same', activation='relu')(inputs)
        x = layers.BatchNormalization()(x)
        x = layers.MaxPooling1D(pool_size=2)(x)
        x = layers.Dropout(0.05)(x)
    
        x = layers.Conv1D(128, 3, padding='same', activation='relu')(x)
        x = layers.BatchNormalization()(x)
        x = layers.MaxPooling1D(pool_size=2)(x)
        x = layers.Dropout(0.05)(x)
    
        x = layers.Conv1D(128, 3, padding='same', activation='relu')(x)
        x = layers.BatchNormalization()(x)
        x = layers.MaxPooling1D(pool_size=2)(x)
        x = layers.Dropout(0.05)(x)
    
        x = layers.Conv1D(128, 3, padding='same', activation='relu')(x)
        x = layers.BatchNormalization()(x)
        x = layers.MaxPooling1D(pool_size=2)(x)
        x = layers.Dropout(0.05)(x)
    
        x = layers.Flatten()(x)
        dense_features = layers.Dense(256, activation='relu')(x)  # this is the feature layer
        x = layers.Dropout(0.05)(dense_features)
    
        outputs = layers.Dense(num_classes, activation='softmax')(x)
    
        model = models.Model(inputs=inputs, outputs=outputs)
        return model, dense_features
    

    Then you can train it the same way:

    model_mfcc, feature_layer = build_trainable_cnn((500, 13), NUM_CLASSES)
    model_mfcc.compile(optimizer=Adam(1e-4), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
    model_mfcc.fit(mfcc_data, labels, epochs=30, batch_size=32)
    # Create the feature extractor:
    feature_extractor = models.Model(inputs=model_mfcc.input, outputs=feature_layer)
    feature_extractor.save("cnn_feature_extractor_mfcc.h5")
    
    1. If you must use your existing Sequential model, make sure you access layers by index carefully and ensure the model has been called.
    # Force build the model and call it once
    model_mfcc.build(input_shape=(None, 500, 13))
    _ = model_mfcc(np.zeros((1, 500, 13)))
    
    # Print layer names to confirm correct index
    for i, layer in enumerate(model_mfcc.layers):
        print(i, layer.name, layer.output_shape)
    
    # Extract from the Dense(256) layer
    feature_extractor = models.Model(inputs=model_mfcc.input, outputs=model_mfcc.layers[-3].output)