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)))
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:
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")
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)