'NoneType' 对象不可订阅 - Keras 自定义回调出错 class

'NoneType' object is not subscriptable - error at Keras custom callback class

我在定义自定义回调函数时遇到此错误。

'NoneType' object is not subscriptable

代码示例

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)

之前我遇到了另一个错误:"AttributeError: 'Sequential' object has no attribute 'validation_data'. 为了解决这个错误,我按照建议 here 删除了 self.model.validation_dataself.validation_data。之后我遇到了这个错误。我无法理解此错误的来源

Keras 版本为 2.2.4

按要求完成回溯

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

更新

根据建议,我正在使用 keras 进行回调,即 class Metrics(keras.callback.Callback)。在此解决方案之后,我原来的错误消失了,但我收到另一个错误 AttributeError: 'Metrics' object has no attribute 'on_train_batch_begin' 我真的不知道这个错误。

新错误的回溯是

    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'

这是 tf.keras 中的一个错误,他们弃用了 validation_data 参数并且不再设置回调的 validation_data,它始终设置为 None。

您的选择是不使用 tf.keras 而只使用官方 keras 包,我测试了您的代码并且它在 Keras 2.2.4 中工作。或者,您也可以将验证数据传递给回调的 __init__ 并将其设置在那里。

我认为你可以通过将 validation_dataset 传递给你的 Metrics class 而不是依赖......来解决这个问题 self.validation_data 应该如何设置?