Что означает ось = [1,2,3] в K.sum в бэкэнде keras? - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь реализовать пользовательскую функцию потерь для моей модели CNN. Я нашел ноутбук IPython , в котором реализована пользовательская функция потерь с именем 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 backend и действительно путаюсь с матричными вычислениями keras backend. Итак, я создал несколько тензоров, чтобы увидеть, что происходит в коде:

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 голосов
/ 10 января 2019

Что такое [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.

Что делает эта функция dice_coef?

enter image description here

См. здесь для полного объяснения dice_coef.

0 голосов
/ 10 января 2019

Так же, как в 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(), как следует из названия, вычисляет Коэффициент костей . Я не уверен, какова цель smooth, но если бы это было с целью избежать деления на 0, вы бы ожидали небольшого числа, например 1e-6.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...