Customize model.fit() in Tensorflow Keras - TypeError: TypeError: compile() got an unexpected keyword argument 'optimizer'

Viewed 3087

I am trying to implement my own weight training algorithm by modifying model.fit() in Keras. I have read this article from Keras which explains it quite well based on GANs. However, the issue that I am facing at the moment is the following:

I have followed exactly the same steps and procedures as explained in the article but I have substitute their training algorithm with my own. The error that I get is

TypeError: compile() got an unexpected keyword argument 'optimizer'

The model that I have created uses Tensorflow 1.15. Also, I use ELMO Embedding layer from Tensorflow hub for which Tensorflow 1.15 is required (since it does not support V2+ yet)

def Predictor():
  input_sentence = Input(shape=(250,), dtype=tf.int32)
  embedding = ELMoEmbedding(index_word=index_word, trainable=False)(input_sentence)
  lstm = LSTM(1024)(embedding)
  dense = Dense(64, activation='relu')(lstm)
  pred = Dense(5, activation='softmax')(dense)

  model = Model(inputs=[input_sentence], outputs=pred)

  return model

def Adversary():
  input_features = Input((1,))
  dense1 = Dense(64, activation='relu')(input_features)
  pred = Dense(5, activation='sigmoid')(dense1)

  model = Model(inputs=[input_features], outputs=[pred])

  return model

class Mitigator(Model):

    def __init__(self, predictor, adversary, debias_param):
        super(Mitigator, self).__init__()
        self.predictor = predictor
        self.adversary = adversary
        self.debias_param = debias_param

    def compile(self, a_optimizer, p_optimizer, a_loss, p_loss):
        super(Mitigator, self).compile()
        self.a_optimizer = a_optimizer
        self.p_optimizer = p_optimizer
        self.a_loss = a_loss
        self.p_loss = p_loss

    def train_step(self, data):
        # Pass tf.data.Dataset element based on numpy arrays
        x, train_y, z_true = data

        # Generate prediction and compute loss for train_step
        y_pred = self.predictor(x)
        pred_loss = self.p_loss(train_y, y_pred)

        # Input data for Adversary
        adv_x = tf.concat([y_pred, train_y], axis=1)

        # Train Adversary
        z_pred = self.adversary(adv_x)
        adv_loss = self.a_loss(z_true, z_pred)
        adv_grad = {v: g for (g, v) in self.a_optimizer.compute_gradients(adv_loss)}
        adv_min = self.a_optimizer.minimize(adv_loss, var_list=self.adversary.trainable_weights)

        # Train Predictor
        pred_grad = []

        for (g, v) in self.p_optimizer.compute_gradients(pred_loss):
            unit_adv = tf_normalize(adv_grad[v])
            g -= tf.math.reduce_sum(g * unit_adv) * unit_adv
            g -= self.debias_param * adv_grad[v]
            pred_grad.append((g, v))
            pred_min = self.p_optimizer.apply_gradients(pred_grad)

        return {"pred_loss": pred_loss, "adv_loss": adv_loss}

    def test_step(self, data):
        # Pass tf.data.Dataset element based on numpy arrays
        x, y_true, z_true = data

        # Compute predictions for Predictor
        y_pred = self.predictor(x, training=False)

        # Input data for Adversary
        adv_x = tf.concat([y_pred, y_true], axis=1)

        # Compute predictions for Adversary
        z_pred = self.adversary(adv_x, training=False)

        # Update losses
        self.p_loss(y_pred, y_true)
        self.a_loss(z_pred, z_true)

The error occurs when I run the following code:

mitigator = Mitigator(predictor=Predictor, adversary=Adversary, debias_param=1)

mitigator.compile(a_optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
                  p_optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
                  a_loss='binary_crossentropy',
                  p_loss='categorical_crossentropy')

mitigator.fit(x=train_text, y=[train_y, z_true], epochs=5)

So far, I have ran the code from the Keras article to check if the same error occurs but it does not. The GAN example runs fine.

Does anyone know how I can solve this error? If more information is needed to help me, please let me know.

Update

As requested, the full traceback for the error is given below.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-4f1a8c7cee8b> in <module>()
----> 1 mitigator.fit(x=train_text, y=[train_y, z_true], epochs=5)

3 frames
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)
    725         max_queue_size=max_queue_size,
    726         workers=workers,
--> 727         use_multiprocessing=use_multiprocessing)
    728 
    729   def evaluate(self,

/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training_arrays.py in fit(self, model, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, **kwargs)
    641         steps=steps_per_epoch,
    642         validation_split=validation_split,
--> 643         shuffle=shuffle)
    644 
    645     if validation_data:

/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, batch_size, check_steps, steps_name, steps, validation_split, shuffle, extract_tensors_from_dataset)
   2430     is_compile_called = False
   2431     if not self._is_compiled and self.optimizer:
-> 2432       self._compile_from_inputs(all_inputs, y_input, x, y)
   2433       is_compile_called = True
   2434 

/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/training.py in _compile_from_inputs(self, all_inputs, target, orig_inputs, orig_target)
   2665         sample_weight_mode=self.sample_weight_mode,
   2666         run_eagerly=self.run_eagerly,
-> 2667         experimental_run_tf_function=self._experimental_run_tf_function)
   2668 
   2669   # TODO(omalleyt): Consider changing to a more descriptive function name.

TypeError: compile() got an unexpected keyword argument 'optimizer'
2 Answers

You could set the optimizer inside the compile() or train_step() function.

class Mitigator(Model):

    def __init__(self, predictor, adversary, debias_param):
        super(Mitigator, self).__init__()
        self.predictor = predictor
        self.adversary = adversary
        self.debias_param = debias_param
             
    def compile(self):
        super(Mitigator, self).compile()
        self.a_optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
        self.p_optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
def train_step(self, data):
        a_optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
        p_optimizer = tf.keras.optimizers.Adam(learning_rate=0.0001)
        # Pass tf.data.Dataset element based on numpy arrays
        x, y_true, z_true = data

Set the self._is_compiled = True just make the code think your code is compiled, I do not think this could work.

check your tensorflow version

import tensorflow print(tensorflow.version)

it must be above v2.4

so if your version is below you have two option either you install latest version of Tensorflow and keras or use google colabs.

since these customised training method and some preprocessing APIs were included in recent versions of keras and tensorflow.

Related