Home > Mobile >  error in constructing multioutput model in keras
error in constructing multioutput model in keras

Time:02-01

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>}.

CodePudding user response:

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)

  •  Tags:  
  • Related