为啥在 Keras 度量函数中使用 axis=-1?

Posted

技术标签:

【中文标题】为啥在 Keras 度量函数中使用 axis=-1?【英文标题】:Why use axis=-1 in Keras metrics function?为什么在 Keras 度量函数中使用 axis=-1? 【发布时间】:2018-02-28 02:26:09 【问题描述】:

keras 版本:2.0.8

在某些 Keras 度量函数和损失函数中,使用 axis=-1 作为参数。

例如:

def binary_accuracy(y_true, y_pred):
    return K.mean(K.equal(y_true, K.round(y_pred)), axis=-1)

就我而言:

y_true 的形状:(4,256,256,2)

y_pred 的形状:(4,256,256,2)

因此,binary_accuracy(y_true, y_pred) 应该返回一个 shape=(4,256,256) 的张量,而不是一个标量张量。

但是当使用 binary_accuracy 作为度量函数时:

model.compile(optimizer=adam, loss=keras.losses.binary_crossentropy, metrics=[binary_accuracy])

日志仍然将 binary_accuracy 打印为标量,这让我很困惑。

keras 对 binary_accuracy 函数的返回有什么特别的吗?

11/300 纪元

0s - 损失:0.4158 - binary_accuracy:0.9308 - val_loss:0.4671 - val_binary_accuracy: 0.7767

【问题讨论】:

为什么你认为二进制精度应该返回张量而不是标量? 因为函数是以返回张量的方式实现的。将张量转换为标量的步骤隐藏在其他地方。 @MatiasValdenegro 根据 binary_accuracy 函数,它应该返回一个 shape=(4,256,256) 的张量(不是标量张量)。我测试它,它是真的。 @DanielMöller 当然,但是日志总是会打印一个标量,这让我很困惑。 【参考方案1】:

这就是您要查找的内容,在 training_utils.py 内:

def weighted(y_true, y_pred, weights, mask=None):
    """Wrapper function.
    # Arguments
        y_true: `y_true` argument of `fn`.
        y_pred: `y_pred` argument of `fn`.
        weights: Weights tensor.
        mask: Mask tensor.
    # Returns
        Scalar tensor.
    """
    # score_array has ndim >= 2
    score_array = fn(y_true, y_pred)
    if mask is not None:
        # Cast the mask to floatX to avoid float64 upcasting in Theano
        mask = K.cast(mask, K.floatx())
        # mask should have the same shape as score_array
        score_array *= mask
        #  the loss per batch should be proportional
        #  to the number of unmasked samples.
        score_array /= K.mean(mask) + K.epsilon()

    # apply sample weighting
    if weights is not None:
        # reduce score_array to same ndim as weight array
        ndim = K.ndim(score_array)
        weight_ndim = K.ndim(weights)
        score_array = K.mean(score_array,
                             axis=list(range(weight_ndim, ndim)))
        score_array *= weights
        score_array /= K.mean(K.cast(K.not_equal(weights, 0), K.floatx()))
    return K.mean(score_array)
return weighted

度量函数由score_array = fn(y_true, y_pred) 调用(它是一个嵌套函数,fn 在外部函数中定义)。该数组在最后一行 return K.mean(score_array) 中取平均值。这就是为什么您看到的是标量指标而不是张量。中间的线条只是在必要时引入掩码和权重。

【讨论】:

这个回复解释了为什么只取最后一个轴的平均值是可以的,但我仍然不确定为什么设计是这样的。听起来平均值是稍后才取的,那么为什么要在损失函数中取axis=-1的平均值呢?在损失函数定义中不取均值不是更有效吗?

以上是关于为啥在 Keras 度量函数中使用 axis=-1?的主要内容,如果未能解决你的问题,请参考以下文章

Keras-Tuner:是不是可以在目标/度量函数中使用测试/验证集?

Keras 中的损失函数和度量有啥区别? [复制]

tf.keras中度量和损失MSE之间的差异[重复]

keras.argmax中axis=-1是啥意思?

Keras:批量标准化(axis = 1)的等级为0

:keras中的损失函数之BinaryCrossentropy详解