I am working on a multi-output classification task using Keras and ResNet50. The dataset consists of facial images, and each image has four associated labels representing the intensity of boredom, engagement, confusion, and frustration, each ranging from 1 to 4.
I want to create a ResNet-based model with multiple outputs to predict these four labels simultaneously.
from tensorflow import keras
from tensorflow.keras import Input
from tensorflow.keras.applications import ResNet50
from tensorflow.keras import layers, models
base_model = ResNet50(input_shape=(128, 128, 3),
include_top=False,
weights='imagenet')
model = models.Sequential([
base_model,
layers.GlobalAveragePooling2D(),
layers.Dense(64, activation='relu'),
layers.Dense(4, activation='softmax', name='Boredom'),
layers.Dense(4, activation='softmax', name='Engagement'),
layers.Dense(4, activation='softmax', name='Confusion'),
layers.Dense(4, activation='softmax', name='Frustration')
])
model.compile(optimizer='adam',
loss={'Boredom': 'categorical_crossentropy',
'Engagement': 'categorical_crossentropy',
'Confusion': 'categorical_crossentropy',
'Frustration': 'categorical_crossentropy'},
metrics=['accuracy'])
model.summary()
Error:
ValueError: Found unexpected losses or metrics that do not correspond to any Model output: dict_keys(['Boredom', 'Engagement', 'Confusion']). Valid mode output names: ['Frustration']. Received struct is: {'Boredom': 'categorical_crossentropy', 'Engagement': 'categorical_crossentropy', 'Confusion': 'categorical_crossentropy'}
I don't really know what is wrong, the names are matching
If you use Sequential
you have in general only one output.
Use the functional approach to have multiple output layers.
from tensorflow import keras
from tensorflow.keras import Input
from tensorflow.keras.applications import ResNet50
from tensorflow.keras import layers, models
inputs = Input(shape=(128, 128, 3))
base_model = ResNet50(input_shape=(128, 128, 3),
include_top=False,
weights='imagenet')
x = base_model(inputs)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(64, activation='relu')(x)
# Now generate 4 outputs
boredom = layers.Dense(4, activation='softmax', name='Boredom')(x)
engagement = layers.Dense(4, activation='softmax', name='Engagement')(x)
confusion = layers.Dense(4, activation='softmax', name='Confusion')(x)
frustration = layers.Dense(4, activation='softmax', name='Frustration')(x)
# explicitly state your output layers when creating the model:
model = models.Model(inputs, [boredom, engagement, confusion, frustration])
model.compile(optimizer='adam',
loss={'Boredom': 'categorical_crossentropy',
'Engagement': 'categorical_crossentropy',
'Confusion': 'categorical_crossentropy',
'Frustration': 'categorical_crossentropy'},
metrics=['accuracy'])