I am getting this error when I am defining a custom callback function.
'NoneType' object is not subscriptable
Code sample
class Metrics(tf.keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self._data = []
def on_epoch_end(self, batch, logs={}):
X_val, y_val = self.validation_data[0], self.validation_data[1]
y_predict = np.asarray(model.predict(X_val))
y_val = np.argmax(y_val, axis=1)
y_predict = np.argmax(y_predict, axis=1)
self._data.append({
'val_jaccard': jaccard(y_val, y_predict),
'val_f1': f1_score(y_val, y_predict),
'val_precision': recall_score(y_val, y_predict),
'val_jaccard': precision_score(y_val, y_predict),
})
return
metrics = Metrics()
model.fit((item for item in image_data),steps_per_epoch=steps_per_epoch,
epochs=20, validation_data = (item for item in image_data_val), validation_steps = valid_step , callbacks = [metrics], verbose=2)
Previously I was getting another error: "AttributeError: 'Sequential' object has no attribute 'validation_data'.
In order to solve that error, I removed self.model.validation_data
with self.validation_data
as suggested here. After which I landed up to this error. I am not able to understand the source of this error
Keras version is 2.2.4
Complete traceback as requested
Epoch 1/20
Exception ignored in: <bound method BaseSession._Callable.__del__ of <tensorflow.python.client.session.BaseSession._Callable object at 0x7f8fbe48fa20>>
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1473, in __del__
self._session._session, self._handle)
tensorflow.python.framework.errors_impl.CancelledError: (None, None, 'Session has been closed.')
Exception ignored in: <bound method BaseSession._Callable.__del__ of <tensorflow.python.client.session.BaseSession._Callable object at 0x7f8fbe42f2e8>>
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1473, in __del__
self._session._session, self._handle)
tensorflow.python.framework.errors_impl.CancelledError: (None, None, 'Session has been closed.')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-102-43fa8dafc96c> in <module>()
5 model.fit((item for item in image_data),steps_per_epoch=steps_per_epoch, epochs=20,
6 validation_data = (item for item in image_data_val),
----> 7 validation_steps = valid_step , callbacks = [metrics], verbose=2)
8 eval_model=model.evaluate(image_batch, label_batch)
9 eval_model
4 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/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)
671 use_multiprocessing=use_multiprocessing,
672 shuffle=shuffle,
--> 673 initial_epoch=initial_epoch)
674 if training_utils.is_eager_dataset_or_iterator(x):
675 # Make sure that y, sample_weights, validation_split are not passed.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
1431 shuffle=shuffle,
1432 initial_epoch=initial_epoch,
-> 1433 steps_name='steps_per_epoch')
1434
1435 def evaluate_generator(self,
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_generator.py in model_iteration(model, data, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch, mode, batch_size, steps_name, **kwargs)
329 if mode == ModeKeys.TRAIN:
330 # Epochs only apply to `fit`.
--> 331 callbacks.on_epoch_end(epoch, epoch_logs)
332 progbar.on_epoch_end(epoch, epoch_logs)
333
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/callbacks.py in on_epoch_end(self, epoch, logs)
309 logs = logs or {}
310 for callback in self.callbacks:
--> 311 callback.on_epoch_end(epoch, logs)
312
313 def on_train_batch_begin(self, batch, logs=None):
<ipython-input-101-71d6af0b20ff> in on_epoch_end(self, batch, logs)
14
15 def on_epoch_end(self, batch, logs={}):
---> 16 X_val, y_val = self.validation_data[0], self.validation_data[1]
17 y_predict = np.asarray(model.predict(X_val))
18 y_val = np.argmax(y_val, axis=1)
TypeError: 'NoneType' object is not subscriptable
UPDATE
Based on the suggestion, I am using keras for callback i.e class Metrics(keras.callback.Callback)
. After this solution, my original error is gone but I am getting another error which is AttributeError: 'Metrics' object has no attribute 'on_train_batch_begin'
I don't really know this error.
The traceback for the new error is
Epoch 1/20
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-60-43fa8dafc96c> in <module>()
5 model.fit((item for item in image_data),steps_per_epoch=steps_per_epoch, epochs=20,
6 validation_data = (item for item in image_data_val),
----> 7 validation_steps = valid_step , callbacks = [metrics], verbose=2)
8 eval_model=model.evaluate(image_batch, label_batch)
9 eval_model
3 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/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)
671 use_multiprocessing=use_multiprocessing,
672 shuffle=shuffle,
--> 673 initial_epoch=initial_epoch)
674 if training_utils.is_eager_dataset_or_iterator(x):
675 # Make sure that y, sample_weights, validation_split are not passed.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)
1431 shuffle=shuffle,
1432 initial_epoch=initial_epoch,
-> 1433 steps_name='steps_per_epoch')
1434
1435 def evaluate_generator(self,
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_generator.py in model_iteration(model, data, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, validation_freq, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch, mode, batch_size, steps_name, **kwargs)
258 # Callbacks batch begin.
259 batch_logs = {'batch': step, 'size': batch_size}
--> 260 callbacks._call_batch_hook(mode, 'begin', step, batch_logs)
261 progbar.on_batch_begin(step, batch_logs)
262
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/callbacks.py in _call_batch_hook(self, mode, hook, batch, logs)
245 t_before_callbacks = time.time()
246 for callback in self.callbacks:
--> 247 batch_hook = getattr(callback, hook_name)
248 batch_hook(batch, logs)
249 self._delta_ts[hook_name].append(time.time() - t_before_callbacks)
AttributeError: 'Metrics' object has no attribute 'on_train_batch_begin'
TypeError: 'NoneType' object is not subscriptable Solution The best way to resolve this issue is by not assigning the sort() method to any variable and leaving the numbers.
The error, NoneType object is not subscriptable, means that you were trying to subscript a NoneType object. This resulted in a type error. 'NoneType' object is not subscriptable is the one thrown by python when you use the square bracket notation object[key] where an object doesn't define the __getitem__ method.
Its a bug in tf.keras
, they deprecated the validation_data
parameter and no longer set the validation_data
of the callback, its always set to None.
Your option is not to use tf.keras
and just use the official keras
package, I tested your code and it works in Keras 2.2.4. Alternatively you could also just pass your validation data to the __init__
of your callback and set it there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With