Keras AttributeError: 'NoneType' object has no attribute 'endswith' in load_model

Viewed 1425

I am working with a course assignment, where I have to save and load models in keras. My code for creating a model, training it and saving it is

def get_new_model(input_shape):
    """
    This function should build a Sequential model according to the above specification. Ensure the 
    weights are initialised by providing the input_shape argument in the first layer, given by the
    function argument.
    Your function should also compile the model with the Adam optimiser, sparse categorical cross
    entropy loss function, and a single accuracy metric.
    """
    
    model = Sequential([
        Conv2D(16, kernel_size=(3,3),activation='relu',padding='Same', name='conv_1', input_shape=input_shape),
        Conv2D(8, kernel_size=(3,3), activation='relu', padding='Same', name='conv_2'),
        MaxPooling2D(pool_size=(8,8), name='pool_1'),
        tf.keras.layers.Flatten(name='flatten'),
        Dense(32, activation='relu', name='dense_1'),
        Dense(10, activation='softmax', name='dense_2')
    ])
    model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['acc'])
    return model

model = get_new_model(x_train[0].shape)


def get_checkpoint_every_epoch():
    """
    This function should return a ModelCheckpoint object that:
    - saves the weights only at the end of every epoch
    - saves into a directory called 'checkpoints_every_epoch' inside the current working directory
    - generates filenames in that directory like 'checkpoint_XXX' where
      XXX is the epoch number formatted to have three digits, e.g. 001, 002, 003, etc.
    """
    path = 'checkpoints_every_epoch/checkpoint_{epoch:02d}'
    checkpoint = ModelCheckpoint(filepath = path, save_weights_only=True, save_freq= 'epoch')
    return checkpoint


def get_checkpoint_best_only():
    """
    This function should return a ModelCheckpoint object that:
    - saves only the weights that generate the highest validation (testing) accuracy
    - saves into a directory called 'checkpoints_best_only' inside the current working directory
    - generates a file called 'checkpoints_best_only/checkpoint' 
    """
    path = 'checkpoints_best_only/checkpoint'
    checkpoint = ModelCheckpoint(filepath = path, save_best_only=True, save_weights_only=True, monitor='val_acc')
    return checkpoint
    
def get_early_stopping():
    """
    This function should return an EarlyStopping callback that stops training when
    the validation (testing) accuracy has not improved in the last 3 epochs.
    HINT: use the EarlyStopping callback with the correct 'monitor' and 'patience'
    """
    return EarlyStopping(monitor= 'val_acc', patience=3)
    
checkpoint_every_epoch = get_checkpoint_every_epoch()
checkpoint_best_only = get_checkpoint_best_only()
early_stopping = get_early_stopping()
callbacks = [checkpoint_every_epoch, checkpoint_best_only, early_stopping]
model.fit(x_train, y_train, epochs=50, validation_data=(x_test, y_test), callbacks=callbacks)

Here I am saving every epoch's weight in checkpoints_every_epoch/checkpoint_{epoch:02d} and best weights in checkpoints_best_only/checkpoint. Now when I want to load both, using this code

def get_model_last_epoch(model):
    """
    This function should create a new instance of the CNN you created earlier,
    load on the weights from the last training epoch, and return this model.
    """
    filepath = tf.train.latest_checkpoint('checkpoint_every_epoch')
    model.load_weights(filepath)
    return model
    
    
def get_model_best_epoch(model):
    """
    This function should create a new instance of the CNN you created earlier, load 
    on the weights leading to the highest validation accuracy, and return this model.
    """
    filepath = tf.train.latest_checkpoint('checkpoint_best_only')
    model.load_weights(filepath)
    return model
model_last_epoch = get_model_last_epoch(get_new_model(x_train[0].shape))
model_best_epoch = get_model_best_epoch(get_new_model(x_train[0].shape))
print('Model with last epoch weights:')
get_test_accuracy(model_last_epoch, x_test, y_test)
print('')
print('Model with best epoch weights:')
get_test_accuracy(model_best_epoch, x_test, y_test)
    

I get an error which is

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-18-b6d169507ca4> in <module>
      3 # Verify that the second has a higher validation (testing) accuarcy.
      4 
----> 5 model_last_epoch = get_model_last_epoch(get_new_model(x_train[0].shape))
      6 model_best_epoch = get_model_best_epoch(get_new_model(x_train[0].shape))
      7 print('Model with last epoch weights:')

<ipython-input-15-6f7ff0c732b4> in get_model_last_epoch(model)
     10     """
     11     filepath = tf.train.latest_checkpoint('checkpoint_every_epoch')
---> 12     model.load_weights(filepath)
     13     return model
     14 

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py in load_weights(self, filepath, by_name)
    179         raise ValueError('Load weights is not yet supported with TPUStrategy '
    180                          'with steps_per_run greater than 1.')
--> 181     return super(Model, self).load_weights(filepath, by_name)
    182 
    183   @trackable.no_automatic_dependency_tracking

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/network.py in load_weights(self, filepath, by_name)
   1137             format.
   1138     """
-> 1139     if _is_hdf5_filepath(filepath):
   1140       save_format = 'h5'
   1141     else:

/opt/conda/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/network.py in _is_hdf5_filepath(filepath)
   1447 
   1448 def _is_hdf5_filepath(filepath):
-> 1449   return (filepath.endswith('.h5') or filepath.endswith('.keras') or
   1450           filepath.endswith('.hdf5'))
   1451 

AttributeError: 'NoneType' object has no attribute 'endswith'

Can i know what is wrong in my code, or how to improve it and remove error.


Edit:

If i do this on an individual model without using the function tf.train.latest_checkpoint to get the last file name, it works. That is

dummyModel.load_weights('checkpoints_every_epoch/checkpoint_23')
print('Model with last epoch weights:')
get_test_accuracy(dummyModel, x_test, y_test)
print('')
1 Answers

I got it. There was an error in the file pathname. I spend a lot of time to figure it out. So correct function is

def get_model_last_epoch(model):
    """
    This function should create a new instance of the CNN you created earlier,
    load on the weights from the last training epoch, and return this model.
    """
    model.load_weights(tf.train.latest_checkpoint('checkpoints_every_epoch'))
    return model
    
    
def get_model_best_epoch(model):
    """
    This function should create a new instance of the CNN you created earlier, load 
    on the weights leading to the highest validation accuracy, and return this model.
    """
    #filepath = tf.train.latest_checkpoint('checkpoints_best_only')
    model.load_weights(tf.train.latest_checkpoint('checkpoints_best_only'))
    return model
    

and it will not give error, because filename in tf.train.latest_checkpoint is correct

Related