6

I am using the keras subclassing module to re-make a previously functional model that requires two inputs and two outputs. I cannot find any documentation on if/how this is possible.

Does the TF2.0/Keras subclassing API allow for mutli-input?

Input to my functional model, and the build is simple:

word_in = Input(shape=(None,))  # sequence length
char_in = Input(shape=(None, None)) 
... layers...
m = Model(inputs=[word_in, char_in], outputs=[output_1, output_2])
Jacob B
  • 694
  • 10
  • 21

2 Answers2

12

Sub-classed model for multiple inputs is no different than like single input model.

class MyModel(Model):
    def __init__(self):
        super(MyModel, self).__init__()
        # define layers
        self.dense1 = Dense(10, name='d1')
        self.dense2 = Dense(10, name='d2')

    def call(self, inputs):
        x1 = inputs[0]
        x2 = inputs[1]
        # define model
        return x1, x2

You can define your layers in in __init__ and define your model in call method.

word_in = Input(shape=(None,))  # sequence length
char_in = Input(shape=(None, None)) 

model = MyModel()
model([word_in, char_in])
# returns 
# (<tf.Tensor 'my_model_4/my_model_4/Identity:0' shape=(?, ?) dtype=float32>,
# <tf.Tensor 'my_model_4/my_model_4_1/Identity:0' shape=(?, ?, ?) dtype=float32>)
Vivek Mehta
  • 2,612
  • 2
  • 18
  • 30
  • I see, is there a way to define the Input Layers within the model itself? It becomes more messy to have layers both outside and inside the model. – Jacob B Jan 15 '20 at 19:00
  • 1
    No need to define Input Layers outside, you can directly pass actual input to model this way. – Vivek Mehta Jan 16 '20 at 04:45
5

assume you have 3 inputs ( for example roberta model QA task)

    class MasoudModel2(tf.keras.Model):

  def __init__(self):
    # in __init__ you define all the layers
    super(MasoudModel2, self).__init__()
    self.dense1 = tf.keras.layers.Dense(4, activation=tf.nn.relu)
    self.dense2 = tf.keras.layers.Dense(10, activation='softmax')


  def call(self, inputs):
    ids = inputs[0]
    toks = inputs[1]
    att_mask = inputs[2]
    # let's skip real layers
    a = self.dense1(ids)
    b = self.dense2(att_mask)
    return a, b

and then :

ids = tf.keras.Input((MAX_LEN), dtype = tf.int32)
att_mask = tf.keras.Input((MAX_LEN), dtype = tf.int32)
toks = tf.keras.Input((MAX_LEN), dtype = tf.int32)
model2 = MasoudModel2()
model2([ids, att_mask, toks])

JUST FOR MORE INFO : if you want functional API too.

def functional_type():
    ids = tf.keras.Input((MAX_LEN), dtype = tf.int32)
    att_mask = tf.keras.Input((MAX_LEN), dtype = tf.int32)
    toks = tf.keras.Input((MAX_LEN), dtype = tf.int32)
    
    
    c = tf.keras.layers.Dense(10, activation='softmax')(ids)
    d = tf.keras.layers.Dense(3, activation = 'softmax')(att_mask)
    
    model = tf.keras.Model(inputs=[ids, toks, att_mask], outputs =[c, d])
    
    
    return model

and then ( Note: last 2 indexes of the first argument are answers. )

model.fit([input_ids[idxT,], attention_mask[idxT,], token_type_ids[idxT,]], [start_tokens[idxT,], end_tokens[idxT,]], 
        epochs=3, batch_size=32, verbose=DISPLAY, callbacks=[sv],