【问题标题】:What does axis=[1,2,3] mean in K.sum in keras backend?在keras后端的K.sum中axis = [1,2,3]是什么意思?
【发布时间】:2019-06-05 04:35:08
【问题描述】:

我正在尝试为我的 CNN 模型实现自定义损失函数。我找到了一个IPython notebook,它实现了一个名为Dice的自定义损失函数,如下:

from keras import backend as K
smooth = 1.

def dice_coef(y_true, y_pred, smooth=1):
    intersection = K.sum(y_true * y_pred, axis=[1,2,3])
    union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
    return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)

def bce_dice(y_true, y_pred):
    return binary_crossentropy(y_true, y_pred)-K.log(dice_coef(y_true, y_pred))

def true_positive_rate(y_true, y_pred):
    return K.sum(K.flatten(y_true)*K.flatten(K.round(y_pred)))/K.sum(y_true)

seg_model.compile(optimizer = 'adam', 
              loss = bce_dice, 
              metrics = ['binary_accuracy', dice_coef, true_positive_rate])

我以前从未使用过 keras 后端,并且对 keras 后端的矩阵计算感到困惑。所以,我创建了一些张量来查看代码中发生了什么:

val1 = np.arange(24).reshape((4, 6))
y_true = K.variable(value=val1)

val2 = np.arange(10,34).reshape((4, 6))
y_pred = K.variable(value=val2)

现在我运行dice_coef 函数:

result = K.eval(dice_coef(y_true=y_true, y_pred=y_pred))
print('result is:', result)

但它给了我这个错误:

ValueError: Invalid reduction dimension 2 for input with 2 dimensions. for 'Sum_32' (op: 'Sum') with input shapes: [4,6], [3] and with computed input tensors: input[1] = <1 2 3>.

然后我将所有[1,2,3] 更改为-1,如下所示:

def dice_coef(y_true, y_pred, smooth=1):
    intersection = K.sum(y_true * y_pred, axis=-1)
    # intersection = K.sum(y_true * y_pred, axis=[1,2,3])
    # union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
    union = K.sum(y_true, axis=-1) + K.sum(y_pred, axis=-1)
    return K.mean( (2. * intersection + smooth) / (union + smooth), axis=0)

现在它给了我一个价值。

result is: 14.7911625

问题:

  1. 什么是[1,2,3]
  2. 为什么当我将[1,2,3] 更改为-1 时代码有效?
  3. dice_coef 函数有什么作用?

【问题讨论】:

  • [1,2,3] 表示求和(视为聚合操作)穿过张量的第二到第四轴。
  • 同样axis=-1 in sum 表示总和在最后一个轴上运行。

标签: python tensorflow keras conv-neural-network


【解决方案1】:

就像在 numpy 中一样,你可以定义你想要执行某个操作的轴。例如,对于 4d 数组,我们可以像这样沿特定轴求和

>>> a = np.arange(150).reshape((2, 3, 5, 5))
>>> a.sum(axis=0).shape
(3, 5, 5)
>>> a.sum(axis=0, keepdims=True).shape
(1, 3, 5, 5)
>>> a.sum(axis=1, keepdims=True).shape
(2, 1, 5, 5)

如果我们输入一个元组,我们可以沿多个轴执行此操作。

>>> a.sum(axis=(1, 2, 3), keepdims=True).shape
(2, 1, 1, 1)

如果参数为-1,则默认在最后一个轴上执行操作,不管有多少。

>>> a.sum(axis=-1, keepdims=True).shape
(2, 3, 5, 1)

这应该澄清了第 1 点和第 2 点。由于轴参数是(1, 2, 3),因此您需要至少 4 个轴才能使操作有效。尝试将变量更改为 val1 = np.arange(24).reshape((2, 2, 2, 3)) 之类的东西,一切正常。

该模型似乎计算了二元交叉熵骰子损失,而dice_coeff(),顾名思义,计算了Dice coefficient。我不确定smooth 的目的是什么,但如果它是为了避免除以 0,你会期望一个很小的数字,比如 1e-6。

【讨论】:

    【解决方案2】:

    什么是[1,2,3]?

    这些数字指定我们要对哪个维度进行求和。最小的数字显示外部尺寸,最大的数字显示内部尺寸。看例子:

    import tensorflow as tf
    
    tf.enable_eager_execution()
    
        a = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    
        print(tf.reduce_sum(a, axis=2).numpy())
        #[[ 3  7]
        # [11 15]]
        print(tf.reduce_sum(a, axis=1).numpy())
        #[[ 4  6]
        # [12 14]]
        print(tf.reduce_sum(a, axis=0).numpy())
        #[[ 6  8]
        # [10 12]]
    

    在上面的示例中,axis = 2 表示内部条目,它们是:[1,2]、[3,4]、[5,6] 和 [7,8]。结果,求和后,我们得到了张量:[[3, 7], [11, 15]]。同样的想法也适用于其他轴。

    为什么当我将 [1,2,3] 更改为 -1 时代码有效

    当我们没有指定任何轴或另一方面指定所有轴时,意味着我们对所有张量元素求和。这导致我们的张量转换为单个标量。见例子:

    a = tf.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    print(tf.reduce_sum(a).numpy()) # 36
    print(tf.reduce_sum(a, axis=[0,1,2])) # 36
    

    如果我们有 3 维 [0, 1, 2],axis = -1 等于 axis = 2。有关 python 索引的完整教程,请参阅here

    这个 dice_coef 函数有什么作用?

    有关 dice_coef 的完整说明,请参阅 here

    【讨论】:

      【解决方案3】:

      您问题的前两部分已经解释过了。我会解释最后一个。

      • 这个 dice_coef 函数有什么作用?

      dice_coef 函数是计算骰子相似度系数,是一个损失函数。我将解释图像分割任务的上下文,所以骰子相似度系数是衡量两个轮廓重叠程度的指标。

      img Source: Coursera

      取值范围从0到1。

      • 0 表示完全不匹配,即它们根本不重叠
      • 1 表示完美匹配,即它们完全重叠

      一般来说,对于两个集合A和B,Dice相似系数定义为:

      DSC(A,B)=( 2 × |A ∩ B| ) / ( |A|+|B| )。

      为了避免被零除 ϵ 是一个很小的数字

      DSC(A,B)= ( 2 × |A ∩ B| + ϵ ) / ( |A| + |B|+ ϵ )。

      在你的情况下:

      • A 是 y_true

      • B 是 y_pred

      • ϵ 是平滑的

      【讨论】:

        猜你喜欢
        • 2018-05-06
        • 2020-08-30
        • 1970-01-01
        • 2019-02-27
        • 1970-01-01
        • 1970-01-01
        • 2019-11-05
        • 2020-01-21
        • 2018-04-24
        相关资源
        最近更新 更多