I got RecursionError while load_model with a custom_objects in keras〔RecursionError: maximum recursion depth exceeded in __instancecheck__〕

Question:

  • I tried to train a model with a customized activation function, and saved a model for each epoch.
  • I made a loop of 3500 iterations(each iteration should be an epoch), in each iteration the model which saved in the previous iteration is loaded (using keras‘s load_model()).
  • The model keeps training and saving until 90 iterations, then encounters RecursionError

Here is the code:

#define custom activation
class Double_Tanh(Activation):
    def __init__(self, activation, **kwargs):
        super(Double_Tanh, self).__init__(activation, **kwargs)
        self.__name__ = 'double_tanh'

def double_tanh(x):
    return (K.tanh(x) * 2)

get_custom_objects().update({'double_tanh':Double_Tanh(double_tanh)})

# Model Generation
model = Sequential()
#check https://machinelearningmastery.com/use-weight-regularization-lstm-networks-time-series-forecasting/
model.add(LSTM(25, input_shape=(20,1), dropout=0.0, kernel_regularizer=l1_l2(0.00,0.00), bias_regularizer=l1_l2(0.00,0.00)))
model.add(Dense(1))
model.add(Activation(double_tanh))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mse', 'mae'])

model.summary()


epoch_num=1
max_epoch = 3500
for _ in range(max_epoch):

    # train the model
    dir_ = './lstm_only_models/LSTM_only/'
    file_list = os.listdir(dir_)
    if len(file_list) != 0 :
        epoch_num = len(file_list) + 1
        recent_model_name = 'epoch'+str(epoch_num-1)+'.h5'
        filepath = './lstm_only_models/LSTM_only/' + recent_model_name
        custom_objects = {"Double_Tanh": Double_Tanh}
        with keras.utils.custom_object_scope(custom_objects):
            model = load_model(filepath)

    filepath = './lstm_only_models/LSTM_only/epoch'+str(epoch_num)+'.h5'

    checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=False, mode='min')
    callbacks_list = [checkpoint]
    if len(callbacks_list) == 0:
        model.fit(_train_X, _train_Y, epochs=1, batch_size=500, shuffle=True)
    else:
        model.fit(_train_X, _train_Y, epochs=1, batch_size=500, shuffle=True, callbacks=callbacks_list)

    # test the model
    score_train = model.evaluate(_train_X, _train_Y)
    score_dev = model.evaluate(_dev_X, _dev_Y)
    score_test1 = model.evaluate(_test1_X, _test1_Y)
    score_test2 = model.evaluate(_test2_X, _test2_Y)

Error message:

Traceback (most recent call last):
  File "LSTM_only.py", line 110, in <module>
    model = load_model(filepath, custom_objects=custom_objects)
  File "/usr/local/lib/python3.8/dist-packages/keras/utils/traceback_utils.py", line 67, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "LSTM_only.py", line 65, in __init__
    super(Double_Tanh, self).__init__(activation, **kwargs)
  File "LSTM_only.py", line 65, in __init__
    super(Double_Tanh, self).__init__(activation, **kwargs)
  File "LSTM_only.py", line 65, in __init__
    super(Double_Tanh, self).__init__(activation, **kwargs)
  [Previous line repeated 86 more times]
RecursionError: maximum recursion depth exceeded in __instancecheck__

I am not sure why does this happen, so my questions are:

  • How should I adjust my code?
  • What’s the reason of this error?
Asked By: theabc50111

||

Answers:

According to the documents: https://keras.io/guides/serialization_and_saving/#savedmodel-format

  • Using model.save("my_model") enables Keras to restore both built-in layers as well as custom objects.

So don’t need to create the class and register custom_objects.

All we need to do is change the save-format.

Here is the correct codes:

def double_tanh(x):
    return (K.tanh(x) * 2)

# Model Generation
model = Sequential()
#check https://machinelearningmastery.com/use-weight-regularization-lstm-networks-time-series-forecasting/
model.add(LSTM(25, input_shape=(20,1), dropout=0.0, kernel_regularizer=l1_l2(0.00,0.00), bias_regularizer=l1_l2(0.00,0.00)))
model.add(Dense(1, activation=double_tanh))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['mse', 'mae'])

epoch_num=1
max_epoch = 3500
for _ in range(max_epoch):

    # train the model
    dir_ = './lstm_only_models/LSTM_only/'
    file_list = os.listdir(dir_)
    if len(file_list) != 0 :
        epoch_num = len(file_list) + 1
        recent_model_name = 'epoch'+str(epoch_num-1)
        filepath = './lstm_only_models/LSTM_only/' + recent_model_name
        model = load_model(filepath)

    filepath = './lstm_only_models/LSTM_only/epoch'+str(epoch_num)

    model.fit(_train_X, _train_Y, epochs=1, batch_size=500, shuffle=True)
    model.save(filepath)

    # test the model
    score_train = model.evaluate(_train_X, _train_Y)
    score_dev = model.evaluate(_dev_X, _dev_Y)
    score_test1 = model.evaluate(_test1_X, _test1_Y)
    score_test2 = model.evaluate(_test2_X, _test2_Y)

Answered By: theabc50111