0

Say I have an MLP that looks like:

model = models.Sequential()

model.add(layers.Dense(200, activation = "relu", input_dim=250))
model.add(layers.Dense(100, activation="relu"))
model.add(layers.Dense(75, activation="relu"))
model.add(layers.Dense(50, activation="relu"))
model.add(layers.Dense(17, activation = "softmax"))


model.compile(optimizer = optimizers.Adam(lr=0.001), 
         loss = "categorical_crossentropy", 
         metrics = ['MeanSquaredError', 'AUC' , 'accuracy',tf.keras.metrics.Precision()])

history = model.fit(X_train, y_train, epochs = 100,
               validation_data = (X_val, y_val))

Now I want, at the final layer, to add a binary classifier for each of the 17 classes, rather than having the 17 classes output altogether with the softmax; Meaning that the binary classifiers should all ramify from to the last layer. Is this possible to do in Keras? I am guessing it should be a different type of model, instead of Sequential()?

EDIT:

I understood that I can't use the Sequential, and changed the model so that:

from tensorflow.keras import Input
from tensorflow.keras import Model
from tensorflow.keras.layers import Dense, Dropout

def test_model(layer_in):

    dense1 = Dense(200, activation = "relu") (layer_in)
    drop1 = Dropout(rate=0.02)(dense1)
    dense2 = Dense(100, activation="relu")(drop1)
    drop2 = Dropout(rate=0.02)(dense2)
    dense3 = Dense(75, activation="relu")(drop2)
    drop3 = Dropout(rate=0.02)(dense3)
    dense4 = Dense(50, activation="relu")(drop3)
    drop4 = Dropout(rate=0.01)(dense4)
    out = Dense(17, activation= "softmax")(drop4)
    return out


layer_in = Input(shape=(250,))
layer_out = test_model(layer_in)

model = Model(inputs=layer_in, outputs=layer_out)

plot_model(model, show_shapes=True)

enter image description here

So I guess the end goal is to have 17 binary layers at the end with a sigmoid function each, that are all connected to drop4...

La Cordillera
  • 410
  • 5
  • 17
  • I am not able to visualize your model. Please draw an architecture and the model can be then drawn accordingly. Meanwhile I have given you an Idea about how you can create a model having multiple outputs. Now you can tweak the Model according to your use – Varun Singh Jun 15 '21 at 02:18
  • @VarunSingh question edited to help you with that... – La Cordillera Jun 15 '21 at 02:26

1 Answers1

0

In your problem you are trying to use Sequential API to create the Model. There are Limitations to Sequential API, you can just create a layer by layer model. It can't handle multiple inputs/outputs. It can't be used for Branching also.

Below is the text from Keras official website: https://keras.io/guides/functional_api/

The functional API makes it easy to manipulate multiple inputs and outputs. This cannot be handled with the Sequential API.

Also this stack link will be useful for you: Keras' Sequential vs Functional API for Multi-Task Learning Neural Network

Now you can create a Model using Functional API or Model Sub Classing.

In case of functional API Your Model will be

Assuming Output_1 is classification with 17 classes Output_2 is calssification with 2 classes and Output_3 is regression

input_layer=Input(shape=(250))
x=Dense(200, activation = "relu")(input_layer)
x=Dense(100, activation = "relu")(x)
x=Dense(75, activation = "relu")(x)
x=Dense(50, activation = "relu")(x)
output_1=Dense(17, activation = "softmax",name='output_1')(x)
output_2=Dense(3, activation = "softmax",name='output_2')(x)
output_3=Dense(1,name='output_3')(x)
model=Model(inputs=input_layer,outputs=[output_1,output_2,output_3])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), 
              loss = {'output_1' : tf.keras.losses.CategoricalCrossentropy(),
                      'output_2' : tf.keras.losses.CategoricalCrossentropy(),
                      'output_3' : "mse"
                     },
              metrics = {'output_1' :'accuracy',
                         'output_2': 'accuracy',
                         'output_3' : tf.keras.metrics.RootMeanSquaredError()
                       }
             )

Update Below is the code assuming that you have 6 classes You can just extend the same for 17 classes

input_layer=Input(shape=(250))
x=Dense(200, activation = "relu")(input_layer)
x=Dense(100, activation = "relu")(x)
x=Dense(75, activation = "relu")(x)
x=Dense(50, activation = "relu")(x)
output_1=Dense(1,activation='softmax', name='output_1')(x)
output_2=Dense(1,activation='softmax',name='output_2' )(x)
output_3=Dense(1,activation='softmax',name='output_3')(x)
output_4=Dense(1,activation='softmax', name='output_4')(x)
output_5=Dense(1,activation='softmax',name='output_5' )(x)
output_6=Dense(1,activation='softmax',name='output_6')(x)
model=Model(inputs=input_layer,outputs=[output_1,output_2,output_3])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01), 
              loss = {'output_1' : tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_2':  tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_3' : tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_4' :tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_5' :tf.keras.losses.SparseCategoricalCrossentropy(),
                         'output_6' :tf.keras.losses.SparseCategoricalCrossentropy()
                     },
              metrics = {'output_1' : 'accuracy',
                         'output_2':  'accuracy',
                         'output_3' : 'accuracy',
                         'output_4' :'accuracy',
                         'output_5' :'accuracy',
                         'output_6' :'accuracy'
                       }
             )
Varun Singh
  • 489
  • 3
  • 13
  • thanks for looking into it. I am not sure if I understand correctly your three outputs? Could you explain them a bit further? What I ask in the question is to have 17 binary outputs for each class. I am not sure if that's what I'll return with your solution – La Cordillera Jun 15 '21 at 02:29
  • these are just the outputs in the last layer. – Varun Singh Jun 15 '21 at 02:32
  • You want 17 binary outputs, Means you want 17 outputs of binary classifcation? And it can belong to mulitple classes? – Varun Singh Jun 15 '21 at 02:33
  • Yes. My original data has 17 labels, and multilabel is not working very nicely (I'm assuming because the labels are not mutually exclusive). So I thought that perhaps a workaround would be an output of 17 binary classifications rather than the softmax output. – La Cordillera Jun 15 '21 at 02:36
  • And yes, each datapoint can belong to different labels – La Cordillera Jun 15 '21 at 02:38
  • You can use loss and metrics according to your own use case. But this is how it can be done – Varun Singh Jun 15 '21 at 02:44