如何在 Keras 中为张量创建布尔掩码?

How do you create a boolean mask for a tensor in Keras?

我正在构建一个自定义指标来衡量训练期间我的多 class 数据集中一个 class 的准确性。我在选择 class 时遇到问题。

目标是一个热点(例如:class 0 标签是 [1 0 0 0 0]):

from keras import backend as K

def single_class_accuracy(y_true, y_pred):
    idx = bool(y_true[:, 0])              # boolean mask for class 0 
    class_preds = y_pred[idx]
    class_true = y_true[idx]
    class_acc = K.mean(K.equal(K.argmax(class_true, axis=-1), K.argmax(class_preds, axis=-1)))  # multi-class accuracy  
    return class_acc

麻烦的是,我们必须使用 Keras 函数来索引张量。如何为张量创建布尔掩码?

请注意,在谈论一个 class 的 准确度 时,可能指的是以下两个量之一(不等价):

  • recall,对于classC,是标有class的样本比例C 预测有 class C.
  • 精度,其中,对于class C,是预测为[=45的示例的比率=] C 实际上标有 class C.

您无需进行复杂的索引,只需依靠掩码进行计算即可。假设我们在这里谈论精度(改为召回率是微不足道的)。

from keras import backend as K

INTERESTING_CLASS_ID = 0  # Choose the class of interest

def single_class_accuracy(y_true, y_pred):
    class_id_true = K.argmax(y_true, axis=-1)
    class_id_preds = K.argmax(y_pred, axis=-1)
    # Replace class_id_preds with class_id_true for recall here
    accuracy_mask = K.cast(K.equal(class_id_preds, INTERESTING_CLASS_ID), 'int32')
    class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * accuracy_mask
    class_acc = K.sum(class_acc_tensor) / K.maximum(K.sum(accuracy_mask), 1)
    return class_acc

如果你想更灵活,你也可以将class感兴趣的参数化:

from keras import backend as K

def single_class_accuracy(interesting_class_id):
    def fn(y_true, y_pred):
        class_id_true = K.argmax(y_true, axis=-1)
        class_id_preds = K.argmax(y_pred, axis=-1)
        # Replace class_id_preds with class_id_true for recall here
        accuracy_mask = K.cast(K.equal(class_id_preds, interesting_class_id), 'int32')
        class_acc_tensor = K.cast(K.equal(class_id_true, class_id_preds), 'int32') * accuracy_mask
        class_acc = K.sum(class_acc_tensor) / K.maximum(K.sum(accuracy_mask), 1)
        return class_acc
    return fn

并将其用作:

model.compile(..., metrics=[single_class_accuracy(INTERESTING_CLASS_ID)])