Качество модели существенно зависит от размера партии: это нормально или проблема с моими функциями потерь? - PullRequest
0 голосов
/ 06 августа 2020

Я использую определенные ниже пользовательские функции потерь (dice_loss и pixelwise_weighted_binary_crossentropy) для обучения U- Net двухклассной сегментации с помощью Keras.

Я думал, что понял, что они это делают, и значения, которые они возвращают - более конкретно, я ожидал, что они вернут массив потерь, как определено здесь .

Но теперь я увидел, что качество моих моделей существенно зависит от размер партии, где модель, обученная с большим размером партии, намного хуже в отношении производительности для каждой выборки (Примечание: здесь я рисую dice_metric; функция dice_loss, определенная ниже, равна 1 - dice_metric):

введите описание изображения здесь

Кроме того, оценка плохой модели слева с исходным размером пакета, с которым она была обучена (batch_size=180), дает мне Dice-metri c ~ 0,96, но с усреднением на выборку Показатели игры в кости (нанесенные на график) дают мне ~ 0,76.

Это наводит на мысль, что большой размер партии может «скрывать» образцы, которые недостаточно представлены в обучающем наборе. Итак, мой вопрос:

Это нормальное поведение при обучении модели?

Или: это проблема с моими функциями потерь, где они, возможно, бросают все пиксельные значения партии в одна потеря, и это скрывает недостаточно представленные наборы данных?

Я использую следующие функции потерь:

'''This is the Dice-loss as found here: https://stackoverflow.com/questions/51973856/how-is-the-smooth-dice-loss-differentiable'''

def dice_loss(y_true, y_pred):
    [masks, weights] = tf.unstack(y_true, 2, axis=-1)
    y_true = masks

    smooth = 1
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    return 1 - (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)
def pixelwise_weighted_binary_crossentropy(y_true, y_pred):
    '''
    This function implements pixel-wise weighted, binary cross-entropy
    (Important to detect the small borders between cells for segmentation)

    The code is adapted from the Keras TF backend.
    (see their github)
    '''
    try:
        # The weights are passed as part of the y_true tensor:
        [seg, weight] = tf.unstack(y_true, 2, axis=-1)  # unpack segmentation GT and weights

        seg = tf.expand_dims(seg, -1)  # add dimension at end
        weight = tf.expand_dims(weight, -1)  # add dimension at end
    except:
        pass

    epsilon = tf.convert_to_tensor(K.epsilon(), y_pred.dtype.base_dtype)  # create epsilon tensor
    y_pred = tf.clip_by_value(y_pred, epsilon, 1. - epsilon)  # clip values to range [epsilon, 1-epsilon]
    y_pred = math_ops.log(y_pred / (1 - y_pred))  # calculate Logits

    zeros = array_ops.zeros_like(y_pred, dtype=y_pred.dtype)
    cond = (y_pred >= zeros)  # setup condition for ReLU non-linearity
    relu_logits = math_ops.select(cond, y_pred, zeros)  # set y_pred for True, zero for False
    neg_abs_logits = math_ops.select(cond, -y_pred, y_pred)  # get negative absolute value
    entropy = math_ops.add(relu_logits - y_pred * seg, math_ops.log1p(math_ops.exp(neg_abs_logits)), name=None)  # tf.math.log1p(x) := ln(1+x) element-wise

    return K.mean(math_ops.multiply(weight, entropy), axis=-1)  # apply weights and average to obtain final over the entropy
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...