I have tried it with multiple frameworks be it VGG, Resnet, ConvNext. But i'm getting the same error.
While training the model, there are no problems. It even evaluates the model flawlessly. But if I try to load the model afterwards I keep on getting the following error
Traceback (most recent call last):
File "G:\classifier\test.py", line 19, in <module>
model = load_model("best_model_ResNet50.keras", compile=False)
File "G:\tensor\lib\site-packages\keras\src\saving\saving_api.py", line 176, in load_model
return saving_lib.load_model(
File "G:\tensor\lib\site-packages\keras\src\saving\saving_lib.py", line 155, in load_model
model = deserialize_keras_object(
File "G:\tensor\lib\site-packages\keras\src\saving\serialization_lib.py", line 711, in deserialize_keras_object
instance = cls.from_config(inner_config)
File "G:\tensor\lib\site-packages\keras\src\models\sequential.py", line 335, in from_config
model.add(layer)
File "G:\tensor\lib\site-packages\keras\src\models\sequential.py", line 116, in add
self._maybe_rebuild()
File "G:\tensor\lib\site-packages\keras\src\models\sequential.py", line 135, in _maybe_rebuild
self.build(input_shape)
File "G:\tensor\lib\site-packages\keras\src\layers\layer.py", line 223, in build_wrapper
original_build_method(*args, **kwargs)
File "G:\tensor\lib\site-packages\keras\src\models\sequential.py", line 176, in build
x = layer(x)
File "G:\tensor\lib\site-packages\keras\src\utils\traceback_utils.py", line 122, in error_handler
raise e.with_traceback(filtered_tb) from None
File "G:\tensor\lib\site-packages\keras\src\layers\reshaping\flatten.py", line 72, in compute_output_spec
output_shape = self.compute_output_shape(inputs.shape)
AttributeError: Exception encountered when calling Flatten.call().
←[1m'list' object has no attribute 'shape'←[0m
Arguments received by Flatten.call():
• args=(['<KerasTensor shape=(None, 1, 1, 1536), dtype=float32, sparse=False, name=keras_tensor_637>'],)
• kwargs=<class 'inspect._empty'>
The following is the script I used for training the model.
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.applications import ResNet50
from tensorflow.keras import layers, models, optimizers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, CSVLogger, ReduceLROnPlateau, TensorBoard
from sklearn.metrics import classification_report, confusion_matrix
# Load your dataset
train_dir = r'F:\new\classifier\train'
validation_dir = r'F:\new\classifier\val'
test_dir = r'F:\new\classifier\test'
# Setting some variables
INPUT_SIZE = (50, 50)
FREEZE_EPOCHS = 30
UNFREEZE_EPOCHS = 100
# Data Augmentation
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
brightness_range=[0.5, 1.5],
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=False,
fill_mode='nearest')
test_datagen = ImageDataGenerator(rescale=1./255) # Only rescaling for validation and test sets
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=INPUT_SIZE,
batch_size=20,
class_mode='categorical')
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=INPUT_SIZE,
batch_size=20,
class_mode='categorical')
# Model architecture
def build_model(input_shape, num_classes):
base_model = ResNet50(weights='imagenet', include_top=False, input_shape=input_shape)
base_model.trainable = False # Freeze the convolutional base
model = models.Sequential([
base_model,
layers.Flatten(),
layers.Dense(256, activation='relu'),
layers.Dropout(0.5),
layers.Dense(num_classes, activation='softmax')
])
# Learning rate scheduling
lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
initial_learning_rate=1e-4,
decay_steps=100000,
decay_rate=0.96,
staircase=True)
# Model compilation
model.compile(optimizer=optimizers.Adam(learning_rate=lr_schedule),
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
model = build_model((*INPUT_SIZE, 3), 34) # Adjust the target size and number of classes
# Model Checkpoint to save the best model
checkpoint_cb = ModelCheckpoint("best_model_ResNet50.keras", save_best_only=True)
# Learning Rate Scheduling
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=0.001)
# Initial Training before unfreezing the base model
history = model.fit(
train_generator,
steps_per_epoch=100,
epochs=FREEZE_EPOCHS,
validation_data=validation_generator,
validation_steps=50,
callbacks=[checkpoint_cb, csv_logger, reduce_lr])
# Unfreeze the base model for fine-tuning
model.layers[0].trainable = True # Unfreeze the VGG16 base model
# Recompile the model to apply the change
model.compile(optimizer=optimizers.Adam(learning_rate=1e-5), # Use a smaller learning rate
loss='categorical_crossentropy',
metrics=['accuracy'])
# Fine-tuning Training
history_fine = model.fit(
train_generator,
steps_per_epoch=100,
epochs=UNFREEZE_EPOCHS,
validation_data=validation_generator,
validation_steps=50,
callbacks=[checkpoint_cb, csv_logger, reduce_lr])
# Evaluating the Model on the Test Set
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size= INPUT_SIZE,
batch_size=20,
class_mode='categorical',
shuffle=False)
# Print the model structure
model.summary()
test_loss, test_acc = model.evaluate(test_generator, steps=50) # Adjust steps accordingly
print(f"Test Accuracy: {test_acc*100:.2f}%")
# Confusion Matrix and Classification Report
Y_pred = model.predict(test_generator, test_generator.samples // test_generator.batch_size+1)
y_pred = np.argmax(Y_pred, axis=1)
# Get the true class labels
true_classes = test_generator.classes
# Get the class labels for each index from the generator
class_labels = list(test_generator.class_indices.keys())
confusion_mtx = confusion_matrix(true_classes, y_pred)
print('Confusion Matrix')
print(confusion_mtx)
The script I used to load the model afterwards.
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.applications import ResNet50
from tensorflow.keras import layers, models, optimizers
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, CSVLogger, ReduceLROnPlateau, TensorBoard
from sklearn.metrics import classification_report, confusion_matrix
import itertools
from tensorflow.keras.models import load_model
# Load your dataset
test_dir = r'F:\new\classifier\test'
INPUT_SIZE = (50, 50)
test_datagen = ImageDataGenerator(rescale=1./255) # Only rescaling for validation and test sets
model = load_model("best_model_ResNet50.keras", compile=False)
# Evaluating the Model on the Test Set
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size= INPUT_SIZE,
batch_size=20,
class_mode='categorical',
shuffle=False)
# Print the model structure
model.summary()
test_loss, test_acc = model.evaluate(test_generator, steps=50) # Adjust steps accordingly
print(f"Test Accuracy: {test_acc*100:.2f}%")
# Confusion Matrix and Classification Report
Y_pred = model.predict(test_generator, test_generator.samples // test_generator.batch_size+1)
y_pred = np.argmax(Y_pred, axis=1)
# Get the true class labels
true_classes = test_generator.classes
# Get the class labels for each index from the generator
class_labels = list(test_generator.class_indices.keys())
confusion_mtx = confusion_matrix(true_classes, y_pred)
print('Confusion Matrix')
print(confusion_mtx)
# Classification report
classification_rep = classification_report(true_classes, y_pred, target_names=class_labels)
print('Classification Report')
print(classification_rep)