Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
BastienPailloux opened this issue Aug 2, 2024 · 3 comments
Assignees
Labels

Comments

@BastienPailloux
Copy link

**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
Copy link
Member

fchollet commented Aug 2, 2024

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

@BastienPailloux
Copy link
Author

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
Copy link
Author

BastienPailloux commented Aug 5, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants