keras后端的K.sum中axis = [1,2,3]是什么意思?

时间:2019-01-10 10:18:59

标签: python tensorflow keras conv-neural-network

我正在尝试为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函数的作用是什么?

2 个答案:

答案 0 :(得分: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。由于axis参数是(1, 2, 3),因此至少需要4个轴才能使操作有效。尝试将变量更改为val1 = np.arange(24).reshape((2, 2, 2, 3))之类的东西,一切正常。

该模型似乎可以计算二进制交叉熵骰子损失,而dice_coeff()可以计算出Dice coefficient。我不确定smooth的目的是什么,但是如果它是为了避免被0除,那么您会期望会有一个很小的数字,例如1e-6。

答案 1 :(得分:1)

  

什么是[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函数的作用是什么?

enter image description here

请参阅here,以获取有关dice_coef的完整说明。