keras-team / keras

Deep Learning for humans
http://keras.io/
Apache License 2.0
62k stars 19.48k forks source link

Layer "dense" expects 1 input(s), but it received 2 input tensors error while loading a keras model #20084

Open BastienPailloux opened 3 months ago

BastienPailloux commented 3 months ago

**Hello,

I'm not 100% sure it's a bug. I trained a model and saved it on Google Colab Entreprise Tensorflow v2.17.0 Keras v 3.4.1

Once a try to load the model using tf.keras.models.load_model('model_v0-1 (1).keras') I get the following error :**


ValueError Traceback (most recent call last)

in <cell line: 1>() ----> 1 model = tf.keras.models.load_model('model_v0-1 (1).keras')

11 frames

/usr/local/lib/python3.10/dist-packages/keras/src/layers/input_spec.py in assert_input_compatibility(input_spec, inputs, layer_name) 158 inputs = tree.flatten(inputs) 159 if len(inputs) != len(input_spec): --> 160 raise ValueError( 161 f'Layer "{layer_name}" expects {len(input_spec)} input(s),' 162 f" but it received {len(inputs)} input tensors. "

ValueError: Layer "dense" expects 1 input(s), but it received 2 input tensors. Inputs received: [<KerasTensor shape=(None, 11, 11, 1280), dtype=float32, sparse=False, name=keras_tensor_4552>, <KerasTensor shape=(None, 11, 11, 1280), dtype=float32, sparse=False, name=keras_tensor_4553>]


I trained EffecientNetB0 and added some layers

# Configure the startegy
if len(gpus) > 1:
    strategy = tf.distribute.MirroredStrategy()
else:
    strategy = tf.distribute.get_strategy()

with strategy.scope():
    base_model = tf.keras.applications.EfficientNetB0(include_top=False, input_shape=(336, 336, 3), weights='imagenet')
    base_model.trainable = True  # Unfreeze the base model

    # Freeze the first few layers
    for layer in base_model.layers[:15]:
        layer.trainable = False

    num_neurons = (len(filtered_data['species'].unique()) + 1280) // 2

    # Add layers
    model = models.Sequential([
        base_model,
        layers.GlobalAveragePooling2D(),
        layers.Dense(num_neurons, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
        layers.BatchNormalization(),
        layers.Dropout(0.2),
        layers.Dense(num_neurons, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
        layers.BatchNormalization(),
        layers.Dropout(0.2),
        layers.Dense(len(filtered_data['species'].unique()), activation='softmax')
    ])
Model: "sequential"

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ │ efficientnetb0 (Functional) │ (None, 11, 11, 1280) │ 4,049,571 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ global_average_pooling2d │ (None, 1280) │ 0 │ │ (GlobalAveragePooling2D) │ │ │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dense (Dense) │ (None, 672) │ 860,832 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ batch_normalization │ (None, 672) │ 2,688 │ │ (BatchNormalization) │ │ │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dropout (Dropout) │ (None, 672) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dense_1 (Dense) │ (None, 672) │ 452,256 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ batch_normalization_1 │ (None, 672) │ 2,688 │ │ (BatchNormalization) │ │ │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dropout_1 (Dropout) │ (None, 672) │ 0 │ ├──────────────────────────────────────┼─────────────────────────────┼─────────────────┤ │ dense_2 (Dense) │ (None, 65) │ 43,745 │ └──────────────────────────────────────┴─────────────────────────────┴─────────────────┘

Total params: 16,142,256 (61.58 MB)

Trainable params: 5,365,237 (20.47 MB)

Non-trainable params: 46,543 (181.81 KB)

Optimizer params: 10,730,476 (40.93 MB)

Therefore, the only dense layers are the ones I added at the end. Am I doing something wrong ? I read that some other person faces the same issue sinc TF2.16 and keras 3.4, so I guessed it is an issue in keras but not sure.

Thank you for your help/review

fchollet commented 3 months ago

Try with keras-nightly, this error should be fixed already.

BastienPailloux commented 3 months ago

Ok thank you.

And you mean both training the model and load the model or can I just load the previous model ? Because now I always have the same prediction while I don't give the same image

BastienPailloux commented 3 months ago

I tried to train a test model using tf v 2.17.0 and keras-nightly v3.4.1.dev2024080503

I could train it properly and it works correctly

# Configure the startegy
if len(gpus) > 1:
    strategy = tf.distribute.MirroredStrategy()
else:
    strategy = tf.distribute.get_strategy()

with strategy.scope():
    base_model = tf.keras.applications.EfficientNetB0(include_top=False, input_shape=(336, 336, 3), weights='imagenet')
    base_model.trainable = True  # Unfreeze the base model

    # Freeze the first few layers
    for layer in base_model.layers[:15]:
        layer.trainable = False

    num_neurons = (len(filtered_data['species'].unique()) + 1280) // 2

    # Add layers
    model = models.Sequential([
        base_model,
        layers.GlobalAveragePooling2D(),
        layers.Dense(num_neurons, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
        layers.BatchNormalization(),
        layers.Dropout(0.2),
        layers.Dense(num_neurons, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
        layers.BatchNormalization(),
        layers.Dropout(0.2),
        layers.Dense(len(filtered_data['species'].unique()), activation='softmax')
    ])

# Compiler le modèle
model.compile(optimizer=optimizers.Adam(learning_rate=0.001),
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=3, min_lr=0.00000001)
checkpoint = ModelCheckpoint('best_model_v0-0-3.keras', monitor='val_accuracy', save_best_only=True, mode='max')

# Entraîner le modèle
history = model.fit(train_dataset,
                    epochs=40,
                    validation_data=val_dataset,
                    class_weight=class_weights,
                    callbacks=[reduce_lr, checkpoint])

# Save the best model
model.save('model_v0-0-3.keras')`

It tested it in the same environment and it worked perfectly :

`def download_and_preprocess_image(url, target_size=(336, 336)):
    response = requests.get(url)
    image = Image.open(io.BytesIO(response.content))
    image = image.resize(target_size)
    image_array = np.array(image) / 255.0
    if image_array.shape[-1] == 4:  # Si l'image a un canal alpha
        image_array = image_array[..., :3]  # Retirer le canal alpha
    image_array = np.expand_dims(image_array, axis=0)
    return image_array

# URL de l'image pour le test
url = 'https://as2.ftcdn.net/v2/jpg/00/47/10/49/1000_F_47104960_17G7ayVOOcu4dBsSYMxW3Z8BnhR1TQdK.jpg'
image_array = download_and_preprocess_image(url)

# Faire une prédiction en utilisant le modèle
predictions = model.predict(image_array)

# Obtenir les top 5 prédictions et leurs scores
top_5_indices = np.argsort(predictions[0])[-5:][::-1]
top_5_scores = predictions[0][top_5_indices]
top_5_labels = label_encoder.inverse_transform(top_5_indices)

# Afficher les top 5 prédictions avec leurs scores
for index, label, score in zip(top_5_indices, top_5_labels, top_5_scores):
    print(f"Index: {index}, Species: {label}, Score: {score:.4f}")

# Télécharger et afficher l'image avec les résultats
response = requests.get(url)
image = Image.open(io.BytesIO(response.content))

plt.imshow(image)
plt.title(f"Top Prediction: {top_5_labels[0]} ({top_5_scores[0]:.4f})")
plt.axis('off')
plt.show()

I got this, which is correct: Index: 4, Species: Hippotragus equinus, Score: 0.9953 Index: 0, Species: Ara ararauna, Score: 0.0026 Index: 5, Species: Parabuteo unicinctus, Score: 0.0010 Index: 3, Species: Dacelo novaeguineae, Score: 0.0009 Index: 2, Species: Ara macao, Score: 0.0001


However, when I load the model in a new environment (still with tf v 2.17.0 and keras-nightly v3.4.1.dev2024080503) using:

model = models.load_model('model_v0-0-3.keras')
labels_df = pd.read_csv('labels0-0-1.csv')
labels = labels_df['label'].values

label_encoder = LabelEncoder()
label_encoder.fit(labels)

def download_and_preprocess_image(url, target_size=(336, 336)):
    response = requests.get(url)
    image = Image.open(io.BytesIO(response.content))
    image = image.resize(target_size)
    image_array = np.array(image) / 255.0
    if image_array.shape[-1] == 4:  # Si l'image a un canal alpha
        image_array = image_array[..., :3]  # Retirer le canal alpha
    image_array = np.expand_dims(image_array, axis=0)
    return image_array

# URL de l'image pour le test
url = 'https://as2.ftcdn.net/v2/jpg/00/47/10/49/1000_F_47104960_17G7ayVOOcu4dBsSYMxW3Z8BnhR1TQdK.jpg'
image_array = download_and_preprocess_image(url)

# Faire une prédiction en utilisant le modèle
predictions = model.predict(image_array)

# Obtenir les top 5 prédictions et leurs scores
top_5_indices = np.argsort(predictions[0])[-5:][::-1]
top_5_scores = predictions[0][top_5_indices]
top_5_labels = label_encoder.inverse_transform(top_5_indices)

# Afficher les top 5 prédictions avec leurs scores
for index, label, score in zip(top_5_indices, top_5_labels, top_5_scores):
    print(f"Index: {index}, Species: {label}, Score: {score:.4f}")

# Télécharger et afficher l'image avec les résultats
response = requests.get(url)
image = Image.open(io.BytesIO(response.content))

plt.imshow(image)
plt.title(f"Top Prediction: {top_5_labels[0]} ({top_5_scores[0]:.4f})")
plt.axis('off')
plt.show()

I got : Index: 3, Species: Dacelo novaeguineae, Score: 1.0000 Index: 5, Species: Parabuteo unicinctus, Score: 0.0000 Index: 6, Species: Pelecanus rufescens, Score: 0.0000 Index: 4, Species: Hippotragus equinus, Score: 0.0000 Index: 2, Species: Ara macao, Score: 0.0000

And it does not matter the image I got always the same result with the Dacelo as first result with a score of 1