Вывод softmax делает вывод двоичной кросс-энтропии NAN, что мне делать?

Я реализовал нейронную сеть в Tensorflow, где последний слой является сверточным слоем, я передаю вывод этого сверточного слоя в функцию активации softmax, а затем передаю его в функцию потери кросс-энтропии, которая определяется следующим образом вместе с метками но проблема в том, что я получил NAN как результат моей функции потерь, и я понял, что это потому, что у меня 1 на выходе softmax. Итак, у меня вопрос: что мне делать в этом случае? Мой вход - изображение 16 на 16, где у меня есть 0 и 1 в качестве значений каждого пикселя (двоичная классификация)

Моя функция потерь:

#Loss function
def loss(prediction, label):
    #with tf.variable_scope("Loss") as Loss_scope:
    log_pred = tf.log(prediction, name='Prediction_Log')
    log_pred_2 = tf.log(1-prediction, name='1-Prediction_Log')
    cross_entropy = -tf.multiply(label, log_pred) - tf.multiply((1-label), log_pred_2) 

    return cross_entropy

person MRM    schedule 21.06.2019    source источник
comment
Вам следует использовать tf.nn.softmax_cross_entropy_with_logits_v2 или _ 2_ для этого, используя выходные данные последнего уровня перед активацией softmax ( логиты). Эти функции предназначены для правильной обработки крайних случаев.   -  person jdehesa    schedule 21.06.2019
comment
@jdehesa Хорошее замечание! :-) Я действительно должен был включить в свой ответ указатель на нестандартные функции. Я предположил, что вопрос OP был о реализации ее собственных потерь fn   -  person Stewart_R    schedule 21.06.2019
comment
обновленный ответ теперь с примечанием о готовых функциях, прекрасно справляющихся с этим   -  person Stewart_R    schedule 21.06.2019
comment
@ jdehesa, я уже пробовал их (без softmax, как говорится в документации), но проблема в том, что мои потери равны нулю, поэтому моя модель не обучается.   -  person MRM    schedule 22.06.2019


Ответы (1)


Обратите внимание, что log(0) не определено, поэтому, если когда-либо prediction==0 или prediction==1 у вас будет NaN.

Чтобы обойти это, обычно добавляют очень маленькое значение epsilon к значению, переданному в tf.log в любой функции потерь (мы также делаем то же самое при делении, чтобы избежать деления на ноль). Это делает нашу функцию потерь численно стабильной, а эпсилон-значение достаточно малым, чтобы им можно было пренебречь с точки зрения любой неточности, которую оно вносит в наши потери.

Возможно, попробуйте что-нибудь вроде:

#Loss function
def loss(prediction, label):
    #with tf.variable_scope("Loss") as Loss_scope:

    epsilon = tf.constant(0.000001)
    log_pred = tf.log(prediction + epsilon, name='Prediction_Log')
    log_pred_2 = tf.log(1-prediction + epsilon, name='1-Prediction_Log')

    cross_entropy = -tf.multiply(label, log_pred) - tf.multiply((1-label), log_pred_2) 
    return cross_entropy

ОБНОВИТЬ:

Однако, как указывает jdehesa в своих комментариях, «нестандартные» функции потерь уже прекрасно справляются с проблемой числовой стабильности.

person Stewart_R    schedule 21.06.2019