Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

error in constructing multioutput model in keras

I am trying to create a multi-output model in Keras. The model starts with a convolution and aims to stack the results of two separate dense layers. I created some random data for a regression task where x1 is the inputs and df is labels. The df contains three columns. After defining the train and test split and forming the model, I receive an error in fitting the model. Can anyone help me to correct my code?

x1 = np.random.rand(500, 244, 244, 20) 
df = pd.DataFrame(np.random.uniform(0,1,size=(500, 3)), columns=list('XYZ'))     
x_train, x_test, y_train, y_test = train_test_split(x1,df ,test_size=0.2)

n1_y_train=y_train['X'].values
n1_y_test=y_test['X'].values

n2_y_train=y_train['Y'].values
n2_y_test=y_test['Y'].values

n3_y_train=y_train['Z'].values
n3_y_test=y_test['Z'].values

train_shape = x_train.shape

inputs = layers.Input(shape = train_shape[1:])

x = layers.Conv2D(16, (3,3), activation='relu', padding="same")(inputs)
x = layers.Flatten()(x)

# ‌section1:
l1 = layers.Dense(16, activation='relu')(x)
l1 = layers.Dense(1)(l1)

# ‌section2:
l2 = layers.Dense(32, activation='relu')(x)
l2 = layers.Dense(1)(l2)

output1 = tf.reduce_mean(tf.stack([l1, l2], axis=0), axis=0, name = "output1")
output2 = tf.reduce_mean(tf.stack([l1, l2], axis=0), axis=0, name = "output2")
output3 = tf.reduce_mean(tf.stack([l1, l2], axis=0), axis=0, name = "output3")

model = tf.keras.models.Model(inputs, [output1,output2,output3])


model.compile(
        optimizer=tf.keras.optimizers.Adam(),
        loss= tf.keras.losses.mse,
        metrics=tf.keras.metrics.RootMeanSquaredError(name="rmse"))

history = model.fit(x_train,{"output1": n1_y_train, "output2": n2_y_train, "output3": n3_y_train},
validation_data = (x_test,{"output1": n1_y_test, "output2": n2_y_test, "output3": n3_y_test}),
verbose=2,
epochs=100,
batch_size=32)

error:

ValueError: Found unexpected losses or metrics that do not correspond to any Model output: dict_keys(['output1', 'output2', 'output3']). Valid mode output names: ['tf.math.reduce_mean', 'tf.math.reduce_mean_1', 'tf.math.reduce_mean_2']. Received struct is: {'output1': <tf.Tensor 'IteratorGetNext:1' shape=(None,) dtype=float32>, 'output2': <tf.Tensor 'IteratorGetNext:2' shape=(None,) dtype=float32>, 'output3': <tf.Tensor 'IteratorGetNext:3' shape=(None,) dtype=float32>}.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You should wrap the output layers with Lambda layers and use tf.concat instead of tf.stack. By using Lambda layers, you can explicitly set the names of the outputs, which will be captured by your model. Here is a working example:

import pandas as pd
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split

x1 = np.random.rand(10, 244, 244, 20) 
df = pd.DataFrame(np.random.uniform(0,1,size=(10, 3)), columns=list('XYZ'))     
x_train, x_test, y_train, y_test = train_test_split(x1,df ,test_size=0.2)

n1_y_train=y_train['X'].values
n1_y_test=y_test['X'].values

n2_y_train=y_train['Y'].values
n2_y_test=y_test['Y'].values

n3_y_train=y_train['Z'].values
n3_y_test=y_test['Z'].values

train_shape = x_train.shape
inputs = tf.keras.layers.Input(shape = train_shape[1:])

x = tf.keras.layers.Conv2D(16, (3,3), activation='relu', padding="same")(inputs)
x = tf.keras.layers.Flatten()(x)
l1 = tf.keras.layers.Dense(16, activation='relu')(x)
l1 = tf.keras.layers.Dense(1)(l1)
l2 = tf.keras.layers.Dense(32, activation='relu')(x)
l2 = tf.keras.layers.Dense(1)(l2)

output1 = tf.keras.layers.Lambda(lambda x: tf.reduce_mean(x, axis=1, keepdims=True), name='output1')(tf.concat([l1, l2], axis=1))
output2 = tf.keras.layers.Lambda(lambda x: tf.reduce_mean(x, axis=1, keepdims=True), name='output2')(tf.concat([l1, l2], axis=1))
output3 = tf.keras.layers.Lambda(lambda x: tf.reduce_mean(x, axis=1, keepdims=True), name='output3')(tf.concat([l1, l2], axis=1))

model = tf.keras.Model(inputs, [output1,output2,output3])

model.compile(
        optimizer=tf.keras.optimizers.Adam(),
        loss= tf.keras.losses.mse,
        metrics=tf.keras.metrics.RootMeanSquaredError(name="rmse"))
history = model.fit(x_train,{"output1": n1_y_train, "output2": n2_y_train, "output3": n3_y_train},
validation_data = (x_test,{"output1": n1_y_test, "output2": n2_y_test, "output3": n3_y_test}),
verbose=2,
epochs=100,
batch_size=2)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading