TypeError:使用自定义指标时,__ index__返回了非int(类型NoneType)

时间:2019-04-24 17:44:50

标签: python tensorflow keras

我需要编写一个度量标准,以使我能够针对极端不平衡的多类分类问题对某些模型进行评分。

为此,我为tensorflow.keras编写了自己的自定义指标:

import tensorflow as tf
import tensorflow.keras.backend as K

weight_vector = [class_weights[i] for i in range(n_classes)]
# adapted from https://www.kaggle.com/guglielmocamporese/macro-f1-score-keras
def weighted_macro_f1_score(y_true, y_pred):
  y_true = tf.reshape(y_true, shape=(-1,n_classes))

  y_pred = tf.reshape(y_pred, shape=(-1,n_classes))
  y_pred = tf.argmax(y_pred, axis=-1)
  y_pred = tf.one_hot(y_pred, depth=n_classes)  

  aux = np.array(weight_vector, dtype=np.float32)
  weights = np.vstack([aux]*y_true.shape[0])

  tp = K.sum(K.cast(y_true*y_pred*weights, 'float'))
  fp = K.sum(K.cast((1-y_true)*y_pred*weights, 'float'))
  fn = K.sum(K.cast(y_true*(1-y_pred)*weights, 'float'))

  p = tp / (tp + fp + K.epsilon())
  #print(f"p = {p}")
  r = tp / (tp + fn + K.epsilon())
  #print(f"r = {r}")

  f1 = 2*p*r / (p+r+K.epsilon())
  f1 = tf.where(tf.is_nan(f1), tf.zeros_like(f1), f1)
  return K.mean(f1)

当我在渴望模式下的一些numpy数组上对其进行测试时,我得到了预期的结果。

但是,当我尝试将其输入到model.fit时,出现此错误:

model.compile(
    optimizer='adam', 
    loss='categorical_crossentropy', 
    metrics=metrics, 
    sample_weight_mode="temporal")

history = model.fit(X, Y, epochs=20, sample_weight=sample_weight)

错误:

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-12-6dbe62cf6d4e> in <module>()
      3     loss='categorical_crossentropy',
      4     metrics=metrics,
----> 5     sample_weight_mode="temporal")
      6 
      7 history = model.fit(X, Y, epochs=20, sample_weight=sample_weight)

10 frames

/usr/local/lib/python3.6/dist-packages/tensorflow/python/training/checkpointable/base.py in _method_wrapper(self, *args, **kwargs)
    440     self._setattr_tracking = False  # pylint: disable=protected-access
    441     try:
--> 442       method(self, *args, **kwargs)
    443     finally:
    444       self._setattr_tracking = previous_value  # pylint: disable=protected-access

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in compile(self, optimizer, loss, metrics, loss_weights, sample_weight_mode, weighted_metrics, target_tensors, distribute, **kwargs)
    497           targets=self.targets,
    498           skip_target_indices=skip_target_indices,
--> 499           sample_weights=self.sample_weights)
    500 
    501       # Prepare gradient updates and state updates.

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _handle_metrics(self, outputs, skip_target_indices, targets, sample_weights, masks, return_stateful_result)
   1842                 output,
   1843                 output_mask,
-> 1844                 return_stateful_result=return_stateful_result))
   1845         metric_results.extend(
   1846             self._handle_per_output_metrics(

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _handle_per_output_metrics(self, metrics_dict, y_true, y_pred, mask, weights, return_stateful_result)
   1798           # In graph mode, we build the sub-graph for both the stateful and the
   1799           # stateless fns.
-> 1800           stateful_metric_result = _call_stateful_fn(stateful_fn)
   1801           metric_result = _call_stateless_fn(metric_fn)
   1802           _track_metric_tensors(metric_name, metric_result,

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py in _call_stateful_fn(fn)
   1771         def _call_stateful_fn(fn):
   1772           return training_utils.call_metric_function(
-> 1773               fn, y_true, y_pred, weights=weights, mask=mask)
   1774 
   1775         def _call_stateless_fn(fn):

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_utils.py in call_metric_function(metric_fn, y_true, y_pred, weights, mask)
    850   """Invokes metric function and returns the metric result tensor."""
    851   if mask is None:
--> 852     return metric_fn(y_true, y_pred, sample_weight=weights)
    853 
    854   mask = math_ops.cast(mask, y_pred.dtype)

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py in __call__(self, *args, **kwargs)
    436       The metric value tensor.
    437     """
--> 438     update_op = self.update_state(*args, **kwargs)
    439     with ops.control_dependencies([update_op]):
    440       result_t = self.result()

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py in decorated(metric_obj, *args, **kwargs)
     96     """Decorated function with `add_update()`."""
     97 
---> 98     update_op = update_state_fn(*args, **kwargs)
     99     if update_op is not None:  # update_op will be None in eager execution.
    100       metric_obj.add_update(update_op, inputs=True)

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py in update_state(self, y_true, y_pred, sample_weight)
    647         y_pred, y_true, sample_weight)
    648 
--> 649     matches = self._fn(y_true, y_pred, **self._fn_kwargs)
    650     return super(MeanMetricWrapper, self).update_state(
    651         matches, sample_weight=sample_weight)

<ipython-input-11-030fcade0122> in weighted_macro_f1_score(y_true, y_pred)
      8 
      9   aux = np.array(weight_vector, dtype=np.float32)
---> 10   weights = np.vstack([aux]*y_true.shape[0])
     11 
     12   tp = K.sum(K.cast(y_true*y_pred*weights, 'float'))

/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/tensor_shape.py in __rmul__(self, other)
    408       A Dimension whose value is the product of `self` and `other`.
    409     """
--> 410     return self * other
    411 
    412   def __floordiv__(self, other):

TypeError: __index__ returned non-int (type NoneType)

我对这个结果感到困惑。当我尝试不修改体重平衡的度量标准时,它工作正常,但现在却不起作用。

这是怎么回事?我该如何解决?

0 个答案:

没有答案